Esempio n. 1
0
    def _validate_dates(self):
        """
        Validate Date/X-Oss-Date headers for signature v2
        :raises: AccessDenied
        :raises: RequestTimeTooSkewed
        """
        if self._is_query_auth:
            self._validate_expire_param()
            # TODO: make sure the case if timestamp param in query
            return

        date_header = self.headers.get('Date')
        oss_date_header = self.headers.get('X-Oss-Date')
        if not date_header and not oss_date_header:
            raise AccessDenied('OSS authentication requires a valid Date '
                               'or x-oss-date header')

        # Anyways, request timestamp should be validated
        epoch = OssTimestamp(0)
        if self.timestamp < epoch:
            raise AccessDenied()

        # If the standard date is too far ahead or behind, it is an
        # error
        delta = 60 * 5
        if abs(int(self.timestamp) - int(OssTimestamp.now())) > delta:
            raise RequestTimeTooSkewed()
Esempio n. 2
0
    def GETorHEAD(self, req):
        # if req.headers is not None and 'Accept-Encoding' in req.headers and req.headers['Accept-Encoding'] == 'gzip':
        #     resp = req.get_response(self.app, method='GET')
        #     resp.headers['Content-Encoding'] = 'gzip'
        #     resp.headers['Transfer-encoding'] = 'chunked'
        #     del resp.headers['Content-Length']
        #     resp.body = self._gen_gzip(resp.body)
        # else:
        resp = req.get_response(self.app, method='GET')
        if 'x-oss-index' in resp.headers:
            index = resp.headers['x-oss-index']
            resp = req.get_response(self.app, obj=index, method='GET')
        if 'x-oss-web-error' in resp.headers:
            obj = resp.headers['x-oss-web-error']
            resp = req.get_response(self.app, obj=obj, method='GET')
        if req.method == 'HEAD':
            resp.app_iter = None
        if 'x-oss-meta-validdate' in resp.headers:
            validDate = resp.headers['x-oss-meta-validdate']
            if str(validDate).isdigit() and validDate > float(
                    OssTimestamp.now().internal):
                raise ObjectInvalid()
            else:
                pass

        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
Esempio n. 3
0
    def PUT(self, req):
        """
        Handle PUT Object and PUT Object (Copy) request
        """
        # set X-Timestamp by oss2swift to use at copy resp body
        req_timestamp = OssTimestamp.now()
        expireDay = ''
        createDate = ''
        data = req.body
        do_crc64 = crcmod.mkCrcFun(0x142F0E1EBA9EA3693L,
                                   initCrc=0L,
                                   xorOut=0xffffffffffffffffL,
                                   rev=True)
        crcValue = do_crc64(data)

        req.headers['X-Timestamp'] = req_timestamp.internal
        req.headers['x-object-meta-object-type'] = 'Normal'
        req.headers['x-object-meta-hash-crc64ecma'] = str(crcValue)

        if all(h in req.headers
               for h in ('x-oss-copy-source', 'x-oss-copy-source-range')):
            raise InvalidArgument('x-oss-copy-source-range',
                                  req.headers['x-oss-copy-source-range'],
                                  'Illegal copy header')
        req.check_copy_source(self.app)
        bucket_headers = {}
        bucket_headers = req.get_container_info(self.app)
        expireDay, createDate = self._parse_lifecycle(bucket_headers,
                                                      req.object_name)
        if expireDay != '':
            try:
                days = int(expireDay)
                expire_sc = str(
                    int(days * 2 * 3600 + float(req_timestamp.internal)))
                req.headers['X-Delete-At'] = expire_sc
            except:
                raise InvalidArgument('X-Deltete-At', days)
        elif createDate != '':
            try:
                unix_time = to_unixtime(createDate, '%Y-%m-%dT%H:%M:%S.000Z')
                if unix_time <= int(req_timestamp):
                    pass
                else:
                    req.headers['X-Object-Meta-ValidDate'] = unix_time
            except:
                raise InvalidArgument('X-Object-Meta-ValidDate', createDate)
        resp = req.get_response(self.app)

        if 'x-oss-copy-source' in req.headers:
            resp.append_copy_resp_body(req.controller_name,
                                       req_timestamp.ossxmlformat)

            # delete object metadata from response
            for key in list(resp.headers.keys()):
                if key.startswith('x-oss-meta-'):
                    del resp.headers[key]

        resp.status = HTTP_OK
        resp.headers['x-oss-hash-crc64ecma'] = crcValue
        return resp
Esempio n. 4
0
    def _validate_expire_param(self):
        """
        Validate Expires in query parameters
        :raises: AccessDenied
        """
        # Expires header is a float since epoch
        try:
            ex = OssTimestamp(float(self.params['Expires']))
        except ValueError:
            raise AccessDenied()

        if OssTimestamp.now() > ex:
            raise AccessDenied('Request has expired')

        if ex >= 2**31:
            raise AccessDenied(
                'Invalid date (should be seconds since epoch): %s' %
                self.params['Expires'])
