示例#1
0
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")
示例#2
0
文件: tempauth.py 项目: hbhdytf/mac
    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
示例#3
0
文件: utils.py 项目: Nexenta/swift3
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))})
示例#4
0
    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)
示例#5
0
 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)
示例#6
0
文件: auth.py 项目: edwardt/swift
 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)
示例#7
0
    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 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)
示例#9
0
    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
示例#10
0
    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))
示例#11
0
    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)
示例#12
0
文件: auth.py 项目: zuiwufenghua/zft
 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)
示例#13
0
    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))
示例#14
0
    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)
示例#15
0
 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)
示例#16
0
 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)
示例#17
0
文件: account.py 项目: Ahiknsr/swift
 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)
示例#18
0
    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)
示例#19
0
文件: acl.py 项目: zizai/swift3
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")
示例#20
0
文件: acl.py 项目: notmyname/swift3
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")
示例#21
0
    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)
示例#22
0
 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']))
示例#23
0
 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']))
示例#24
0
    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)
示例#25
0
 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)
示例#26
0
 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)
示例#27
0
    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)
示例#28
0
    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)
示例#29
0
    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 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)
示例#31
0
    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
示例#32
0
    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)
示例#33
0
    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)
示例#34
0
    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)
示例#35
0
    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))
示例#36
0
    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)
示例#37
0
    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)
示例#38
0
    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)
示例#39
0
    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)
示例#40
0
    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)
示例#41
0
    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)
示例#42
0
 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)
示例#43
0
    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)
示例#44
0
    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)
示例#46
0
 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)
示例#47
0
    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)
示例#48
0
    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)
示例#49
0
文件: tempauth.py 项目: hbhdytf/mac
    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)
示例#50
0
    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)
示例#51
0
    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)
示例#52
0
 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)
示例#53
0
    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)
示例#54
0
    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)