예제 #1
0
 def test_registered_nondefaults(self):
     domain_remap.filter_factory({'default_reseller_prefix': 'cupcake',
                                  'mangle_client_paths': 'yes'})
     swift_info = utils.get_swift_info()
     self.assertIn('domain_remap', swift_info)
     self.assertEqual(swift_info['domain_remap'], {
         'default_reseller_prefix': 'cupcake'})
예제 #2
0
    def PUT(self, req):
        """
        Handles PUT Bucket versioning.
        """
        self.set_s3api_command(req, 'put-bucket-versioning')

        if 'object_versioning' not in get_swift_info():
            raise S3NotImplemented()

        xml = req.xml(MAX_PUT_VERSIONING_BODY_SIZE)
        try:
            elem = fromstring(xml, 'VersioningConfiguration')
            status = elem.find('./Status').text
        except (XMLSyntaxError, DocumentInvalid):
            raise MalformedXML()
        except Exception as e:
            self.logger.error(e)
            raise

        if status not in ['Enabled', 'Suspended']:
            raise MalformedXML()

        # Set up versioning
        # NB: object_versioning responsible for ensuring its container exists
        req.headers['X-Versions-Enabled'] = str(status == 'Enabled').lower()
        req.get_response(self.app, 'POST')

        return HTTPOk()
예제 #3
0
 def test_registered_nondefaults(self):
     domain_remap.filter_factory({'default_reseller_prefix': 'cupcake'})
     swift_info = utils.get_swift_info()
     self.assertTrue('domain_remap' in swift_info)
     self.assertEqual(
         swift_info['domain_remap'].get('default_reseller_prefix'),
         'cupcake')
예제 #4
0
 def test_registered_nondefaults(self):
     domain_remap.filter_factory({'default_reseller_prefix': 'cupcake'})
     swift_info = utils.get_swift_info()
     self.assertTrue('domain_remap' in swift_info)
     self.assertEqual(
         swift_info['domain_remap'].get('default_reseller_prefix'),
         'cupcake')
예제 #5
0
    def test_registered_defaults(self):
        def check_key_is_absnet(key):
            try:
                swift_info[key]
            except KeyError as err:
                if key not in err:
                    raise

        test_limits = {
            'account_ratelimit': 1,
            'max_sleep_time_seconds': 60,
            'container_ratelimit_0': 0,
            'container_ratelimit_10': 10,
            'container_ratelimit_50': 50,
            'container_listing_ratelimit_0': 0,
            'container_listing_ratelimit_10': 10,
            'container_listing_ratelimit_50': 50
        }

        ratelimit.filter_factory(test_limits)('have to pass in an app')
        swift_info = utils.get_swift_info()
        self.assertTrue('ratelimit' in swift_info)
        self.assertEqual(swift_info['ratelimit']['account_ratelimit'], 1.0)
        self.assertEqual(swift_info['ratelimit']['max_sleep_time_seconds'],
                         60.0)
        self.assertEqual(swift_info['ratelimit']['container_ratelimits'][0][0],
                         0)
        self.assertEqual(swift_info['ratelimit']['container_ratelimits'][0][1],
                         0.0)
        self.assertEqual(swift_info['ratelimit']['container_ratelimits'][1][0],
                         10)
        self.assertEqual(swift_info['ratelimit']['container_ratelimits'][1][1],
                         10.0)
        self.assertEqual(swift_info['ratelimit']['container_ratelimits'][2][0],
                         50)
        self.assertEqual(swift_info['ratelimit']['container_ratelimits'][2][1],
                         50.0)
        self.assertEqual(
            swift_info['ratelimit']['container_listing_ratelimits'][0][0], 0)
        self.assertEqual(
            swift_info['ratelimit']['container_listing_ratelimits'][0][1], 0.0)
        self.assertEqual(
            swift_info['ratelimit']['container_listing_ratelimits'][1][0], 10)
        self.assertEqual(
            swift_info['ratelimit']['container_listing_ratelimits'][1][1],
            10.0)
        self.assertEqual(
            swift_info['ratelimit']['container_listing_ratelimits'][2][0], 50)
        self.assertEqual(
            swift_info['ratelimit']['container_listing_ratelimits'][2][1],
            50.0)

        # these were left out on purpose
        for key in [
                'log_sleep_time_seconds', 'clock_accuracy',
                'rate_buffer_seconds', 'ratelimit_whitelis',
                'ratelimit_blacklist'
        ]:
            check_key_is_absnet(key)
예제 #6
0
 def test_registered_nondefaults(self):
     domain_remap.filter_factory({
         'default_reseller_prefix': 'cupcake',
         'mangle_client_paths': 'yes'
     })
     swift_info = utils.get_swift_info()
     self.assertIn('domain_remap', swift_info)
     self.assertEqual(swift_info['domain_remap'],
                      {'default_reseller_prefix': 'cupcake'})
