def get_acl(account_name, headers): """ Attempts to construct an Oss ACL based on what is found in the swift headers """ elem = Element('AccessControlPolicy') owner = SubElement(elem, 'Owner') SubElement(owner, 'ID').text = account_name SubElement(owner, 'DisplayName').text = account_name access_control_list = SubElement(elem, 'AccessControlList') # grant FULL_CONTROL to myself by default referrers, _ = parse_acl(headers.get('x-container-read')) if referrer_allowed('unknown', referrers): # grant public-read access SubElement(access_control_list, 'Grant').text = 'PUBLIC-READ' referrers, _ = parse_acl(headers.get('x-container-write')) if referrer_allowed('unknown', referrers): # grant public-write access SubElement(access_control_list, 'Grant').text = 'PUBLIC-READ-WRITE' body = tostring(elem) return HTTPOk(body=body, content_type="text/plain")
def extract_acl_and_report_errors(self, req): """ Return a user-readable string indicating the errors in the input ACL, or None if there are no errors. """ acl_header = 'x-account-access-control' acl_data = req.headers.get(acl_header) result = parse_acl(version=2, data=acl_data) if result is None: return 'Syntax error in input (%r)' % acl_data tempauth_acl_keys = 'admin read-write read-only'.split() for key in result: # While it is possible to construct auth systems that collaborate # on ACLs, TempAuth is not such an auth system. At this point, # it thinks it is authoritative. if key not in tempauth_acl_keys: return 'Key %r not recognized' % key for key in tempauth_acl_keys: if key not in result: continue if not isinstance(result[key], list): return 'Value for key %r must be a list' % key for grantee in result[key]: if not isinstance(grantee, str): return 'Elements of %r list must be strings' % key # Everything looks fine, no errors found internal_hdr = get_sys_meta_prefix('account') + 'core-access-control' req.headers[internal_hdr] = req.headers.pop(acl_header) return None
def get_s3_acl(headers, acl_headers, resource='container'): out = ['<AccessControlPolicy>'] owner_header = 'x-%s-owner' % resource headers = dict([(k.lower(), v) for k, v in headers.iteritems()]) if owner_header in headers: owner = xml_escape(headers[owner_header]) out.append('<Owner><ID>%s</ID><DisplayName>%s</DisplayName></Owner>' % (owner, owner)) out.append('<AccessControlList>') for header in acl_headers: if header in headers: permission = None if resource == 'container': # len(x-container-acl-) = 16; len(x-container-) = 12 frm = 16 if header.startswith('x-container-acl-') else 12 permission = header[frm:].upper().replace('-', '_') elif resource == 'object': # len(x-object-acl-) = 13 permission = header[13:].upper().replace('-', '_') if permission: referrers, groups = parse_acl(headers[header]) for ref in referrers: uri = AMZ_ALL_USERS if ref == '*' else ref grant = amz_group_grant(uri, permission) out.append(grant) for group in groups: grant = amz_user_grant(group, group, permission) out.append(grant) out.append('</AccessControlList></AccessControlPolicy>') body = ''.join(out) return Response(body=body, content_type='application/xml', headers={'Content-Length': str(len(body))})
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant = env_identity.get('tenant') try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: return HTTPNotFound(request=req) if account != '%s_%s' % (self.reseller_prefix, tenant[0]): self.logger.debug('tenant mismatch') return self.denied_response(req) # If user is in the swift operator group then make the owner of it. user_groups = env_identity.get('roles', []) for _group in self.keystone_swift_operator_roles.split(','): _group = _group.strip() if _group in user_groups: self.logger.debug( "User is in group: %s allow him to do whatever it wants" % (_group)) req.environ['swift_owner'] = True return None # If user is of the same name of the tenant then make owner of it. user = env_identity.get('user', '') if self.keystone_tenant_user_admin and user == tenant[1]: self.logger.debug("user: %s == %s tenant and option "\ "keystone_tenant_user_admin is set" % \ (user, tenant)) req.environ['swift_owner'] = True return None # Allow container sync if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts)): self.logger.debug('allowing container-sync') return None # Check if Referrer allow it referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug('authorizing via ACL') return None return self.denied_response(req) # Check if we have the group in the usergroups and allow it for user_group in user_groups: if user_group in groups: self.logger.debug('user in group which is allowed in" \ " ACL: %s authorizing' % (user_group)) return None # last but not least retun deny return self.denied_response(req)
def authorize(self, req): """ add by colony. stolen from swauth """ try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: return HTTPNotFound(request=req) if not account: return self.denied_response(req) user_groups = (req.remote_user or '').split(',') # authority of admin. if account in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): req.environ['swift_owner'] = True return None # authority of normal. if hasattr(req, 'acl'): referrers, groups = parse_acl(req.acl) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: return None return self.denied_response(req) if not req.remote_user: return self.denied_response(req) for user_group in user_groups: if user_group in groups: return None return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: return HTTPNotFound(request=req) if not account or not account.startswith(self.reseller_prefix): return self.denied_response(req) user_groups = (req.remote_user or '').split(',') if '.reseller_admin' in user_groups: return None if account in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): # If the user is admin for the account and is not trying to do an # account DELETE or PUT... return None referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): return None if not req.remote_user: return self.denied_response(req) for user_group in user_groups: if user_group in groups: return None return self.denied_response(req)
def authorize_anonymous(self, req): """ Authorize an anonymous request. :returns: None if authorization is granted, an error page otherwise. """ try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) #allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return is_authoritative_authz = (account and account.startswith(self.reseller_prefix)) if not is_authoritative_authz: return self.denied_response(req) referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) authorized = self._authorize_unconfirmed_identity(req, obj, referrers, roles) if not authorized: return self.denied_response(req)
def extract_acl_and_report_errors(self, req): """ Return a user-readable string indicating the errors in the input ACL, or None if there are no errors. """ acl_header = 'x-account-access-control' acl_data = req.headers.get(acl_header) result = parse_acl(version=2, data=acl_data) if result is None: return 'Syntax error in input (%r)' % acl_data tempauth_acl_keys = 'admin read-write read-only'.split() for key in result: # While it is possible to construct auth systems that collaborate # on ACLs, TempAuth is not such an auth system. At this point, # it thinks it is authoritative. if key not in tempauth_acl_keys: return "Key '%s' not recognized" % key for key in tempauth_acl_keys: if key not in result: continue if not isinstance(result[key], list): return "Value for key '%s' must be a list" % key for grantee in result[key]: if not isinstance(grantee, six.string_types): return "Elements of '%s' list must be strings" % key # Everything looks fine, no errors found internal_hdr = get_sys_meta_prefix('account') + 'core-access-control' req.headers[internal_hdr] = req.headers.pop(acl_header) return None
def test_parse_v2_acl(self): # For all these tests, the header name will be "hdr". tests = [ # Simple case: all ACL data in one header line ({'hdr': '{"a":1,"b":"foo"}'}, {'a': 1, 'b': 'foo'}), # No header "hdr" exists -- should return None ({}, None), ({'junk': 'junk'}, None), # Empty ACLs should return empty dict ({'hdr': ''}, {}), ({'hdr': '{}'}, {}), ({'hdr': '{ }'}, {}), # Bad input -- should return None ({'hdr': '["array"]'}, None), ({'hdr': 'null'}, None), ({'hdr': '"some_string"'}, None), ({'hdr': '123'}, None), ] for hdrs_in, expected in tests: result = acl.parse_acl(version=2, data=hdrs_in.get('hdr')) self.assertEquals(expected, result, '%r: %r != %r' % (hdrs_in, result, expected))
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant = env_identity.get('tenant') try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: return HTTPNotFound(request=req) if account != '%s_%s' % (self.reseller_prefix, tenant[0]): self.logger.debug('tenant mismatch: %s != %s_%s' % \ (account, self.reseller_prefix, tenant[0])) return self.denied_response(req) # If user is in the swift operator group then make the owner of it. user_groups = env_identity.get('roles', []) for _group in self.keystone_swift_operator_roles.split(','): _group = _group.strip() if _group in user_groups: self.logger.debug("User is in group: %s allows" % (_group)) req.environ['swift_owner'] = True return None # If user is of the same name of the tenant then make owner of it. user = env_identity.get('user', '') if self.keystone_tenant_user_admin and user == tenant[1]: self.logger.debug("user: %s == %s tenant and option "\ "keystone_tenant_user_admin is set" % \ (user, tenant)) req.environ['swift_owner'] = True return None # Allow container sync if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get( 'x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts)): self.logger.debug('allowing container-sync') return None # Check if Referrer allow it referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug('authorizing via ACL') return None return self.denied_response(req) # Check if we have the group in the usergroups and allow it for user_group in user_groups: if user_group in groups: self.logger.debug('user in group which is allowed in" \ " ACL: %s authorizing' % (user_group)) return None # last but not least retun deny return self.denied_response(req)
def test_parse_v2_acl(self): # For all these tests, the header name will be "hdr". tests = [ # Simple case: all ACL data in one header line ({'hdr': '{"a":1,"b":"foo"}'}, {'a': 1, 'b': 'foo'}), # No header "hdr" exists -- should return None ({}, None), ({'junk': 'junk'}, None), # Empty ACLs should return empty dict ({'hdr': ''}, {}), ({'hdr': '{}'}, {}), ({'hdr': '{ }'}, {}), # Bad input -- should return None ({'hdr': '["array"]'}, None), ({'hdr': 'null'}, None), ({'hdr': '"some_string"'}, None), ({'hdr': '123'}, None), ] for hdrs_in, expected in tests: result = acl.parse_acl(version=2, data=hdrs_in.get('hdr')) self.assertEqual(expected, result, '%r: %r != %r' % (hdrs_in, result, expected))
def authorize_anonymous(self, req): """ Authorize an anonymous request. :returns: None if authorization is granted, an error page otherwise. """ try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) # allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return is_authoritative_authz = (account and (self._get_account_prefix(account) in self.reseller_prefixes)) if not is_authoritative_authz: return self.denied_response(req) referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) authorized = self._authorize_unconfirmed_identity( req, obj, referrers, roles) if not authorized: return self.denied_response(req)
def add_acls_from_sys_metadata(self, resp): if resp.environ["REQUEST_METHOD"] in ("HEAD", "GET", "PUT", "POST"): prefix = get_sys_meta_prefix("account") + "core-" name = "access-control" (extname, intname) = ("x-account-" + name, prefix + name) acl_dict = parse_acl(version=2, data=resp.headers.pop(intname)) if acl_dict: # treat empty dict as empty header resp.headers[extname] = format_acl(version=2, acl_dict=acl_dict)
def add_acls_from_sys_metadata(self, resp): if resp.environ['REQUEST_METHOD'] in ('HEAD', 'GET', 'PUT', 'POST'): prefix = get_sys_meta_prefix('account') + 'core-' name = 'access-control' (extname, intname) = ('x-account-' + name, prefix + name) acl_dict = parse_acl(version=2, data=resp.headers.pop(intname)) if acl_dict: # treat empty dict as empty header resp.headers[extname] = format_acl(version=2, acl_dict=acl_dict)
def add_acls_from_sys_metadata(self, resp): if resp.environ['REQUEST_METHOD'] in ('HEAD', 'GET', 'PUT', 'POST'): prefix = get_sys_meta_prefix('account') + 'core-' name = 'access-control' (extname, intname) = ('x-account-' + name, prefix + name) acl_dict = parse_acl(version=2, data=resp.headers.pop(intname)) if acl_dict: # treat empty dict as empty header resp.headers[extname] = format_acl( version=2, acl_dict=acl_dict)
def authorize(self, req): env = req.environ identity = env.get('cloudstack.identity', {}) try: version, _account, container, obj = split_path(req.path, minsegs=1, maxsegs=4, rest_with_last=True) except ValueError: return HTTPNotFound(request=req) if not _account or not _account.startswith(self.reseller_prefix): return self.denied_response(req) # Remove the reseller_prefix from the account. if self.reseller_prefix != '': account = _account[len(self.reseller_prefix) + 1:] else: account = _account user_roles = identity.get('roles', []) # If this user is part of this account or is the global admin, give access. if account == identity.get( 'account') or self.cs_roles[1] in user_roles: req.environ['swift_owner'] = True return None # Allow container sync if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get( 'x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts)): self.logger.debug('Allowing container-sync') return None # Check if Referrer allow it referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug('Authorizing via ACL') return None return self.denied_response(req) # Check if we have the group in the user_roles and allow if we do for role in user_roles: if role in groups: self.logger.debug('User has role %s, allowing via ACL' % (role)) return None # This user is not authorized, deny request. return self.denied_response(req)
def get_acl(account_name, headers): """ Attempts to construct an S3 ACL based on what is found in the swift headers """ elem = Element('AccessControlPolicy') owner = SubElement(elem, 'Owner') SubElement(owner, 'ID').text = account_name SubElement(owner, 'DisplayName').text = account_name access_control_list = SubElement(elem, 'AccessControlList') # grant FULL_CONTROL to myself by default grant = SubElement(access_control_list, 'Grant') grantee = SubElement(grant, 'Grantee', nsmap={'xsi': XMLNS_XSI}) grantee.set('{%s}type' % XMLNS_XSI, 'CanonicalUser') SubElement(grantee, 'ID').text = account_name SubElement(grantee, 'DisplayName').text = account_name SubElement(grant, 'Permission').text = 'FULL_CONTROL' referrers, _ = parse_acl(headers.get('x-container-read')) if referrer_allowed('unknown', referrers): # grant public-read access grant = SubElement(access_control_list, 'Grant') grantee = SubElement(grant, 'Grantee', nsmap={'xsi': XMLNS_XSI}) grantee.set('{%s}type' % XMLNS_XSI, 'Group') SubElement(grantee, 'URI').text = \ 'http://acs.amazonaws.com/groups/global/AllUsers' SubElement(grant, 'Permission').text = 'READ' referrers, _ = parse_acl(headers.get('x-container-write')) if referrer_allowed('unknown', referrers): # grant public-write access grant = SubElement(access_control_list, 'Grant') grantee = SubElement(grant, 'Grantee', nsmap={'xsi': XMLNS_XSI}) grantee.set('{%s}type' % XMLNS_XSI, 'Group') SubElement(grantee, 'URI').text = \ 'http://acs.amazonaws.com/groups/global/AllUsers' SubElement(grant, 'Permission').text = 'WRITE' body = tostring(elem) return HTTPOk(body=body, content_type="text/plain")
def authorize(self, req): env = req.environ identity = env.get('cloudstack.identity', {}) try: version, _account, container, obj = split_path(req.path, minsegs=1, maxsegs=4, rest_with_last=True) except ValueError: return HTTPNotFound(request=req) if not _account or not _account.startswith(self.reseller_prefix): return self.denied_response(req) # Remove the reseller_prefix from the account. if self.reseller_prefix != '': account = _account[len(self.reseller_prefix)+1:] else: account = _account user_roles = identity.get('roles', []) # If this user is part of this account or is the global admin, give access. if account == identity.get('account') or self.cs_roles[1] in user_roles: req.environ['swift_owner'] = True self.logger.debug("User %s is global admin or owner, authorizing" % identity.get('username')) return None # Allow container sync if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts)): self.logger.debug('Allowing container-sync') return None if req.method == 'OPTIONS': #allow OPTIONS requests to proceed as normal self.logger.debug("Allow OPTIONS request.") return None # Check if Referrer allow it referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug('Authorizing via ACL') return None return self.denied_response(req) # Check if we have the group in the user_roles and allow if we do for role in user_roles: if role in groups: self.logger.debug('User has role %s, allowing via ACL' % (role)) return None # This user is not authorized, deny request. return self.denied_response(req)
def test_parse_acl(self): self.assertEqual(acl.parse_acl(None), ([], [])) self.assertEqual(acl.parse_acl(''), ([], [])) self.assertEqual(acl.parse_acl('.r:ref1'), (['ref1'], [])) self.assertEqual(acl.parse_acl('.r:-ref1'), (['-ref1'], [])) self.assertEqual(acl.parse_acl('account:user'), ([], ['account:user'])) self.assertEqual(acl.parse_acl('account'), ([], ['account'])) self.assertEqual(acl.parse_acl('acc1,acc2:usr2,.r:ref3,.r:-ref4'), (['ref3', '-ref4'], ['acc1', 'acc2:usr2'])) self.assertEqual(acl.parse_acl( 'acc1,acc2:usr2,.r:ref3,acc3,acc4:usr4,.r:ref5,.r:-ref6'), (['ref3', 'ref5', '-ref6'], ['acc1', 'acc2:usr2', 'acc3', 'acc4:usr4']))
def test_parse_acl(self): self.assertEquals(acl.parse_acl(None), ([], [])) self.assertEquals(acl.parse_acl(''), ([], [])) self.assertEquals(acl.parse_acl('.r:ref1'), (['ref1'], [])) self.assertEquals(acl.parse_acl('.r:-ref1'), (['-ref1'], [])) self.assertEquals(acl.parse_acl('account:user'), ([], ['account:user'])) self.assertEquals(acl.parse_acl('account'), ([], ['account'])) self.assertEquals(acl.parse_acl('acc1,acc2:usr2,.r:ref3,.r:-ref4'), (['ref3', '-ref4'], ['acc1', 'acc2:usr2'])) self.assertEquals(acl.parse_acl( 'acc1,acc2:usr2,.r:ref3,acc3,acc4:usr4,.r:ref5,.r:-ref6'), (['ref3', 'ref5', '-ref6'], ['acc1', 'acc2:usr2', 'acc3', 'acc4:usr4']))
def authorize(self, req): env = req.environ identity = env.get("cloudstack.identity", {}) try: version, _account, container, obj = split_path(req.path, minsegs=1, maxsegs=4, rest_with_last=True) except ValueError: return HTTPNotFound(request=req) if not _account or not _account.startswith(self.reseller_prefix): return self.denied_response(req) # Remove the reseller_prefix from the account. if self.reseller_prefix != "": account = _account[len(self.reseller_prefix) + 1 :] else: account = _account user_roles = identity.get("roles", []) # If this user is part of this account or is the global admin, give access. if account == identity.get("account") or self.cs_roles[1] in user_roles: req.environ["swift_owner"] = True return None # Allow container sync if ( req.environ.get("swift_sync_key") and req.environ["swift_sync_key"] == req.headers.get("x-container-sync-key", None) and "x-timestamp" in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts) ): self.logger.debug("Allowing container-sync") return None # Check if Referrer allow it referrers, groups = parse_acl(getattr(req, "acl", None)) if referrer_allowed(req.referer, referrers): if obj or ".rlistings" in groups: self.logger.debug("Authorizing via ACL") return None return self.denied_response(req) # Check if we have the group in the user_roles and allow if we do for role in user_roles: if role in groups: self.logger.debug("User has role %s, allowing via ACL" % (role)) return None # This user is not authorized, deny request. return self.denied_response(req)
def authorize_colony(self, req): """ add by colony. 1. All user GET or HEAD account. 2. All user create a container. 3. All user read or write objects with no contaner acl. 4. But any user are limited by container acl if exists. """ try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: return HTTPNotFound(request=req) if not account: self.logger.info('no account') return self.denied_response(req) user_groups = (req.remote_user or '').split(',') self.logger.info('request_remote_user: %s' % req.remote_user) self.logger.info('request_method: %s' % req.method) # all user has normal authority, but 'swift_owner'. req.environ['swift_owner'] = True # Any user GET or HEAD account if req.method in ['HEAD', 'GET'] and not container: self.logger.info('HEAD or GET account all ok') return None # Any user creates container if req.method in ['PUT', 'POST', 'DELETE'] and container and not obj: self.logger.info('Any user create container') return None if hasattr(req, 'acl'): self.logger.info('container acl: %s' % req.acl) referrers, groups = parse_acl(req.acl) self.logger.info('referrers: %s' % referrers) self.logger.info('group: %s' % groups) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.info('referer_allowed') return None if not req.remote_user: return self.denied_response(req) for user_group in user_groups: if user_group in groups: self.logger.info('group_allowed: %s' % user_group) return None if not referrers and not groups: self.logger.info('no acl allow default access') return None self.logger.info('group not allowed.') return self.denied_response(req) self.logger.info('request forbidden') return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: version, account, container, obj = req.split_path(1, 4, True) except ValueError: self.logger.increment("errors") return HTTPNotFound(request=req) if not account or not account.startswith(self.reseller_prefix): return self.denied_response(req) user_groups = (req.remote_user or "").split(",") if ( ".reseller_admin" in user_groups and account != self.reseller_prefix and account[len(self.reseller_prefix)] != "." ): req.environ["swift_owner"] = True return None if account in user_groups and (req.method not in ("DELETE", "PUT") or container): # If the user is admin for the account and is not trying to do an # account DELETE or PUT... req.environ["swift_owner"] = True return None if ( req.environ.get("swift_sync_key") and (req.environ["swift_sync_key"] == req.headers.get("x-container-sync-key", None)) and "x-timestamp" in req.headers ): return None if req.method == "OPTIONS": # allow OPTIONS requests to proceed as normal return None referrers, groups = parse_acl(getattr(req, "acl", None)) if referrer_allowed(req.referer, referrers): if obj or ".rlistings" in groups: return None return self.denied_response(req) if not req.remote_user: return self.denied_response(req) for user_group in user_groups: if user_group in groups: return None return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not account or not account.startswith(self.reseller_prefix): return self.denied_response(req) user_groups = (req.remote_user or '').split(',') if '.reseller_admin' in user_groups and \ account != self.reseller_prefix and \ account[len(self.reseller_prefix)] != '.': req.environ['swift_owner'] = True return None if account in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): # If the user is admin for the account and is not trying to do an # account DELETE or PUT... req.environ['swift_owner'] = True return None if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts)): return None if req.method == 'OPTIONS': #allow OPTIONS requests to proceed as normal return None referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: return None return self.denied_response(req) if not req.remote_user: return self.denied_response(req) for user_group in user_groups: if user_group in groups: return None return self.denied_response(req)
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant = env_identity.get('tenant') try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: return HTTPNotFound(request=req) if account != '%s_%s' % (self.reseller_prefix, tenant): self.logger.debug('tenant mismatch: %s != %s_%s' % \ (account, self.reseller_prefix, tenant)) return self.denied_response(req) user_groups = env_identity.get('roles', []) #TODO: setting? if self.keystone_admin_group in user_groups: req.environ['swift_owner'] = True return None if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts)): self.logger.debug('allowing container-sync') return None # Check if Referrer allow it #TODO: check if it works referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug('authorizing via ACL') return None return self.denied_response(req) # Check if we have the group in the group user and allow it for user_group in user_groups: if user_group in groups: self.logger.debug('user in group: %s authorizing' % \ (user_group)) return None return self.denied_response(req)
def get_target(self, environ): req = Request(environ) try: parts = req.split_path(1, 4, True) version, account, container, obj = parts except ValueError: version = account = container = obj = None referrers, acls = swift_acl.parse_acl(getattr(req, 'acl', None)) target = { "req": req, "method": req.method.lower(), "version": version, "account": account, "container": container, "object": obj, "acls": acls, "referrers": referrers } return target
def authorize_anonymous(self, req): """ Authorize an anonymous request. :returns: None if authorization is granted, an error page otherwise. """ try: part = swift_utils.split_path(req.path, 1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) is_authoritative_authz = account and account.startswith(self.reseller_prefix) if not is_authoritative_authz: return self.denied_response(req) referrers, roles = swift_acl.parse_acl(getattr(req, "acl", None)) authorized = self._authorize_unconfirmed_identity(req, obj, referrers, roles) if not authorized: return self.denied_response(req)
def authorize(self, req): env = req.environ identity = env.get('mauth.identity', {}) try: version, _account, container, obj = split_path(req.path, minsegs=1, maxsegs=4, rest_with_last=True) except ValueError: return HTTPNotFound(request=req) if not _account or not _account.startswith(self.reseller_prefix): return self.denied_response(req) user_roles = identity.get('roles', []) # If this user is part of this account, give access. if _account == identity.get('account_part'): req.environ['swift_owner'] = True return None # Allow container sync if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or get_remote_client(req) in self.allowed_sync_hosts)): self.logger.debug('Allowing container-sync') return None # Check if Referrer allow it referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug('Authorizing via ACL') return None return self.denied_response(req) # Check if we have the group in the user_roles and allow if we do for role in user_roles: if role in groups: self.logger.debug('User has role %s, allowing via ACL' % (role)) return None # This user is not authorized, deny request. return self.denied_response(req)
def authorize_anonymous(self, req): """ Authorize an anonymous request. :returns: None if authorization is granted, an error page otherwise. """ try: part = swift_utils.split_path(req.path, 1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) is_authoritative_authz = (account and account.startswith(self.reseller_prefix)) if not is_authoritative_authz: return self.denied_response(req) referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) authorized = self._authorize_unconfirmed_identity( req, obj, referrers, roles) if not authorized: return self.denied_response(req)
def test_parse_v2_acl(self): # For all these tests, the header name will be "hdr". tests = [ # Simple case: all ACL data in one header line ({ 'hdr': '{"a":1,"b":"foo"}' }, { 'a': 1, 'b': 'foo' }), # No header "hdr" exists -- should return None ({}, None), ({ 'junk': 'junk' }, None), ] for hdrs_in, expected in tests: result = acl.parse_acl(version=2, data=hdrs_in.get('hdr')) self.assertEquals(expected, result, '%r: %r != %r' % (hdrs_in, result, expected))
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant_id, tenant_name = env_identity.get('tenant') user = env_identity.get('user', '') referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) #allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) user_roles = env_identity.get('roles', []) # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg % tenant_id) req.environ['swift_owner'] = True return # cross-tenant authorization if self._authorize_cross_tenant(user, tenant_id, tenant_name, roles): log_msg = 'user %s:%s, %s:%s, or *:%s allowed in ACL authorizing' self.logger.debug(log_msg % (tenant_name, user, tenant_id, user, user)) return acl_authorized = self._authorize_unconfirmed_identity(req, obj, referrers, roles) if acl_authorized: return # Check if a user tries to access an account that does not match their # token if not self._reseller_check(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' % (account, tenant_id) self.logger.debug(log_msg) return self.denied_response(req) # Check the roles the user is belonging to. If the user is # part of the role defined in the config variable # operator_roles (like admin) then it will be # promoted as an admin of the account/tenant. for role in self.operator_roles.split(','): role = role.strip() if role in user_roles: log_msg = 'allow user with role %s as account admin' % (role) self.logger.debug(log_msg) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. if self.is_admin and user == tenant_name: self.logger.warning("the is_admin feature has been deprecated " "and will be removed in the future " "update your config file") req.environ['swift_owner'] = True return if acl_authorized is not None: return self.denied_response(req) # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in roles: log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg % (tenant_name, user, user_role)) return return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: _junk, account, container, obj = req.split_path(1, 4, True) except ValueError: self.logger.increment("errors") return HTTPNotFound(request=req) if self._get_account_prefix(account) is None: self.logger.debug( "Account name: %s doesn't start with " "reseller_prefix(s): %s." % (account, ",".join(self.reseller_prefixes)) ) return self.denied_response(req) # At this point, TempAuth is convinced that it is authoritative. # If you are sending an ACL header, it must be syntactically valid # according to TempAuth's rules for ACL syntax. acl_data = req.headers.get("x-account-access-control") if acl_data is not None: error = self.extract_acl_and_report_errors(req) if error: msg = "X-Account-Access-Control invalid: %s\n\nInput: %s\n" % (error, acl_data) headers = [("Content-Type", "text/plain; charset=UTF-8")] return HTTPBadRequest(request=req, headers=headers, body=msg) user_groups = (req.remote_user or "").split(",") account_user = user_groups[1] if len(user_groups) > 1 else None if ( ".reseller_admin" in user_groups and account not in self.reseller_prefixes and not self._dot_account(account) ): req.environ["swift_owner"] = True self.logger.debug("User %s has reseller admin authorizing." % account_user) return None if account in user_groups and (req.method not in ("DELETE", "PUT") or container): # The user is admin for the account and is not trying to do an # account DELETE or PUT account_prefix = self._get_account_prefix(account) require_group = self.account_rules.get(account_prefix).get("require_group") if require_group and require_group in user_groups: req.environ["swift_owner"] = True self.logger.debug("User %s has admin and %s group." " Authorizing." % (account_user, require_group)) return None elif not require_group: req.environ["swift_owner"] = True self.logger.debug("User %s has admin authorizing." % account_user) return None if ( req.environ.get("swift_sync_key") and (req.environ["swift_sync_key"] == req.headers.get("x-container-sync-key", None)) and "x-timestamp" in req.headers ): self.logger.debug("Allow request with container sync-key: %s." % req.environ["swift_sync_key"]) return None if req.method == "OPTIONS": # allow OPTIONS requests to proceed as normal self.logger.debug("Allow OPTIONS request.") return None referrers, groups = parse_acl(getattr(req, "acl", None)) if referrer_allowed(req.referer, referrers): if obj or ".rlistings" in groups: self.logger.debug("Allow authorizing %s via referer ACL." % req.referer) return None for user_group in user_groups: if user_group in groups: self.logger.debug("User %s allowed in ACL: %s authorizing." % (account_user, user_group)) return None # Check for access via X-Account-Access-Control acct_acls = self.account_acls(req) if acct_acls: # At least one account ACL is set in this account's sysmeta data, # so we should see whether this user is authorized by the ACLs. user_group_set = set(user_groups) if user_group_set.intersection(acct_acls["admin"]): req.environ["swift_owner"] = True self.logger.debug("User %s allowed by X-Account-Access-Control" " (admin)" % account_user) return None if user_group_set.intersection(acct_acls["read-write"]) and (container or req.method in ("GET", "HEAD")): # The RW ACL allows all operations to containers/objects, but # only GET/HEAD to accounts (and OPTIONS, above) self.logger.debug("User %s allowed by X-Account-Access-Control" " (read-write)" % account_user) return None if user_group_set.intersection(acct_acls["read-only"]) and req.method in ("GET", "HEAD"): self.logger.debug("User %s allowed by X-Account-Access-Control" " (read-only)" % account_user) return None return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: _junk, account, container, obj = req.split_path(1, 4, True) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if self._get_account_prefix(account) is None: self.logger.debug("Account name: %s doesn't start with " "reseller_prefix(s): %s." % (account, ','.join(self.reseller_prefixes))) return self.denied_response(req) # At this point, TempAuth is convinced that it is authoritative. # If you are sending an ACL header, it must be syntactically valid # according to TempAuth's rules for ACL syntax. acl_data = req.headers.get('x-account-access-control') if acl_data is not None: error = self.extract_acl_and_report_errors(req) if error: msg = 'X-Account-Access-Control invalid: %s\n\nInput: %s\n' % ( error, acl_data) headers = [('Content-Type', 'text/plain; charset=UTF-8')] return HTTPBadRequest(request=req, headers=headers, body=msg) user_groups = (req.remote_user or '').split(',') account_user = user_groups[1] if len(user_groups) > 1 else None if '.reseller_admin' in user_groups and \ account not in self.reseller_prefixes and \ not self._dot_account(account): req.environ['swift_owner'] = True self.logger.debug("User %s has reseller admin authorizing." % account_user) return None if account in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): # The user is admin for the account and is not trying to do an # account DELETE or PUT account_prefix = self._get_account_prefix(account) require_group = self.account_rules.get(account_prefix).get( 'require_group') if require_group and require_group in user_groups: req.environ['swift_owner'] = True self.logger.debug("User %s has admin and %s group." " Authorizing." % (account_user, require_group)) return None elif not require_group: req.environ['swift_owner'] = True self.logger.debug("User %s has admin authorizing." % account_user) return None if (req.environ.get('swift_sync_key') and (req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None)) and 'x-timestamp' in req.headers): self.logger.debug("Allow request with container sync-key: %s." % req.environ['swift_sync_key']) return None if req.method == 'OPTIONS': # allow OPTIONS requests to proceed as normal self.logger.debug("Allow OPTIONS request.") return None referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug("Allow authorizing %s via referer ACL." % req.referer) return None for user_group in user_groups: if user_group in groups: self.logger.debug("User %s allowed in ACL: %s authorizing." % (account_user, user_group)) return None # Check for access via X-Account-Access-Control acct_acls = self.account_acls(req) if acct_acls: # At least one account ACL is set in this account's sysmeta data, # so we should see whether this user is authorized by the ACLs. user_group_set = set(user_groups) if user_group_set.intersection(acct_acls['admin']): req.environ['swift_owner'] = True self.logger.debug('User %s allowed by X-Account-Access-Control' ' (admin)' % account_user) return None if (user_group_set.intersection(acct_acls['read-write']) and (container or req.method in ('GET', 'HEAD'))): # The RW ACL allows all operations to containers/objects, but # only GET/HEAD to accounts (and OPTIONS, above) self.logger.debug('User %s allowed by X-Account-Access-Control' ' (read-write)' % account_user) return None if (user_group_set.intersection(acct_acls['read-only']) and req.method in ('GET', 'HEAD')): self.logger.debug('User %s allowed by X-Account-Access-Control' ' (read-only)' % account_user) return None return self.denied_response(req)
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant_id, tenant_name = env_identity.get('tenant') user = env_identity.get('user', '') referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) #allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) user_roles = [r.lower() for r in env_identity.get('roles', [])] # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg % tenant_id) req.environ['swift_owner'] = True return # cross-tenant authorization if self._authorize_cross_tenant(user, tenant_id, tenant_name, roles): log_msg = 'user %s:%s, %s:%s, or *:%s allowed in ACL authorizing' self.logger.debug(log_msg % (tenant_name, user, tenant_id, user, user)) return acl_authorized = self._authorize_unconfirmed_identity( req, obj, referrers, roles) if acl_authorized: return # Check if a user tries to access an account that does not match their # token if not self._reseller_check(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' % (account, tenant_id) self.logger.debug(log_msg) return self.denied_response(req) # Check the roles the user is belonging to. If the user is # part of the role defined in the config variable # operator_roles (like admin) then it will be # promoted as an admin of the account/tenant. for role in self.operator_roles.split(','): role = role.strip() if role in user_roles: log_msg = 'allow user with role %s as account admin' % (role) self.logger.debug(log_msg) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. if self.is_admin and user == tenant_name: self.logger.warning("the is_admin feature has been deprecated " "and will be removed in the future " "update your config file") req.environ['swift_owner'] = True return if acl_authorized is not None: return self.denied_response(req) # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in (r.lower() for r in roles): log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg % (tenant_name, user, user_role)) return return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: version, account, container, obj = req.split_path(1, 4, True) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not account or not account.startswith(self.reseller_prefix): self.logger.debug("Account name: %s doesn't start with " "reseller_prefix: %s." % (account, self.reseller_prefix)) return self.denied_response(req) user_groups = (req.remote_user or '').split(',') account_user = user_groups[1] if len(user_groups) > 1 else None if '.reseller_admin' in user_groups and \ account != self.reseller_prefix and \ account[len(self.reseller_prefix)] != '.': req.environ['swift_owner'] = True self.logger.debug("User %s has reseller admin authorizing." % account_user) return None if account in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): # If the user is admin for the account and is not trying to do an # account DELETE or PUT... req.environ['swift_owner'] = True self.logger.debug("User %s has admin authorizing." % account_user) return None if (req.environ.get('swift_sync_key') and (req.environ['swift_sync_key'] == req.headers.get( 'x-container-sync-key', None)) and 'x-timestamp' in req.headers): self.logger.debug("Allow request with container sync-key: %s." % req.environ['swift_sync_key']) return None if req.method == 'OPTIONS': #allow OPTIONS requests to proceed as normal self.logger.debug("Allow OPTIONS request.") return None referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug("Allow authorizing %s via referer ACL." % req.referer) return None for user_group in user_groups: if user_group in groups: self.logger.debug("User %s allowed in ACL: %s authorizing." % (account_user, user_group)) return None return self.denied_response(req)
def authorize(self, env_identity, req): # Cleanup - make sure that a previously set swift_owner setting is # cleared now. This might happen for example with COPY requests. req.environ.pop('swift_owner', None) tenant_id, tenant_name = env_identity['tenant'] user_id, user_name = env_identity['user'] referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) # allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) self._set_project_domain_id(req, part, env_identity) user_roles = [r.lower() for r in env_identity.get('roles', [])] user_service_roles = [ r.lower() for r in env_identity.get('service_roles', []) ] # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg, tenant_id) req.environ['swift_owner'] = True return # The system_reader_role is almost as good as reseller_admin. if self.system_reader_roles.intersection(user_roles): # Note that if a system reader is trying to write, we're letting # the request fall on other access checks below. This way, # a compliance auditor can write a log file as a normal member. if req.method in ('GET', 'HEAD'): msg = 'User %s has system reader authorizing' self.logger.debug(msg, tenant_id) # We aren't setting 'swift_owner' nor 'reseller_request' # because they are only ever used for something that modifies # the contents of the cluster (setting ACL, deleting accounts). return # If we are not reseller admin and user is trying to delete its own # account then deny it. if not container and not obj and req.method == 'DELETE': # User is not allowed to issue a DELETE on its own account msg = 'User %s:%s is not allowed to delete its own account' self.logger.debug(msg, tenant_name, user_name) return self.denied_response(req) # cross-tenant authorization matched_acl = None if roles: allow_names = self._is_name_allowed_in_acl(req, part, env_identity) matched_acl = self._authorize_cross_tenant(user_id, user_name, tenant_id, tenant_name, roles, allow_names) if matched_acl is not None: log_msg = 'user %s allowed in ACL authorizing.' self.logger.debug(log_msg, matched_acl) return acl_authorized = self._authorize_unconfirmed_identity( req, obj, referrers, roles) if acl_authorized: return # Check if a user tries to access an account that does not match their # token if not self._account_matches_tenant(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' self.logger.debug(log_msg, account, tenant_id) return self.denied_response(req) # Compare roles from tokens against the configuration options: # # X-Auth-Token role Has specified X-Service-Token role Grant # in operator_roles? service_roles? in service_roles? swift_owner? # ------------------ -------------- -------------------- ------------ # yes yes yes yes # yes yes no no # yes no don't care yes # no don't care don't care no # ------------------ -------------- -------------------- ------------ account_prefix = self._get_account_prefix(account) operator_roles = self.account_rules[account_prefix]['operator_roles'] have_operator_role = set(operator_roles).intersection(set(user_roles)) service_roles = self.account_rules[account_prefix]['service_roles'] have_service_role = set(service_roles).intersection( set(user_service_roles)) allowed = False if have_operator_role and (service_roles and have_service_role): allowed = True elif have_operator_role and not service_roles: allowed = True if allowed: log_msg = 'allow user with role(s) %s as account admin' self.logger.debug( log_msg, ','.join(have_operator_role.union(have_service_role))) req.environ['swift_owner'] = True return if acl_authorized is not None: return self.denied_response(req) # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in (r.lower() for r in roles): log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg, tenant_name, user_name, user_role) return # Check if this user has a read-only role: # This check needs to come after the normal role check so that # read-only users can have write capabilities added for # specific containers readonly_roles = self.account_rules[account_prefix]['readonly_roles'] have_readonly_role = set(readonly_roles).intersection(set(user_roles)) if have_readonly_role and req.method in {'GET', 'HEAD'}: log_msg = 'user %s:%s allowed with read-only role: authorizing' self.logger.debug(log_msg, tenant_name, user_name) return return self.denied_response(req)
def _authorize_anon_object(self, req, account, container, obj): referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): self.log.debug('anonymous request AUTHORIZED OKAY') return None return self.unauthorized(req)
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant = env_identity.get('tenant') try: part = swift_utils.split_path(req.path, 1, 4, True) version, account, container, obj = part except ValueError: return webob.exc.HTTPNotFound(request=req) user_roles = env_identity.get('roles', []) # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg % tenant[0]) req.environ['swift_owner'] = True return # Check if a user tries to access an account that does not match their # token if not self._reseller_check(account, tenant[0]): log_msg = 'tenant mismatch: %s != %s' % (account, tenant[0]) self.logger.debug(log_msg) return self.denied_response(req) # Check the roles the user is belonging to. If the user is # part of the role defined in the config variable # operator_roles (like admin) then it will be # promoted as an admin of the account/tenant. for role in self.operator_roles.split(','): role = role.strip() if role in user_roles: log_msg = 'allow user with role %s as account admin' % (role) self.logger.debug(log_msg) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. user = env_identity.get('user', '') if self.is_admin and user == tenant[1]: req.environ['swift_owner'] = True return # Allow container sync. if (req.environ.get('swift_sync_key') and req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None) and 'x-timestamp' in req.headers and (req.remote_addr in self.allowed_sync_hosts or swift_utils.get_remote_client(req) in self.allowed_sync_hosts)): log_msg = 'allowing proxy %s for container-sync' % req.remote_addr self.logger.debug(log_msg) return # Check if referrer is allowed. referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) if swift_acl.referrer_allowed(req.referer, referrers): #TODO(chmou): convert .rlistings to Keystone type role. if obj or '.rlistings' in roles: log_msg = 'authorizing %s via referer ACL' % req.referrer self.logger.debug(log_msg) return return self.denied_response(req) # Allow ACL at individual user level (tenant:user format) if '%s:%s' % (tenant[0], user) in roles: log_msg = 'user %s:%s allowed in ACL authorizing' self.logger.debug(log_msg % (tenant[0], user)) return # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in roles: log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg % (tenant[0], user, user_role)) return return self.denied_response(req)
def authorize(self, env_identity, req): tenant_id, tenant_name = env_identity['tenant'] user_id, user_name = env_identity['user'] referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) #allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) self._set_project_domain_id(req, part, env_identity) user_roles = [r.lower() for r in env_identity.get('roles', [])] # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg, tenant_id) req.environ['swift_owner'] = True return # If we are not reseller admin and user is trying to delete its own # account then deny it. if not container and not obj and req.method == 'DELETE': # User is not allowed to issue a DELETE on its own account msg = 'User %s:%s is not allowed to delete its own account' self.logger.debug(msg, tenant_name, user_name) return self.denied_response(req) # cross-tenant authorization matched_acl = None if roles: allow_names = self._is_name_allowed_in_acl(req, part, env_identity) matched_acl = self._authorize_cross_tenant(user_id, user_name, tenant_id, tenant_name, roles, allow_names) if matched_acl is not None: log_msg = 'user %s allowed in ACL authorizing.' self.logger.debug(log_msg, matched_acl) return acl_authorized = self._authorize_unconfirmed_identity(req, obj, referrers, roles) if acl_authorized: return # Check if a user tries to access an account that does not match their # token if not self._reseller_check(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' self.logger.debug(log_msg, account, tenant_id) return self.denied_response(req) # Check the roles the user is belonging to. If the user is # part of the role defined in the config variable # operator_roles (like admin) then it will be # promoted as an admin of the account/tenant. for role in self.operator_roles.split(','): role = role.strip() if role in user_roles: log_msg = 'allow user with role %s as account admin' self.logger.debug(log_msg, role) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. if self.is_admin and user_name == tenant_name: self.logger.warning("the is_admin feature has been deprecated " "and will be removed in the future " "update your config file") req.environ['swift_owner'] = True return if acl_authorized is not None: return self.denied_response(req) # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in (r.lower() for r in roles): log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg, tenant_name, user_name, user_role) return return self.denied_response(req)
def authorize(self, env_identity, req): tenant_id, tenant_name = env_identity['tenant'] user_id, user_name = env_identity['user'] referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) # allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) self._set_project_domain_id(req, part, env_identity) user_roles = [r.lower() for r in env_identity.get('roles', [])] user_service_roles = [r.lower() for r in env_identity.get( 'service_roles', [])] # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg, tenant_id) req.environ['swift_owner'] = True return # If we are not reseller admin and user is trying to delete its own # account then deny it. if not container and not obj and req.method == 'DELETE': # User is not allowed to issue a DELETE on its own account msg = 'User %s:%s is not allowed to delete its own account' self.logger.debug(msg, tenant_name, user_name) return self.denied_response(req) # cross-tenant authorization matched_acl = None if roles: allow_names = self._is_name_allowed_in_acl(req, part, env_identity) matched_acl = self._authorize_cross_tenant(user_id, user_name, tenant_id, tenant_name, roles, allow_names) if matched_acl is not None: log_msg = 'user %s allowed in ACL authorizing.' self.logger.debug(log_msg, matched_acl) return acl_authorized = self._authorize_unconfirmed_identity(req, obj, referrers, roles) if acl_authorized: return # Check if a user tries to access an account that does not match their # token if not self._account_matches_tenant(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' self.logger.debug(log_msg, account, tenant_id) return self.denied_response(req) # Compare roles from tokens against the configuration options: # # X-Auth-Token role Has specified X-Service-Token role Grant # in operator_roles? service_roles? in service_roles? swift_owner? # ------------------ -------------- -------------------- ------------ # yes yes yes yes # yes no don't care yes # no don't care don't care no # ------------------ -------------- -------------------- ------------ account_prefix = self._get_account_prefix(account) operator_roles = self.account_rules[account_prefix]['operator_roles'] have_operator_role = set(operator_roles).intersection( set(user_roles)) service_roles = self.account_rules[account_prefix]['service_roles'] have_service_role = set(service_roles).intersection( set(user_service_roles)) if have_operator_role and (service_roles and have_service_role): req.environ['swift_owner'] = True elif have_operator_role and not service_roles: req.environ['swift_owner'] = True if req.environ.get('swift_owner'): log_msg = 'allow user with role(s) %s as account admin' self.logger.debug(log_msg, ','.join(have_operator_role.union( have_service_role))) return # If user is of the same name of the tenant then make owner of it. if self.is_admin and user_name == tenant_name: self.logger.warning("the is_admin feature has been deprecated " "and will be removed in the future " "update your config file") req.environ['swift_owner'] = True return if acl_authorized is not None: return self.denied_response(req) # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in (r.lower() for r in roles): log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg, tenant_name, user_name, user_role) return return self.denied_response(req)
def authorize_colony(self, req): """ add by colony. 1. All user GET or HEAD account. 2. All user create a container. 3. All user read or write objects without contaner acl. 4. But any user are limited by container acl if exists. """ try: version, account, container, obj = split_path(req.path, 1, 4, True) except ValueError: return HTTPNotFound(request=req) if not account: self.logger.debug('no account') return self.denied_response(req) user_groups = (req.remote_user or '').split(',') self.logger.debug('request_remote_user: %s' % req.remote_user) self.logger.debug('request_method: %s' % req.method) # All user has admin authority, so they set 'swift_owner' as True. req.environ['swift_owner'] = True # Any user GET or HEAD account if req.method in ['HEAD', 'GET'] and not container: self.logger.debug('HEAD or GET account all ok') return None if req.method in [ 'PUT', 'DELETE' ] and not container and self.admin_role in user_groups: self.logger.debug('PUT or DELETE account by admin_role ok') return None # Getting container acls for container writing request, # because PUT/POST/DELETE container doesn't return container acls. write_cont_acl = None if req.method in ['PUT', 'POST', 'DELETE'] and container and not obj: connect = httplib.HTTPConnection if self.auth_protocol == 'http' else httplib.HTTPSConnection conn = connect('%s:%s' % (req.server_name, req.server_port), timeout=10) conn.request('HEAD', '/v1.0%s' % req.path_info, None, req.headers) resp = conn.getresponse() if resp.status == 204 and resp.getheader('x-container-write'): write_cont_acl = resp.getheader('x-container-write') # Deny the other account requesting 'POST' container # for modify container acl (and the other metadata) tenant = user_groups[1] if len(user_groups) >= 2 else '' if account != 'AUTH_%s' % tenant and req.method == 'POST' and container and not obj: return self.denied_response(req) if hasattr(req, 'acl') or write_cont_acl: if write_cont_acl: self.logger.debug('write container acl: %s' % write_cont_acl) referrers, groups = parse_acl(write_cont_acl) self.logger.debug('write referrers: %s' % referrers) self.logger.debug('write group: %s' % groups) else: self.logger.debug('container acl: %s' % req.acl) referrers, groups = parse_acl(req.acl) self.logger.debug('referrers: %s' % referrers) self.logger.debug('group: %s' % groups) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug('referer_allowed') return None if not req.remote_user: return self.denied_response(req) for user_group in user_groups: if user_group in groups: self.logger.debug('group_allowed: %s' % user_group) return None if not referrers and not groups: self.logger.debug('no acl allow default access') return None self.logger.debug('group not allowed.') return self.denied_response(req) # Any user creates container by default if req.method in ['PUT', 'POST', 'DELETE'] and container and not obj: self.logger.debug( 'Any user delete container or write metadata by default.') return None self.logger.debug('request forbidden') return self.denied_response(req)
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant_id, tenant_name = env_identity.get('tenant') try: part = swift_utils.split_path(req.path, 1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) user_roles = env_identity.get('roles', []) # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg % tenant_id) req.environ['swift_owner'] = True return # Check if a user tries to access an account that does not match their # token if not self._reseller_check(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' % (account, tenant_id) self.logger.debug(log_msg) return self.denied_response(req) # Check the roles the user is belonging to. If the user is # part of the role defined in the config variable # operator_roles (like admin) then it will be # promoted as an admin of the account/tenant. for role in self.operator_roles.split(','): role = role.strip() if role in user_roles: log_msg = 'allow user with role %s as account admin' % (role) self.logger.debug(log_msg) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. user = env_identity.get('user', '') if self.is_admin and user == tenant_name: req.environ['swift_owner'] = True return referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) authorized = self._authorize_unconfirmed_identity(req, obj, referrers, roles) if authorized: return elif authorized is not None: return self.denied_response(req) # Allow ACL at individual user level (tenant:user format) # For backward compatibility, check for ACL in tenant_id:user format if ('%s:%s' % (tenant_name, user) in roles or '%s:%s' % (tenant_id, user) in roles): log_msg = 'user %s:%s or %s:%s allowed in ACL authorizing' self.logger.debug(log_msg % (tenant_name, user, tenant_id, user)) return # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in roles: log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg % (tenant_name, user, user_role)) return return self.denied_response(req)
def authorize(self, req): env = req.environ env_identity = env.get('keystone.identity', {}) tenant_id, tenant_name = env_identity.get('tenant') try: part = swift_utils.split_path(req.path, 1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) user_roles = env_identity.get('roles', []) # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg % tenant_id) req.environ['swift_owner'] = True return # Check if a user tries to access an account that does not match their # token if not self._reseller_check(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' % (account, tenant_id) self.logger.debug(log_msg) return self.denied_response(req) # Check the roles the user is belonging to. If the user is # part of the role defined in the config variable # operator_roles (like admin) then it will be # promoted as an admin of the account/tenant. for role in self.operator_roles.split(','): role = role.strip() if role in user_roles: log_msg = 'allow user with role %s as account admin' % (role) self.logger.debug(log_msg) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. user = env_identity.get('user', '') if self.is_admin and user == tenant_name: req.environ['swift_owner'] = True return referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) authorized = self._authorize_unconfirmed_identity( req, obj, referrers, roles) if authorized: return elif authorized is not None: return self.denied_response(req) # Allow ACL at individual user level (tenant:user format) # For backward compatibility, check for ACL in tenant_id:user format if ('%s:%s' % (tenant_name, user) in roles or '%s:%s' % (tenant_id, user) in roles): log_msg = 'user %s:%s or %s:%s allowed in ACL authorizing' self.logger.debug(log_msg % (tenant_name, user, tenant_id, user)) return # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in roles: log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg % (tenant_name, user, user_role)) return return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: # /v1/AUTH_sun/test/1.jpg # account=AUTH_sun container=test obj=1.jpg _junk, account, container, obj = req.split_path(1, 4, True) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if self._get_account_prefix(account) is None: self.logger.debug("Account name: %s doesn't start with " "reseller_prefix(s): %s." % (account, ','.join(self.reseller_prefixes))) return self.denied_response(req) # At this point, TempAuth is convinced that it is authoritative. # If you are sending an ACL header, it must be syntactically valid # according to TempAuth's rules for ACL syntax. acl_data = req.headers.get('x-account-access-control') if acl_data is not None: error = self.extract_acl_and_report_errors(req) if error: msg = 'X-Account-Access-Control invalid: %s\n\nInput: %s\n' % ( error, acl_data) headers = [('Content-Type', 'text/plain; charset=UTF-8')] return HTTPBadRequest(request=req, headers=headers, body=msg) user_groups = (req.remote_user or '').split(',') # user_groups = req.remote_user=groups = ['sun','sun'] account_user = user_groups[1] if len(user_groups) > 1 else None ''' The next three line will be changed by the next two lines if you don't need limitations. ''' if '.reseller.admin' in user_groups and \ account not in self.reseller_prefixes and \ not self._dot_account(account): req.environ['swift_owner'] = True self.logger.debug("User %s has reseller admin authorizing." % account_user) return None if account in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): # The user is admin for the account and is not trying to do an # account DELETE or PUT account_prefix = self._get_account_prefix(account) require_group = self.account_rules.get(account_prefix).get( 'require_group') if require_group and require_group in user_groups: req.environ['swift_owner'] = True self.logger.debug("User %s has admin and %s group." " Authorizing." % (account_user, require_group)) return None elif not require_group: req.environ['swift_owner'] = True self.logger.debug("User %s has admin authorizing." % account_user) return None if (req.environ.get('swift_sync_key') and (req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None)) and 'x-timestamp' in req.headers): self.logger.debug("Allow request with container sync-key: %s." % req.environ['swift_sync_key']) return None if req.method == 'OPTIONS': # allow OPTIONS requests to proceed as normal self.logger.debug("Allow OPTIONS request.") return None referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug("Allow authorizing %s via referer ACL." % req.referer) return None for user_group in user_groups: if user_group in groups: self.logger.debug("User %s allowed in ACL: %s authorizing." % (account_user, user_group)) return None # Check for access via X-Account-Access-Control acct_acls = self.account_acls(req) if acct_acls: # At least one account ACL is set in this account's sysmeta data, # so we should see whether this user is authorized by the ACLs. user_group_set = set(user_groups) if user_group_set.intersection(acct_acls['admin']): req.environ['swift_owner'] = True self.logger.debug('User %s allowed by X-Account-Access-Control' ' (admin)' % account_user) return None if (user_group_set.intersection(acct_acls['read-write']) and (container or req.method in ('GET', 'HEAD'))): # The RW ACL allows all operations to containers/objects, but # only GET/HEAD to accounts (and OPTIONS, above) self.logger.debug('User %s allowed by X-Account-Access-Control' ' (read-write)' % account_user) return None if (user_group_set.intersection(acct_acls['read-only']) and req.method in ('GET', 'HEAD')): self.logger.debug('User %s allowed by X-Account-Access-Control' ' (read-only)' % account_user) return None return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. """ try: version, account, container, obj = req.split_path(1, 4, True) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not account or not account.startswith(self.reseller_prefix): self.logger.debug("Account name: %s doesn't start with " "reseller_prefix: %s." % (account, self.reseller_prefix)) return self.denied_response(req) user_groups = (req.remote_user or '').split(',') account_user = user_groups[1] if len(user_groups) > 1 else None if '.reseller_admin' in user_groups and \ account != self.reseller_prefix and \ account[len(self.reseller_prefix)] != '.': req.environ['swift_owner'] = True self.logger.debug("User %s has reseller admin authorizing." % account_user) return None if account in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): # If the user is admin for the account and is not trying to do an # account DELETE or PUT... req.environ['swift_owner'] = True self.logger.debug("User %s has admin authorizing." % account_user) return None if (req.environ.get('swift_sync_key') and (req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None)) and 'x-timestamp' in req.headers): self.logger.debug("Allow request with container sync-key: %s." % req.environ['swift_sync_key']) return None if req.method == 'OPTIONS': #allow OPTIONS requests to proceed as normal self.logger.debug("Allow OPTIONS request.") return None referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug("Allow authorizing %s via referer ACL." % req.referer) return None for user_group in user_groups: if user_group in groups: self.logger.debug("User %s allowed in ACL: %s authorizing." % (account_user, user_group)) return None return self.denied_response(req)
def authorize(self, env_identity, req): tenant_id, tenant_name = env_identity['tenant'] user_id, user_name = env_identity['user'] referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) #allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) self._set_project_domain_id(req, part, env_identity) user_roles = [r.lower() for r in env_identity.get('roles', [])] # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg, tenant_id) req.environ['swift_owner'] = True return # If we are not reseller admin and user is trying to delete its own # account then deny it. if not container and not obj and req.method == 'DELETE': # User is not allowed to issue a DELETE on its own account msg = 'User %s:%s is not allowed to delete its own account' self.logger.debug(msg, tenant_name, user_name) return self.denied_response(req) # cross-tenant authorization matched_acl = None if roles: allow_names = self._is_name_allowed_in_acl(req, part, env_identity) matched_acl = self._authorize_cross_tenant(user_id, user_name, tenant_id, tenant_name, roles, allow_names) if matched_acl is not None: log_msg = 'user %s allowed in ACL authorizing.' self.logger.debug(log_msg, matched_acl) return acl_authorized = self._authorize_unconfirmed_identity( req, obj, referrers, roles) if acl_authorized: return # Check if a user tries to access an account that does not match their # token if not self._reseller_check(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' self.logger.debug(log_msg, account, tenant_id) return self.denied_response(req) # Check the roles the user is belonging to. If the user is # part of the role defined in the config variable # operator_roles (like admin) then it will be # promoted as an admin of the account/tenant. for role in self.operator_roles.split(','): role = role.strip() if role in user_roles: log_msg = 'allow user with role %s as account admin' self.logger.debug(log_msg, role) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. if self.is_admin and user_name == tenant_name: self.logger.warning("the is_admin feature has been deprecated " "and will be removed in the future " "update your config file") req.environ['swift_owner'] = True return if acl_authorized is not None: return self.denied_response(req) # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in (r.lower() for r in roles): log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg, tenant_name, user_name, user_role) return return self.denied_response(req)
def authorize(self, env_identity, req): # Cleanup - make sure that a previously set swift_owner setting is # cleared now. This might happen for example with COPY requests. req.environ.pop('swift_owner', None) tenant_id, tenant_name = env_identity['tenant'] user_id, user_name = env_identity['user'] referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None)) # allow OPTIONS requests to proceed as normal if req.method == 'OPTIONS': return try: part = req.split_path(1, 4, True) version, account, container, obj = part except ValueError: return HTTPNotFound(request=req) self._set_project_domain_id(req, part, env_identity) user_roles = [r.lower() for r in env_identity.get('roles', [])] user_service_roles = [ r.lower() for r in env_identity.get('service_roles', []) ] # Give unconditional access to a user with the reseller_admin # role. if self.reseller_admin_role in user_roles: msg = 'User %s has reseller admin authorizing' self.logger.debug(msg, tenant_id) req.environ['swift_owner'] = True return # If we are not reseller admin and user is trying to delete its own # account then deny it. if not container and not obj and req.method == 'DELETE': # User is not allowed to issue a DELETE on its own account msg = 'User %s:%s is not allowed to delete its own account' self.logger.debug(msg, tenant_name, user_name) return self.denied_response(req) # cross-tenant authorization matched_acl = None if roles: allow_names = self._is_name_allowed_in_acl(req, part, env_identity) matched_acl = self._authorize_cross_tenant(user_id, user_name, tenant_id, tenant_name, roles, allow_names) if matched_acl is not None: log_msg = 'user %s allowed in ACL authorizing.' self.logger.debug(log_msg, matched_acl) return acl_authorized = self._authorize_unconfirmed_identity( req, obj, referrers, roles) if acl_authorized: return # Check if a user tries to access an account that does not match their # token if not self._account_matches_tenant(account, tenant_id): log_msg = 'tenant mismatch: %s != %s' self.logger.debug(log_msg, account, tenant_id) return self.denied_response(req) # Compare roles from tokens against the configuration options: # # X-Auth-Token role Has specified X-Service-Token role Grant # in operator_roles? service_roles? in service_roles? swift_owner? # ------------------ -------------- -------------------- ------------ # yes yes yes yes # yes yes no no # yes no don't care yes # no don't care don't care no # ------------------ -------------- -------------------- ------------ account_prefix = self._get_account_prefix(account) operator_roles = self.account_rules[account_prefix]['operator_roles'] have_operator_role = set(operator_roles).intersection(set(user_roles)) service_roles = self.account_rules[account_prefix]['service_roles'] have_service_role = set(service_roles).intersection( set(user_service_roles)) allowed = False if have_operator_role and (service_roles and have_service_role): allowed = True elif have_operator_role and not service_roles: allowed = True if allowed: log_msg = 'allow user with role(s) %s as account admin' self.logger.debug( log_msg, ','.join(have_operator_role.union(have_service_role))) req.environ['swift_owner'] = True return # If user is of the same name of the tenant then make owner of it. if self.is_admin and user_name == tenant_name: self.logger.warning("the is_admin feature has been deprecated " "and will be removed in the future " "update your config file") req.environ['swift_owner'] = True return if acl_authorized is not None: return self.denied_response(req) # Check if we have the role in the userroles and allow it for user_role in user_roles: if user_role in (r.lower() for r in roles): log_msg = 'user %s:%s allowed in ACL: %s authorizing' self.logger.debug(log_msg, tenant_name, user_name, user_role) return return self.denied_response(req)
def authorize(self, req): """ Returns None if the request is authorized to continue or a standard WSGI response callable if not. Assumes that user groups are all lower case, which is true when Red Hat Enterprise Linux Identity Management is used. """ try: version, account, container, obj = req.split_path(1, 4, True) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not account or not account.startswith(self.reseller_prefix): self.logger.debug("Account name: %s doesn't start with " "reseller_prefix: %s." % (account, self.reseller_prefix)) return self.denied_response(req) user_groups = (req.remote_user or '').split(',') account_user = user_groups[1] if len(user_groups) > 1 else None # If the user is in the reseller_admin group for our prefix, he gets # full access to all accounts we manage. For the default reseller # prefix, the group name is auth_reseller_admin. admin_group = ("%sreseller_admin" % self.reseller_prefix).lower() if admin_group in user_groups and \ account != self.reseller_prefix and \ account[len(self.reseller_prefix)] != '.': req.environ['swift_owner'] = True return None # The "account" is part of the request URL, and already contains the # reseller prefix, like in "/v1/AUTH_vol1/pictures/pic1.png". if account.lower() in user_groups and \ (req.method not in ('DELETE', 'PUT') or container): # If the user is admin for the account and is not trying to do an # account DELETE or PUT... req.environ['swift_owner'] = True self.logger.debug("User %s has admin authorizing." % account_user) return None if (req.environ.get('swift_sync_key') and (req.environ['swift_sync_key'] == req.headers.get('x-container-sync-key', None)) and 'x-timestamp' in req.headers): self.logger.debug("Allow request with container sync-key: %s." % req.environ['swift_sync_key']) return None if req.method == 'OPTIONS': #allow OPTIONS requests to proceed as normal self.logger.debug("Allow OPTIONS request.") return None referrers, groups = parse_acl(getattr(req, 'acl', None)) if referrer_allowed(req.referer, referrers): if obj or '.rlistings' in groups: self.logger.debug("Allow authorizing %s via referer ACL." % req.referer) return None for user_group in user_groups: if user_group in groups: self.logger.debug("User %s allowed in ACL: %s authorizing." % (account_user, user_group)) return None return self.denied_response(req)