Esempio n. 5
0
    def test_object_PUT_copy_self_metadata_replace(self):
        date_header = self.get_date_header()
        timestamp = mktime(date_header)
        last_modified = OssTimestamp(timestamp).ossxmlformat
        header = {'x-oss-metadata-directive': 'REPLACE',
                  'Date': date_header}
        status, headers, body = self._test_object_PUT_copy_self(
            swob.HTTPOk, header, timestamp=timestamp)
        self.assertEqual(status.split()[0], '200')
        self.assertEqual(headers['Content-Type'], 'application/xml')
        self.assertTrue(headers.get('etag') is None)
        elem = fromstring(body, 'CopyObjectResult')
        self.assertEqual(elem.find('LastModified').text, last_modified)
        self.assertEqual(elem.find('ETag').text, '"%s"' % self.etag)

        _, _, headers = self.swift.calls_with_headers[-1]
        self.assertEqual(headers['X-Copy-From'], '/bucket/object')
        self.assertEqual(headers['Content-Length'], '0')
Esempio n. 6
0
    def test_object_PUT_copy_no_slash(self):
        date_header = self.get_date_header()
        timestamp = mktime(date_header)
        last_modified = OssTimestamp(timestamp).ossxmlformat
        # Some clients (like Boto) don't include the leading slash;
        # OSS seems to tolerate this so we should, too
        status, headers, body = self._test_object_PUT_copy(
            swob.HTTPOk, src_path='some/source',
            put_header={'Date': date_header}, timestamp=timestamp)
        self.assertEqual(status.split()[0], '200')
        self.assertEqual(headers['Content-Type'], 'application/xml')
        self.assertTrue(headers.get('etag') is None)
        self.assertTrue(headers.get('x-oss-meta-something') is None)
        elem = fromstring(body, 'CopyObjectResult')
        self.assertEqual(elem.find('LastModified').text, last_modified)
        self.assertEqual(elem.find('ETag').text, '"%s"' % self.etag)

        _, _, headers = self.swift.calls_with_headers[-1]
        self.assertEqual(headers['X-Copy-From'], '/some/source')
        self.assertEqual(headers['Content-Length'], '0')
Esempio n. 7
0
    def timestamp(self):
        if not self._timestamp:
            try:
                if self._is_query_auth and 'Timestamp' in self.params:
                    timestamp = mktime(self.params['Timestamp'],
                                       X_OSS_DATE_FORMAT)
                else:
                    timestamp = mktime(
                        self.headers.get('X-Oss-Date',
                                         self.headers.get('Date')))
            except ValueError:
                raise AccessDenied('OSS authentication requires a valid Date '
                                   'or x-oss-date header')

            try:
                self._timestamp = OssTimestamp(timestamp)
            except ValueError:
                raise AccessDenied()

        return self._timestamp
Esempio n. 8
0
    def PUT(self, req):
        """
        Handles Upload Part and Upload Part Copy.
        """
        if 'uploadId' not in req.params:
            raise InvalidArgument('ResourceType', 'partNumber',
                                  'Unexpected query string parameter')

        try:
            part_number = int(req.params['partNumber'])
            if part_number < 1 or CONF.max_upload_part_num < part_number:
                raise Exception()
        except Exception:
            err_msg = 'Part number must be an integer between 1 and %d,' \
                      ' inclusive' % CONF.max_upload_part_num
            raise InvalidArgument('partNumber', req.params['partNumber'],
                                  err_msg)
        data = req.body
        upload_id = req.params['uploadId']
        _check_upload_info(req, self.app, upload_id)

        req.container_name += MULTIUPLOAD_SUFFIX
        req.object_name = '%s/%s/%d' % (req.object_name, upload_id,
                                        part_number)

        req_timestamp = OssTimestamp.now()
        req.headers['X-Timestamp'] = req_timestamp.internal
        source_resp = req.check_copy_source(self.app)
        
        if 'x-oss-copy-source' in req.headers and \
                'x-oss-copy-source-range' in req.headers:
            rng = req.headers['x-oss-copy-source-range']
  
            header_valid = True
            try:
                rng_obj = Range(rng)
                if len(rng_obj.ranges) != 1:
                    header_valid = False
            except ValueError:
                header_valid = False
            if not header_valid:
                err_msg = ('The x-oss-copy-source-range value must be of the '
                           'form bytes=first-last where first and last are '
                           'the zero-based offsets of the first and last '
                           'bytes to copy')
                raise InvalidArgument('x-oss-source-range', rng, err_msg)
  
            source_size = int(source_resp.headers['Content-Length'])
            if not rng_obj.ranges_for_length(source_size):
                err_msg = ('Range specified is not valid for source object '
                           'of size: %s' % source_size)
                raise InvalidArgument('x-oss-source-range', rng, err_msg)
  
            req.headers['range'] = rng
            del req.headers['x-oss-copy-source-range']
            
        resp = req.get_response(self.app)
         
        do_crc64 = crcmod.mkCrcFun(0x142F0E1EBA9EA3693L, initCrc=0L, xorOut=0xffffffffffffffffL, rev=True)
        if 'x-oss-copy-source' in req.headers:
            resp.append_copy_resp_body(req.controller_name,
                                       req_timestamp.ossxmlformat)
        resp.status = 200
        resp.headers['x-oss-hash-crc64ecma']=do_crc64(data)
        return resp