예제 #7
0
    def test_registered_defaults(self):
        bulk.filter_factory({})
        swift_info = utils.get_swift_info()
        self.assertTrue("bulk_upload" in swift_info)
        self.assertTrue(isinstance(swift_info["bulk_upload"].get("max_containers_per_extraction"), numbers.Integral))
        self.assertTrue(isinstance(swift_info["bulk_upload"].get("max_failed_extractions"), numbers.Integral))

        self.assertTrue("bulk_delete" in swift_info)
        self.assertTrue(isinstance(swift_info["bulk_delete"].get("max_deletes_per_request"), numbers.Integral))
        self.assertTrue(isinstance(swift_info["bulk_delete"].get("max_failed_deletes"), numbers.Integral))
예제 #8
0
    def GETorHEAD(self, req):
        """Handler for HTTP GET/HEAD requests."""
        """
        Handles requests to /info
        Should return a WSGI-style callable (such as swob.Response).

        :param req: swob.Request object
        """
        if not self.expose_info:
            return HTTPForbidden(request=req)

        admin_request = False
        sig = req.params.get('swiftinfo_sig', '')
        expires = req.params.get('swiftinfo_expires', '')

        if sig != '' or expires != '':
            admin_request = True
            if not self.admin_key:
                return HTTPForbidden(request=req)
            try:
                expires = int(expires)
            except ValueError:
                return HTTPUnauthorized(request=req)
            if expires < time():
                return HTTPUnauthorized(request=req)

            valid_sigs = []
            for method in self.allowed_hmac_methods[req.method]:
                valid_sigs.append(get_hmac(method,
                                           '/info',
                                           expires,
                                           self.admin_key))

            # While it's true that any() will short-circuit, this doesn't
            # affect the timing-attack resistance since the only way this will
            # short-circuit is when a valid signature is passed in.
            is_valid_hmac = any(streq_const_time(valid_sig, sig)
                                for valid_sig in valid_sigs)
            if not is_valid_hmac:
                return HTTPUnauthorized(request=req)

        headers = {}
        if 'Origin' in req.headers:
            headers['Access-Control-Allow-Origin'] = req.headers['Origin']
            headers['Access-Control-Expose-Headers'] = ', '.join(
                ['x-trans-id'])

        #json.dumps(dict)可以将字典形式的dict对象转换为json格式的对象
        info = json.dumps(get_swift_info(
            admin=admin_request, disallowed_sections=self.disallowed_sections))

        return HTTPOk(request=req,
                      headers=headers,
                      body=info,
                      content_type='application/json; charset=UTF-8')
예제 #9
0
    def test_registered_defaults(self):

        def check_key_is_absent(key):
            try:
                swift_info[key]
            except KeyError as err:
                if key not in str(err):
                    raise

        test_limits = {'account_ratelimit': 1,
                       'max_sleep_time_seconds': 60,
                       'container_ratelimit_0': 0,
                       'container_ratelimit_10': 10,
                       'container_ratelimit_50': 50,
                       'container_listing_ratelimit_0': 0,
                       'container_listing_ratelimit_10': 10,
                       'container_listing_ratelimit_50': 50}

        ratelimit.filter_factory(test_limits)('have to pass in an app')
        swift_info = utils.get_swift_info()
        self.assertIn('ratelimit', swift_info)
        self.assertEqual(swift_info['ratelimit']
                         ['account_ratelimit'], 1.0)
        self.assertEqual(swift_info['ratelimit']
                         ['max_sleep_time_seconds'], 60.0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_ratelimits'][0][0], 0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_ratelimits'][0][1], 0.0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_ratelimits'][1][0], 10)
        self.assertEqual(swift_info['ratelimit']
                         ['container_ratelimits'][1][1], 10.0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_ratelimits'][2][0], 50)
        self.assertEqual(swift_info['ratelimit']
                         ['container_ratelimits'][2][1], 50.0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_listing_ratelimits'][0][0], 0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_listing_ratelimits'][0][1], 0.0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_listing_ratelimits'][1][0], 10)
        self.assertEqual(swift_info['ratelimit']
                         ['container_listing_ratelimits'][1][1], 10.0)
        self.assertEqual(swift_info['ratelimit']
                         ['container_listing_ratelimits'][2][0], 50)
        self.assertEqual(swift_info['ratelimit']
                         ['container_listing_ratelimits'][2][1], 50.0)

        # these were left out on purpose
        for key in ['log_sleep_time_seconds', 'clock_accuracy',
                    'rate_buffer_seconds', 'ratelimit_whitelis',
                    'ratelimit_blacklist']:
            check_key_is_absent(key)
예제 #10
0
 def test_registered_defaults(self):
     name_check.filter_factory({})(FakeApp())
     swift_info = utils.get_swift_info()
     self.assertTrue('name_check' in swift_info)
     self.assertTrue(
         isinstance(swift_info['name_check'].get('maximum_length'),
                    numbers.Integral))
     self.assertTrue(
         isinstance(swift_info['name_check'].get('forbidden_chars'), str))
     self.assertTrue(
         isinstance(swift_info['name_check'].get('forbidden_regexp'), str))
예제 #11
0
파일: __init__.py 프로젝트: AymericDu/swift
 def versioning_filter(app):
     if allow_object_versioning:
         if 'symlink' not in get_swift_info():
             raise ValueError('object versioning requires symlinks')
         if allow_oio_versioning:
             vfunc = OioObjectVersioningMiddleware.is_valid_version_id
             register_swift_info('object_versioning',
                                 is_valid_version_id=vfunc)
             return OioObjectVersioningMiddleware(app, conf)
         app = ObjectVersioningMiddleware(app, conf)
     return VersionedWritesMiddleware(app, conf)
예제 #12
0
파일: info.py 프로젝트: zhouronghua/swift
    def GETorHEAD(self, req):
        """Handler for HTTP GET/HEAD requests."""
        """
        Handles requests to /info
        Should return a WSGI-style callable (such as swob.Response).

        :param req: swob.Request object
        """
        if not self.expose_info:
            return HTTPForbidden(request=req)

        admin_request = False
        sig = req.params.get('swiftinfo_sig', '')
        expires = req.params.get('swiftinfo_expires', '')

        if sig != '' or expires != '':
            admin_request = True
            if not self.admin_key:
                return HTTPForbidden(request=req)
            try:
                expires = int(expires)
            except ValueError:
                return HTTPUnauthorized(request=req)
            if expires < time():
                return HTTPUnauthorized(request=req)

            valid_sigs = []
            for method in self.allowed_hmac_methods[req.method]:
                valid_sigs.append(
                    get_hmac(method, '/info', expires, self.admin_key))

            # While it's true that any() will short-circuit, this doesn't
            # affect the timing-attack resistance since the only way this will
            # short-circuit is when a valid signature is passed in.
            is_valid_hmac = any(
                streq_const_time(valid_sig, sig) for valid_sig in valid_sigs)
            if not is_valid_hmac:
                return HTTPUnauthorized(request=req)

        headers = {}
        if 'Origin' in req.headers:
            headers['Access-Control-Allow-Origin'] = req.headers['Origin']
            headers['Access-Control-Expose-Headers'] = ', '.join(
                ['x-trans-id'])

        info = json.dumps(
            get_swift_info(admin=admin_request,
                           disallowed_sections=self.disallowed_sections))

        return HTTPOk(request=req,
                      headers=headers,
                      body=info,
                      content_type='application/json; charset=UTF-8')
예제 #13
0
 def test_registered_configured_options(self):
     conf = {'maximum_length': 512,
             'forbidden_chars': '\'\"`',
             'forbidden_regexp': "/\./|/\.\./|/\.$"}
     name_check.filter_factory(conf)(FakeApp())
     swift_info = utils.get_swift_info()
     self.assertTrue('name_check' in swift_info)
     self.assertEqual(swift_info['name_check'].get('maximum_length'), 512)
     self.assertEqual(set(swift_info['name_check'].get('forbidden_chars')),
                      set('\'\"`'))
     self.assertEqual(swift_info['name_check'].get('forbidden_regexp'),
                      "/\./|/\.\./|/\.$")
예제 #14
0
 def test_registered_defaults(self):
     filter_factory(CONF)
     swift_info = utils.get_swift_info()
     self.assertTrue('swift3' in swift_info)
     self.assertEqual(swift_info['swift3'].get('max_bucket_listing'),
                      CONF.max_bucket_listing)
     self.assertEqual(swift_info['swift3'].get('max_parts_listing'),
                      CONF.max_parts_listing)
     self.assertEqual(swift_info['swift3'].get('max_upload_part_num'),
                      CONF.max_upload_part_num)
     self.assertEqual(swift_info['swift3'].get('max_multi_delete_objects'),
                      CONF.max_multi_delete_objects)
예제 #15
0
 def test_registered_defaults(self):
     filter_factory(self.conf)
     swift_info = utils.get_swift_info()
     self.assertTrue('s3api' in swift_info)
     self.assertEqual(swift_info['s3api'].get('max_bucket_listing'),
                      self.conf.max_bucket_listing)
     self.assertEqual(swift_info['s3api'].get('max_parts_listing'),
                      self.conf.max_parts_listing)
     self.assertEqual(swift_info['s3api'].get('max_upload_part_num'),
                      self.conf.max_upload_part_num)
     self.assertEqual(swift_info['s3api'].get('max_multi_delete_objects'),
                      self.conf.max_multi_delete_objects)
예제 #16
0
 def test_registered_defaults(self):
     name_check.filter_factory({})(FakeApp())
     swift_info = utils.get_swift_info()
     self.assertTrue('name_check' in swift_info)
     self.assertTrue(isinstance(
         swift_info['name_check'].get('maximum_length'),
         numbers.Integral))
     self.assertTrue(isinstance(
         swift_info['name_check'].get('forbidden_chars'),
         str))
     self.assertTrue(isinstance(
         swift_info['name_check'].get('forbidden_regexp'),
         str))
예제 #17
0
파일: bucket.py 프로젝트: sapcc/swift
    def _add_object(self, req, elem, o, encoding_type, listing_type,
                    fetch_owner):
        name = o['name']
        if encoding_type == 'url':
            name = quote(name.encode('utf-8'))

        if listing_type == 'object-versions':
            if o['content_type'] == DELETE_MARKER_CONTENT_TYPE:
                contents = SubElement(elem, 'DeleteMarker')
            else:
                contents = SubElement(elem, 'Version')
            SubElement(contents, 'Key').text = name
            SubElement(contents,
                       'VersionId').text = o.get('version_id') or 'null'
            if 'object_versioning' in get_swift_info():
                SubElement(
                    contents,
                    'IsLatest').text = ('true' if o['is_latest'] else 'false')
            else:
                SubElement(contents, 'IsLatest').text = 'true'
        else:
            contents = SubElement(elem, 'Contents')
            SubElement(contents, 'Key').text = name
        SubElement(contents, 'LastModified').text = \
            o['last_modified'][:-3] + 'Z'
        if contents.tag != 'DeleteMarker':
            if 's3_etag' in o:
                # New-enough MUs are already in the right format
                etag = o['s3_etag']
            elif 'slo_etag' in o:
                # SLOs may be in something *close* to the MU format
                etag = '"%s-N"' % o['slo_etag'].strip('"')
            else:
                # Normal objects just use the MD5
                etag = o['hash']
                if len(etag) < 2 or etag[::len(etag) - 1] != '""':
                    # Normal objects just use the MD5
                    etag = '"%s"' % o['hash']
                    # This also catches sufficiently-old SLOs, but we have
                    # no way to identify those from container listings
                # Otherwise, somebody somewhere (proxyfs, maybe?) made this
                # look like an RFC-compliant ETag; we don't need to
                # quote-wrap.
            SubElement(contents, 'ETag').text = etag
            SubElement(contents, 'Size').text = str(o['bytes'])
        if fetch_owner or listing_type != 'version-2':
            owner = SubElement(contents, 'Owner')
            SubElement(owner, 'ID').text = req.user_id
            SubElement(owner, 'DisplayName').text = req.user_id
        if contents.tag != 'DeleteMarker':
            SubElement(contents, 'StorageClass').text = 'STANDARD'
예제 #18
0
 def test_registered_defaults(self):
     filter_factory(CONF)
     swift_info = utils.get_swift_info()
     self.assertTrue('swift3' in swift_info)
     self.assertEqual(swift_info['swift3'].get('version'),
                      swift3.__version__)
     self.assertEqual(swift_info['swift3'].get('max_bucket_listing'),
                      CONF.max_bucket_listing)
     self.assertEqual(swift_info['swift3'].get('max_parts_listing'),
                      CONF.max_parts_listing)
     self.assertEqual(swift_info['swift3'].get('max_upload_part_num'),
                      CONF.max_upload_part_num)
     self.assertEqual(swift_info['swift3'].get('max_multi_delete_objects'),
                      CONF.max_multi_delete_objects)
예제 #19
0
def version_id_param(req):
    """
    Get the version ID specified by the request, if any.
    """
    version_id = req.params.get('versionId')
    if version_id not in ('null', None):
        obj_vers_info = get_swift_info().get('object_versioning')
        if obj_vers_info is None:
            raise S3NotImplemented()
        is_valid_version = obj_vers_info.get('is_valid_version_id',
                                             lambda x: True)
        if not is_valid_version(version_id):
            raise InvalidArgument('versionId', version_id,
                                  'Invalid version id specified')
    return version_id
예제 #20
0
    def GETorHEAD(self, req):
        """Handler for HTTP GET/HEAD requests."""
        """
        Handles requests to /info
        Should return a WSGI-style callable (such as swob.Response).

        :param req: swob.Request object
        """
        if not self.expose_info:
            return HTTPForbidden(request=req)

        admin_request = False
        sig = req.params.get('swiftinfo_sig', '')
        expires = req.params.get('swiftinfo_expires', '')

        if sig != '' or expires != '':
            admin_request = True
            if not self.admin_key:
                return HTTPForbidden(request=req)
            try:
                expires = int(expires)
            except ValueError:
                return HTTPUnauthorized(request=req)
            if expires < time():
                return HTTPUnauthorized(request=req)

            valid_sigs = []
            for method in self.allowed_hmac_methods[req.method]:
                valid_sigs.append(
                    get_hmac(method, '/info', expires, self.admin_key))

            if sig not in valid_sigs:
                return HTTPUnauthorized(request=req)

        headers = {}
        if 'Origin' in req.headers:
            headers['Access-Control-Allow-Origin'] = req.headers['Origin']
            headers['Access-Control-Expose-Headers'] = ', '.join(
                ['x-trans-id'])

        info = json.dumps(
            get_swift_info(admin=admin_request,
                           disallowed_sections=self.disallowed_sections))

        return HTTPOk(request=req,
                      headers=headers,
                      body=info,
                      content_type='application/json; charset=UTF-8')
예제 #21
0
    def test_registered_defaults(self):
        def check_key_is_absnet(key):
            try:
                swift_info[key]
            except KeyError as err:
                if key not in err:
                    raise

        test_limits = {
            "account_ratelimit": 1,
            "max_sleep_time_seconds": 60,
            "container_ratelimit_0": 0,
            "container_ratelimit_10": 10,
            "container_ratelimit_50": 50,
            "container_listing_ratelimit_0": 0,
            "container_listing_ratelimit_10": 10,
            "container_listing_ratelimit_50": 50,
        }

        ratelimit.filter_factory(test_limits)("have to pass in an app")
        swift_info = utils.get_swift_info()
        self.assertTrue("ratelimit" in swift_info)
        self.assertEqual(swift_info["ratelimit"]["account_ratelimit"], 1.0)
        self.assertEqual(swift_info["ratelimit"]["max_sleep_time_seconds"], 60.0)
        self.assertEqual(swift_info["ratelimit"]["container_ratelimits"][0][0], 0)
        self.assertEqual(swift_info["ratelimit"]["container_ratelimits"][0][1], 0.0)
        self.assertEqual(swift_info["ratelimit"]["container_ratelimits"][1][0], 10)
        self.assertEqual(swift_info["ratelimit"]["container_ratelimits"][1][1], 10.0)
        self.assertEqual(swift_info["ratelimit"]["container_ratelimits"][2][0], 50)
        self.assertEqual(swift_info["ratelimit"]["container_ratelimits"][2][1], 50.0)
        self.assertEqual(swift_info["ratelimit"]["container_listing_ratelimits"][0][0], 0)
        self.assertEqual(swift_info["ratelimit"]["container_listing_ratelimits"][0][1], 0.0)
        self.assertEqual(swift_info["ratelimit"]["container_listing_ratelimits"][1][0], 10)
        self.assertEqual(swift_info["ratelimit"]["container_listing_ratelimits"][1][1], 10.0)
        self.assertEqual(swift_info["ratelimit"]["container_listing_ratelimits"][2][0], 50)
        self.assertEqual(swift_info["ratelimit"]["container_listing_ratelimits"][2][1], 50.0)

        # these were left out on purpose
        for key in [
            "log_sleep_time_seconds",
            "clock_accuracy",
            "rate_buffer_seconds",
            "ratelimit_whitelis",
            "ratelimit_blacklist",
        ]:
            check_key_is_absnet(key)
예제 #22
0
    def DELETE(self, req):
        """
        Handle DELETE Object request
        """
        if 'versionId' in req.params and \
                req.params['versionId'] != 'null' and \
                'object_versioning' not in get_swift_info():
            raise S3NotImplemented()

        version_id = req.params.get('versionId')
        if version_id not in ('null', None):
            container_info = req.get_container_info(self.app)
            if not container_info.get('sysmeta', {}).get(
                    'versions-container', ''):
                # Versioning has never been enabled
                return HTTPNoContent(headers={'x-amz-version-id': version_id})

        try:
            try:
                query = req.gen_multipart_manifest_delete_query(
                    self.app, version=version_id)
            except NoSuchKey:
                query = {}

            req.headers['Content-Type'] = None  # Ignore client content-type

            if version_id is not None:
                query['version-id'] = version_id
                query['symlink'] = 'get'

            resp = req.get_response(self.app, query=query)
            if query.get('multipart-manifest') and resp.status_int == HTTP_OK:
                for chunk in resp.app_iter:
                    pass  # drain the bulk-deleter response
                resp.status = HTTP_NO_CONTENT
                resp.body = b''
            if resp.sw_headers.get('X-Object-Current-Version-Id') == 'null':
                new_resp = self._restore_on_delete(req)
                if new_resp:
                    resp = new_resp
        except NoSuchKey:
            # expect to raise NoSuchBucket when the bucket doesn't exist
            req.get_container_info(self.app)
            # else -- it's gone! Success.
            return HTTPNoContent()
        return resp
예제 #23
0
    def GETorHEAD(self, req):
        had_match = False
        for match_header in ('if-match', 'if-none-match'):
            if match_header not in req.headers:
                continue
            had_match = True
            for value in list_from_csv(req.headers[match_header]):
                value = normalize_etag(value)
                if value.endswith('-N'):
                    # Deal with fake S3-like etags for SLOs uploaded via Swift
                    req.headers[match_header] += ', ' + value[:-2]

        if had_match:
            # Update where to look
            update_etag_is_at_header(req, sysmeta_header('object', 'etag'))

        object_name = req.object_name
        version_id = req.params.get('versionId')
        if version_id not in ('null', None) and \
                'object_versioning' not in get_swift_info():
            raise S3NotImplemented()

        query = {} if version_id is None else {'version-id': version_id}
        if version_id not in ('null', None):
            container_info = req.get_container_info(self.app)
            if not container_info.get('sysmeta', {}).get(
                    'versions-container', ''):
                # Versioning has never been enabled
                raise NoSuchVersion(object_name, version_id)

        resp = req.get_response(self.app, query=query)

        if req.method == 'HEAD':
            resp.app_iter = None

        if 'x-amz-meta-deleted' in resp.headers:
            raise NoSuchKey(object_name)

        for key in ('content-type', 'content-language', 'expires',
                    'cache-control', 'content-disposition',
                    'content-encoding'):
            if 'response-' + key in req.params:
                resp.headers[key] = req.params['response-' + key]

        return resp
예제 #24
0
    def test_registered_defaults(self):
        bulk.filter_factory({})
        swift_info = utils.get_swift_info()
        self.assertTrue('bulk_upload' in swift_info)
        self.assertTrue(isinstance(
            swift_info['bulk_upload'].get('max_containers_per_extraction'),
            numbers.Integral))
        self.assertTrue(isinstance(
            swift_info['bulk_upload'].get('max_failed_extractions'),
            numbers.Integral))

        self.assertTrue('bulk_delete' in swift_info)
        self.assertTrue(isinstance(
            swift_info['bulk_delete'].get('max_deletes_per_request'),
            numbers.Integral))
        self.assertTrue(isinstance(
            swift_info['bulk_delete'].get('max_failed_deletes'),
            numbers.Integral))
예제 #25
0
    def test_registered_defaults(self):
        bulk.filter_factory({})
        swift_info = utils.get_swift_info()
        self.assertTrue('bulk_upload' in swift_info)
        self.assertTrue(isinstance(
            swift_info['bulk_upload'].get('max_containers_per_extraction'),
            numbers.Integral))
        self.assertTrue(isinstance(
            swift_info['bulk_upload'].get('max_failed_extractions'),
            numbers.Integral))

        self.assertTrue('bulk_delete' in swift_info)
        self.assertTrue(isinstance(
            swift_info['bulk_delete'].get('max_deletes_per_request'),
            numbers.Integral))
        self.assertTrue(isinstance(
            swift_info['bulk_delete'].get('max_failed_deletes'),
            numbers.Integral))
예제 #26
0
파일: info.py 프로젝트: jettang/icehouse
    def GETorHEAD(self, req):
        """Handler for HTTP GET/HEAD requests."""
        """
        Handles requests to /info
        Should return a WSGI-style callable (such as swob.Response).

        :param req: swob.Request object
        """
        if not self.expose_info:
            return HTTPForbidden(request=req)

        admin_request = False
        sig = req.params.get("swiftinfo_sig", "")
        expires = req.params.get("swiftinfo_expires", "")

        if sig != "" or expires != "":
            admin_request = True
            if not self.admin_key:
                return HTTPForbidden(request=req)
            try:
                expires = int(expires)
            except ValueError:
                return HTTPUnauthorized(request=req)
            if expires < time():
                return HTTPUnauthorized(request=req)

            valid_sigs = []
            for method in self.allowed_hmac_methods[req.method]:
                valid_sigs.append(get_hmac(method, "/info", expires, self.admin_key))

            if sig not in valid_sigs:
                return HTTPUnauthorized(request=req)

        headers = {}
        if "Origin" in req.headers:
            headers["Access-Control-Allow-Origin"] = req.headers["Origin"]
            headers["Access-Control-Expose-Headers"] = ", ".join(["x-trans-id"])

        info = json.dumps(get_swift_info(admin=admin_request, disallowed_sections=self.disallowed_sections))

        return HTTPOk(request=req, headers=headers, body=info, content_type="application/json; charset=UTF-8")
예제 #27
0
        def do_test(conf, expect_enabled):
            fake_app = object()

            with mock.patch.dict('swift.common.utils._swift_admin_info',
                                 clear=True):
                # we're not expecting utils._swift_info to be modified but mock
                # it anyway just in case it is
                with mock.patch.dict('swift.common.utils._swift_info',
                                     clear=True):
                    # Sanity checks...
                    self.assertNotIn('encryption', utils._swift_admin_info)
                    self.assertNotIn('encryption',
                                     utils.get_swift_info(admin=True))
                    self.assertNotIn('encryption',
                                     utils.get_swift_info(admin=True)['admin'])

                    factory = crypto.filter_factory(conf)
                    self.assertTrue(callable(factory))
                    filtered_app = factory(fake_app)

                    self.assertNotIn('encryption', utils._swift_info)
                    self.assertNotIn('encryption', utils.get_swift_info())
                    self.assertNotIn('encryption',
                                     utils.get_swift_info(admin=True))

                    self.assertIn('encryption', utils._swift_admin_info)
                    self.assertDictEqual({'enabled': expect_enabled},
                                         utils._swift_admin_info['encryption'])
                    self.assertIn('encryption',
                                  utils.get_swift_info(admin=True)['admin'])
                    self.assertDictEqual(
                        {'enabled': expect_enabled},
                        utils.get_swift_info(
                            admin=True)['admin']['encryption'])

            self.assertIsInstance(filtered_app, crypto.decrypter.Decrypter)
            self.assertIsInstance(filtered_app.app, crypto.encrypter.Encrypter)
            self.assertIs(filtered_app.app.app, fake_app)
예제 #28
0
 def versioning_filter(app):
     if allow_object_versioning:
         if 'symlink' not in get_swift_info():
             raise ValueError('object versioning requires symlinks')
         app = ObjectVersioningMiddleware(app, conf)
     return VersionedWritesMiddleware(app, conf)
예제 #29
0
 def test_registered_defaults(self):
     tempurl.filter_factory({})
     swift_info = utils.get_swift_info()
     self.assertTrue("tempurl" in swift_info)
     self.assertEqual(set(swift_info["tempurl"]["methods"]), set(("GET", "HEAD", "PUT", "POST", "DELETE")))
예제 #30
0
 def test_non_default_methods(self):
     tempurl.filter_factory({'methods': 'GET HEAD PUT DELETE BREW'})
     swift_info = utils.get_swift_info()
     self.assertTrue('tempurl' in swift_info)
     self.assertEqual(set(swift_info['tempurl']['methods']),
                      set(('GET', 'HEAD', 'PUT', 'DELETE', 'BREW')))
예제 #31
0
 def test_registered_defaults(self):
     tempurl.filter_factory({})
     swift_info = utils.get_swift_info()
     self.assertTrue('tempurl' in swift_info)
     self.assertEqual(set(swift_info['tempurl']['methods']),
                      set(('GET', 'HEAD', 'PUT', 'POST', 'DELETE')))
예제 #32
0
 def test_non_default_methods(self):
     tempurl.filter_factory({"methods": "GET HEAD PUT DELETE BREW"})
     swift_info = utils.get_swift_info()
     self.assertTrue("tempurl" in swift_info)
     self.assertEqual(set(swift_info["tempurl"]["methods"]), set(("GET", "HEAD", "PUT", "DELETE", "BREW")))
예제 #33
0
 def test_registered_nondefaults(self):
     cname_lookup.filter_factory({'lookup_depth': '2'})
     swift_info = utils.get_swift_info()
     self.assertIn('cname_lookup', swift_info)
     self.assertEqual(swift_info['cname_lookup'].get('lookup_depth'), 2)
예제 #34
0
 def test_registered_defaults(self):
     domain_remap.filter_factory({})
     swift_info = utils.get_swift_info()
     self.assertIn('domain_remap', swift_info)
     self.assertEqual(swift_info['domain_remap'],
                      {'default_reseller_prefix': None})
예제 #35
0
 def test_registered_defaults(self):
     domain_remap.filter_factory({})
     swift_info = utils.get_swift_info()
     self.assertIn('domain_remap', swift_info)
     self.assertEqual(swift_info['domain_remap'], {
         'default_reseller_prefix': None})
예제 #36
0
    def POST(self, req):
        """
        Handles Delete Multiple Objects.
        """
        def object_key_iter(elem):
            for obj in elem.iterchildren('Object'):
                key = obj.find('./Key').text
                if not key:
                    raise UserKeyMustBeSpecified()
                version = obj.find('./VersionId')
                if version is not None:
                    version = version.text

                yield key, version

        max_body_size = min(
            # FWIW, AWS limits multideletes to 1000 keys, and swift limits
            # object names to 1024 bytes (by default). Add a factor of two to
            # allow some slop.
            2 * self.conf.max_multi_delete_objects * MAX_OBJECT_NAME_LENGTH,
            # But, don't let operators shoot themselves in the foot
            10 * 1024 * 1024)

        try:
            xml = req.xml(max_body_size)
            if not xml:
                raise MissingRequestBodyError()

            req.check_md5(xml)
            elem = fromstring(xml, 'Delete', self.logger)

            quiet = elem.find('./Quiet')
            if quiet is not None and quiet.text.lower() == 'true':
                self.quiet = True
            else:
                self.quiet = False

            delete_list = list(object_key_iter(elem))
            if len(delete_list) > self.conf.max_multi_delete_objects:
                raise MalformedXML()
        except (XMLSyntaxError, DocumentInvalid):
            raise MalformedXML()
        except ErrorResponse:
            raise
        except Exception as e:
            self.logger.error(e)
            raise

        elem = Element('DeleteResult')

        # check bucket existence
        try:
            req.get_response(self.app, 'HEAD')
        except AccessDenied as error:
            body = self._gen_error_body(error, elem, delete_list)
            return HTTPOk(body=body)

        if 'object_versioning' not in get_swift_info() and any(
                version not in ('null', None)
                for _key, version in delete_list):
            raise S3NotImplemented()

        def do_delete(base_req, key, version):
            req = copy.copy(base_req)
            req.environ = copy.copy(base_req.environ)
            req.object_name = key
            if version:
                req.params = {'version-id': version, 'symlink': 'get'}

            try:
                try:
                    query = req.gen_multipart_manifest_delete_query(
                        self.app, version=version)
                except NoSuchKey:
                    query = {}
                if version:
                    query['version-id'] = version
                    query['symlink'] = 'get'

                resp = req.get_response(self.app,
                                        method='DELETE',
                                        query=query,
                                        headers={'Accept': 'application/json'})
                # Have to read the response to actually do the SLO delete
                if query.get('multipart-manifest'):
                    try:
                        delete_result = json.loads(resp.body)
                        if delete_result['Errors']:
                            # NB: bulk includes 404s in "Number Not Found",
                            # not "Errors"
                            msg_parts = [delete_result['Response Status']]
                            msg_parts.extend(
                                '%s: %s' % (obj, status)
                                for obj, status in delete_result['Errors'])
                            return key, {
                                'code': 'SLODeleteError',
                                'message': '\n'.join(msg_parts)
                            }
                        # else, all good
                    except (ValueError, TypeError, KeyError):
                        # Logs get all the gory details
                        self.logger.exception(
                            'Could not parse SLO delete response: %r',
                            resp.body)
                        # Client gets something more generic
                        return key, {
                            'code': 'SLODeleteError',
                            'message': 'Unexpected swift response'
                        }
            except NoSuchKey:
                pass
            except ErrorResponse as e:
                return key, {'code': e.__class__.__name__, 'message': e._msg}
            except Exception:
                self.logger.exception(
                    'Unexpected Error handling DELETE of %r %r' %
                    (req.container_name, key))
                return key, {'code': 'Server Error', 'message': 'Server Error'}

            return key, None

        with StreamingPile(self.conf.multi_delete_concurrency) as pile:
            for key, err in pile.asyncstarmap(
                    do_delete,
                ((req, key, version) for key, version in delete_list)):
                if err:
                    error = SubElement(elem, 'Error')
                    SubElement(error, 'Key').text = key
                    SubElement(error, 'Code').text = err['code']
                    SubElement(error, 'Message').text = err['message']
                elif not self.quiet:
                    deleted = SubElement(elem, 'Deleted')
                    SubElement(deleted, 'Key').text = key

        body = tostring(elem)

        return HTTPOk(body=body)
예제 #37
0
 def test_registered_defaults(self):
     domain_remap.filter_factory({})
     swift_info = utils.get_swift_info()
     self.assertTrue('domain_remap' in swift_info)
     self.assertTrue(
         swift_info['domain_remap'].get('default_reseller_prefix') is None)
예제 #38
0
 def test_registered_nondefaults(self):
     cname_lookup.filter_factory({'lookup_depth': '2'})
     swift_info = utils.get_swift_info()
     self.assertIn('cname_lookup', swift_info)
     self.assertEqual(swift_info['cname_lookup'].get('lookup_depth'), 2)
예제 #39
0
 def test_registered_defaults(self):
     domain_remap.filter_factory({})
     swift_info = utils.get_swift_info()
     self.assertTrue('domain_remap' in swift_info)
     self.assertTrue(
         swift_info['domain_remap'].get('default_reseller_prefix') is None)