예제 #1
0
파일: tempurl.py 프로젝트: yinyalan/swift
    def auth_callback_same_account(req):
        try:
            _ver, acc, _rest = req.split_path(2, 3, True)
        except ValueError:
            return HTTPUnauthorized(request=req)

        if acc == account_to_match:
            return None
        else:
            return HTTPUnauthorized(request=req)
예제 #2
0
파일: tempurl.py 프로젝트: yinyalan/swift
    def auth_callback_same_container(req):
        try:
            _ver, acc, con, _rest = req.split_path(3, 4, True)
        except ValueError:
            return HTTPUnauthorized(request=req)

        if acc == account_to_match and con == container_to_match:
            return None
        else:
            return HTTPUnauthorized(request=req)
예제 #3
0
 def __call__(self, env, start_response):
     if env['REQUEST_METHOD'] == 'GET':
         if self.status == 200:
             start_response(Response().status,
                            [('Content-Type', 'text/xml')])
             json_pattern = [
                 '"name":%s', '"last_modified":%s', '"hash":%s',
                 '"bytes":%s'
             ]
             json_pattern = '{' + ','.join(json_pattern) + '}'
             json_out = []
             for b in self.objects:
                 name = simplejson.dumps(b[0])
                 time = simplejson.dumps(b[1])
                 json_out.append(json_pattern % (name, time, b[2], b[3]))
             account_list = '[' + ','.join(json_out) + ']'
             return account_list
         elif self.status == 401:
             start_response(HTTPUnauthorized().status, [])
         elif self.status == 403:
             start_response(HTTPForbidden().status, [])
         elif self.status == 404:
             start_response(HTTPNotFound().status, [])
         else:
             start_response(HTTPBadRequest().status, [])
     elif env['REQUEST_METHOD'] == 'PUT':
         if self.status == 201:
             start_response(HTTPCreated().status, [])
         elif self.status == 401:
             start_response(HTTPUnauthorized().status, [])
         elif self.status == 403:
             start_response(HTTPForbidden().status, [])
         elif self.status == 202:
             start_response(HTTPAccepted().status, [])
         else:
             start_response(HTTPBadRequest().status, [])
     elif env['REQUEST_METHOD'] == 'POST':
         if self.status == 204:
             start_response(HTTPNoContent().status, [])
         else:
             start_response(HTTPBadRequest().status, [])
     elif env['REQUEST_METHOD'] == 'DELETE':
         if self.status == 204:
             start_response(HTTPNoContent().status, [])
         elif self.status == 401:
             start_response(HTTPUnauthorized().status, [])
         elif self.status == 403:
             start_response(HTTPForbidden().status, [])
         elif self.status == 404:
             start_response(HTTPNotFound().status, [])
         elif self.status == 409:
             start_response(HTTPConflict().status, [])
         else:
             start_response(HTTPBadRequest().status, [])
     return []
예제 #4
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')
예제 #5
0
 def __call__(self, env, start_response):
     req = Request(env)
     if env['REQUEST_METHOD'] == 'GET' or env['REQUEST_METHOD'] == 'HEAD':
         if self.status == 200:
             if 'HTTP_RANGE' in env:
                 resp = Response(request=req,
                                 body=self.object_body,
                                 conditional_response=True)
                 return resp(env, start_response)
             start_response(
                 Response(request=req).status,
                 self.response_headers.items())
             if env['REQUEST_METHOD'] == 'GET':
                 return self.object_body
         elif self.status == 401:
             start_response(HTTPUnauthorized(request=req).status, [])
         elif self.status == 403:
             start_response(HTTPForbidden(request=req).status, [])
         elif self.status == 404:
             start_response(HTTPNotFound(request=req).status, [])
         else:
             start_response(HTTPBadRequest(request=req).status, [])
     elif env['REQUEST_METHOD'] == 'PUT':
         if self.status == 201:
             start_response(
                 HTTPCreated(request=req).status,
                 [('etag', self.response_headers['etag'])])
         elif self.status == 401:
             start_response(HTTPUnauthorized(request=req).status, [])
         elif self.status == 403:
             start_response(HTTPForbidden(request=req).status, [])
         elif self.status == 404:
             start_response(HTTPNotFound(request=req).status, [])
         elif self.status == 413:
             start_response(
                 HTTPRequestEntityTooLarge(request=req).status, [])
         else:
             start_response(HTTPBadRequest(request=req).status, [])
     elif env['REQUEST_METHOD'] == 'DELETE':
         if self.status == 204:
             start_response(HTTPNoContent(request=req).status, [])
         elif self.status == 401:
             start_response(HTTPUnauthorized(request=req).status, [])
         elif self.status == 403:
             start_response(HTTPForbidden(request=req).status, [])
         elif self.status == 404:
             start_response(HTTPNotFound(request=req).status, [])
         else:
             start_response(HTTPBadRequest(request=req).status, [])
     return []
예제 #6
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')
예제 #7
0
    def POST(self):
        """
        POST handler on Proxy

        Deals with storlet ACL updates
        """
        # Get the current container's ACL
        # We perform a sub request rather than get_container_info
        # since get_container_info bypasses authorization, and we
        # prefer to be on the safe side.
        sub_req = make_subrequest(self.request.environ,
                                  'HEAD', self.path,
                                  agent=self.agent)
        sub_resp = sub_req.get_response(self.app)
        if sub_resp.status_int != 204:
            self.logger.info("Failed to retrieve container metadata")
            return HTTPUnauthorized(('Unauthorized to get or modify '
                                     'the container ACL'))

        # Add the requested ACL
        read_acl = sub_resp.headers.get("X-Container-Read")
        if read_acl:
            new_read_acl = ','.join([read_acl, self.acl_string])
        else:
            new_read_acl = self.acl_string

        self.request.headers['X-Container-Read'] = new_read_acl
        resp = self.request.get_response(self.app)
        return resp
예제 #8
0
 def handle_shared(self, version, account, shared_account, shared_container,
                   env):
     if not account:
         return HTTPUnauthorized()
     email = 'shared'
     if self.whitelist_url:
         acc_id = get_account_from_whitelist(self.whitelist_url, self.app,
                                             unquote(shared_account),
                                             self.logger, env)
         if acc_id and acc_id.startswith(self.google_prefix):
             email = unquote(shared_account)
             shared_account = acc_id
     shared = retrieve_metadata(self.app, self.version, account, 'shared',
                                env)
     if not shared:
         shared = {}
     if version in self.shared_container_add:
         shared['%s/%s' % (shared_account, shared_container)] = email
     elif version in self.shared_container_remove:
         try:
             del shared['%s/%s' % (shared_account, shared_container)]
         except KeyError:
             return HTTPNotFound(
                 body='Could not remove shared container %s/%s' %
                 (shared_account, shared_container))
     if store_metadata(self.app, self.version, account, 'shared', shared,
                       env):
         return Response(
             body='Successfully handled shared container %s/%s' %
             (shared_account, shared_container))
     return HTTPNotFound(body='Could not handle shared container %s/%s' %
                         (shared_account, shared_container))
예제 #9
0
 def denied_response(self, req):
     if req.remote_user:
         self.logger.increment('forbidden')
         return HTTPForbidden(request=req)
     else:
         self.logger.increment('unauthorized')
         return HTTPUnauthorized(request=req)
예제 #10
0
 def handle_login(self, req, code, state):
     self.storage_driver = LiteAuthStorage(req.environ, self.prefix)
     oauth_client = self.provider.create_for_token(self.conf, code)
     token = oauth_client.access_token
     if not token:
         req.response = HTTPUnauthorized(request=req)
         return req.response
     user_info = oauth_client.userinfo
     if not user_info:
         req.response = HTTPForbidden(request=req)
         return req.response
     account_id = '%s:%s' % (self.prefix + user_info.get('id'),
                             user_info.get('email'))
     self.storage_driver.store_id(account_id, token,
                                  oauth_client.expires_in)
     return Response(request=req,
                     status=302,
                     headers={
                         'x-auth-token':
                         token,
                         'x-storage-token':
                         token,
                         'x-auth-token-expires':
                         oauth_client.expires_in,
                         'x-storage-url':
                         self.auth_endpoint,
                         'location':
                         '%s%s?account=%s' %
                         (self.service_domain, state or '/', account_id)
                     })
예제 #11
0
    def __call__(self, env, start_response):
        """
        Main hook into the WSGI paste.deploy filter/app pipeline.

        :param env: The WSGI environment dict.
        :param start_response: The WSGI start_response hook.
        :returns: Response as per WSGI.
        """
        if env['REQUEST_METHOD'] == 'POST':
            try:
                content_type, attrs = \
                    _parse_attrs(env.get('CONTENT_TYPE') or '')
                if content_type == 'multipart/form-data' and \
                        'boundary' in attrs:
                    http_user_agent = "%s FormPost" % (env.get(
                        'HTTP_USER_AGENT', ''))
                    env['HTTP_USER_AGENT'] = http_user_agent.strip()
                    status, headers, body = self._translate_form(
                        env, attrs['boundary'])
                    start_response(status, headers)
                    return body
            except (FormInvalid, EOFError) as err:
                body = 'FormPost: %s' % err
                start_response('400 Bad Request',
                               (('Content-Type', 'text/plain'),
                                ('Content-Length', str(len(body)))))
                return [body]
            except FormUnauthorized as err:
                message = 'FormPost: %s' % str(err).title()
                return HTTPUnauthorized(body=message)(env, start_response)
        return self.app(env, start_response)
예제 #12
0
 def _process_delete(self,
                     delete_path,
                     obj_name,
                     env,
                     resp_dict,
                     failed_files,
                     failed_file_response,
                     retry=0):
     delete_obj_req = Request.blank(delete_path, env)
     resp = delete_obj_req.get_response(self.app)
     if resp.status_int // 100 == 2:
         resp_dict['Number Deleted'] += 1
     elif resp.status_int == HTTP_NOT_FOUND:
         resp_dict['Number Not Found'] += 1
     elif resp.status_int == HTTP_UNAUTHORIZED:
         failed_files.append([quote(obj_name), HTTPUnauthorized().status])
     elif resp.status_int == HTTP_CONFLICT and \
             self.retry_count > 0 and self.retry_count > retry:
         retry += 1
         sleep(self.retry_interval**retry)
         self._process_delete(delete_path, obj_name, env, resp_dict,
                              failed_files, failed_file_response, retry)
     else:
         if resp.status_int // 100 == 5:
             failed_file_response['type'] = HTTPBadGateway
         failed_files.append([quote(obj_name), resp.status])
예제 #13
0
    def _process_delete(self,
                        resp,
                        pile,
                        obj_name,
                        resp_dict,
                        failed_files,
                        failed_file_response,
                        retry=0):
        if resp.status_int // 100 == 2:
            resp_dict['Number Deleted'] += 1
        elif resp.status_int == HTTP_NOT_FOUND:
            resp_dict['Number Not Found'] += 1
        elif resp.status_int == HTTP_UNAUTHORIZED:
            failed_files.append(
                [wsgi_quote(str_to_wsgi(obj_name)),
                 HTTPUnauthorized().status])
        elif resp.status_int == HTTP_CONFLICT and pile and \
                self.retry_count > 0 and self.retry_count > retry:
            retry += 1
            sleep(self.retry_interval**retry)
            delete_obj_req = Request.blank(resp.environ['PATH_INFO'],
                                           resp.environ)

            def _retry(req, app, obj_name, retry):
                return req.get_response(app), obj_name, retry

            pile.spawn(_retry, delete_obj_req, self.app, obj_name, retry)
        else:
            if resp.status_int // 100 == 5:
                failed_file_response['type'] = HTTPBadGateway
            failed_files.append(
                [wsgi_quote(str_to_wsgi(obj_name)), resp.status])
예제 #14
0
    def __call__(self, env, start_response):
        """
        Accepts a standard WSGI application call.

        TODO(darrell): add support for Swift v1 authen/authz
        TODO(darrell): add support for X-Auth-Token header

        Currently only supports authentication (via swift3 callback) and
        authorization for S3 API requests.
        """
        # TODO(darrell): sniff out and handle Swift v1 auth requests

        # check-and-maybe-reload-db
        self.reload_confs()

        s3 = env.get('swift3.auth_details')
        # TODO(darrell): look for and do something with X-Auth-Token (with
        # fallback to X-Storage-Token)
        # TODO(darrell): maybe care about HTTP_X_SERVICE_TOKEN if we need to?
        if not s3:
            # TDOO(darrell): remove this when adding support for Swift API
            # requests
            return HTTPBadRequest(body='Only S3 API requests are supported '
                                  'at this time.')(env, start_response)

        if s3 and self.s3_ok(env, s3):
            return self.app(env, start_response)

        # Unauthorized or missing token
        return HTTPUnauthorized(headers={
            'Www-Authenticate': 'Cloud-connector realm="unknown"'})(
                env, start_response)
예제 #15
0
    def _verify_access(self, cont, obj):
        """
        Verifies access to the specified object in swift
        :param cont: swift container name
        :param obj: swift object name
        :raise HTTPNotFound: if the object doesn't exists in swift
        :return response: Object response
        """
        if obj:
            path = os.path.join('/', self.api_version, self.account, cont, obj)
        else:
            path = os.path.join('/', self.api_version, self.account, cont)
        self.logger.debug('Verifying access to %s' % path)

        new_env = dict(self.req.environ)
        if 'HTTP_TRANSFER_ENCODING' in new_env.keys():
            del new_env['HTTP_TRANSFER_ENCODING']

        auth_token = self.req.headers.get('X-Auth-Token')
        sub_req = make_subrequest(new_env,
                                  'HEAD',
                                  path,
                                  headers={'X-Auth-Token': auth_token},
                                  swift_source='function_middleware')

        resp = sub_req.get_response(self.app)

        if not resp.is_success:
            if resp.status_int == 401:
                raise HTTPUnauthorized('Unauthorized to access to this '
                                       'resource: ' + path + '\n')
            else:
                raise HTTPNotFound('There was an error: "' + path +
                                   ' doesn\'t exists in Swift.\n')
예제 #16
0
    def run(self, req_resp, storlet_list, data_iter):
        on_other_server = {}

        # Execute multiple Storlets, PIPELINE, if any.
        for key in sorted(storlet_list):
            storlet, params, server = self._get_storlet_data(storlet_list[key])

            if server == self.server:
                self._setup_gateway()
                self.logger.info('Vertigo - Go to execute ' + storlet +
                                 ' storlet with parameters "' + params + '"')

                if not self._verify_access_to_storlet(storlet):
                    return HTTPUnauthorized('Vertigo - Storlet ' + storlet +
                                            ': No permission')
                self._setup_gateway()
                data_iter = self._call_gateway(req_resp, params, data_iter)
            else:
                storlet_execution = {
                    'storlet': storlet,
                    'params': params,
                    'server': server
                }
                launch_key = len(on_other_server.keys())
                on_other_server[launch_key] = storlet_execution

        if on_other_server:
            req_resp.headers['Storlet-List'] = json.dumps(on_other_server)

        if isinstance(req_resp, Request):
            req_resp.environ['wsgi.input'] = data_iter
        else:
            req_resp.app_iter = data_iter

        return req_resp
예제 #17
0
 def authorize(self, req):
     self.app.logger.info('StackSync API: authorize: path info: %s',
                          req.path)
     if 'swift.authorize' in req.environ:
         resp = req.environ['swift.authorize'](req)
         del req.environ['swift.authorize']
         return resp
     return HTTPUnauthorized()
예제 #18
0
    def get_mc_deletion_data(self):
        header = [i for i in self.available_deletion_headers
                  if i in self.request.headers.keys()]
        if len(header) > 1:
            raise HTTPUnauthorized('Vertigo - The system can only delete 1'
                                   ' microcontroller each time.\n')
        mc = self.request.headers[header[0]]

        return header[0].rsplit('-', 2)[1].lower(), mc
예제 #19
0
 def denied_response(self, req):
     """
     Returns a standard WSGI response callable with the status of 403 or 401
     depending on whether the REMOTE_USER is set or not.
     """
     if req.remote_user:
         return HTTPForbidden(request=req)
     else:
         return HTTPUnauthorized(request=req)
예제 #20
0
 def test_auth_fail(self):
     app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
     cache = FakeCache({'object_count': 1, 'meta': {'quota-count': '1'},
                        'write_acl': None})
     req = Request.blank(
         '/v1/a/c/o',
         environ={'REQUEST_METHOD': 'PUT', 'swift.cache': cache,
                  'CONTENT_LENGTH': '100',
                  'swift.authorize': lambda *args: HTTPUnauthorized()})
     res = req.get_response(app)
     self.assertEquals(res.status_int, 401)
예제 #21
0
        def isTokenValid(req):
            try:
                version, account, container, obj = split_path(
                    req.path, 1, 4, True)
            except ValueError:
                return HTTPNotFound(request=req)
            if 'prefix' in creds and creds['prefix']:
                if not obj.startswith(creds['prefix']):
                    return HTTPUnauthorized(request=req)
            if req.method not in ('GET', 'HEAD'):
                if 'ro' in creds and creds['ro']:
                    return HTTPUnauthorized(request=req)

            if account != creds['account']:
                return HTTPUnauthorized(request=req)
            else:
                uc = urllib.parse.unquote(container)
                if uc != creds['container'] and uc != creds[
                        'container'] + '_segments':
                    return HTTPUnauthorized(request=req)
            try:
                payload = {}
                if 'jti' in creds:
                    payload['jti'] = creds['jti']
                r = requests.get(creds['herodote_url'] + '/auth/swift/' +
                                 creds['owner'] + '/' + creds['container'] +
                                 '/' + creds['user'],
                                 params=payload)
                if r.status_code != 200:
                    return HTTPUnauthorized(request=req)
                return None
            except Exception:
                return HTTPUnauthorized(request=req)
예제 #22
0
    def __call__(self, env, start_response):
        """
        Accepts a standard WSGI application call, authenticating the request
        and installing callback hooks for authorization and ACL header
        validation. For an authenticated request, REMOTE_USER will be set to a
        comma separated list of the user's groups.

        If the request matches the self.auth_prefix, the request will be
        routed through the internal auth request handler (self.handle).
        This is to handle granting tokens, etc.
        """
        if self.allow_overrides and env.get('swift.authorize_override', False):
            return self.app(env, start_response)
        if env.get('PATH_INFO', '').startswith(self.auth_prefix):
            return self.handle(env, start_response)
        token = env.get('HTTP_X_AUTH_TOKEN', env.get('HTTP_X_STORAGE_TOKEN'))
        if token and token.startswith(self.reseller_prefix):
            groups = self.get_groups(env, token)
            if groups:
                user = groups and groups.split(',', 1)[0] or ''
                trans_id = env.get('swift.trans_id')
                self.logger.debug('User: %s uses token %s (trans_id %s)' %
                                  (user, token, trans_id))
                env['REMOTE_USER'] = groups
                env['swift.authorize'] = self.authorize
                env['swift.clean_acl'] = clean_acl
                if '.reseller_admin' in groups:
                    env['reseller_request'] = True
            else:
                # Invalid token (may be expired)
                if self.auth_method == "active":
                    return HTTPSeeOther(location=self.ext_authentication_url)(
                        env, start_response)
                elif self.auth_method == "passive":
                    self.logger.increment('unauthorized')
                    return HTTPUnauthorized()(env, start_response)
        else:
            # With a non-empty reseller_prefix, I would like to be called
            # back for anonymous access to accounts I know I'm the
            # definitive auth for.
            try:
                version, rest = split_path(env.get('PATH_INFO', ''), 1, 2,
                                           True)
            except ValueError:
                version, rest = None, None
                self.logger.increment('errors')
            # Not my token, not my account, I can't authorize this request,
            # deny all is a good idea if not already set...
            if 'swift.authorize' not in env:
                env['swift.authorize'] = self.denied_response

        return self.app(env, start_response)
예제 #23
0
    def _get_function_unset_data(self):
        header = [
            i for i in self.available_unset_headers
            if i in self.req.headers.keys()
        ]
        if len(header) > 1:
            raise HTTPUnauthorized('The system can only unset 1 '
                                   'function at a time.\n')

        trigger = header[0].lower().split('-', 2)[2].rsplit('-', 1)[0]
        function = self.req.headers[header[0]]

        return trigger, function
예제 #24
0
 def denied_response(self, req):
     """
     Returns a standard WSGI response callable with the status of 403 or 401
     depending on whether the REMOTE_USER is set or not.
     """
     if req.remote_user:
         self.logger.increment('forbidden')
         return HTTPForbidden(request=req)
     else:
         if self.auth_method == "active":
             return HTTPSeeOther(location=self.ext_authentication_url)
         elif self.auth_method == "passive":
             self.logger.increment('unauthorized')
             return HTTPUnauthorized(request=req)
예제 #25
0
파일: tempurl.py 프로젝트: strawerry/swift
    def _invalid(self, env, start_response):
        """
        Performs the necessary steps to indicate a WSGI 401
        Unauthorized response to the request.

        :param env: The WSGI environment for the request.
        :param start_response: The WSGI start_response hook.
        :returns: 401 response as per WSGI.
        """
        if env['REQUEST_METHOD'] == 'HEAD':
            body = None
        else:
            body = '401 Unauthorized: Temp URL invalid\n'
        return HTTPUnauthorized(body=body)(env, start_response)
예제 #26
0
    def __call__(self, env, start_response):
        s3 = env.get('s3api.auth_details')
        if not s3:
            # TODO: remove this when adding support for Swift API
            # requests
            return HTTPBadRequest(body='Only S3 API requests are supported '
                                  'at this time.')(env, start_response)
        if s3 and self.s3_ok(env, s3):
            return self.app(env, start_response)

        # Unauthorized or missing token
        return HTTPUnauthorized(
            headers={'Www-Authenticate': 'Cloud-connector realm="unknown"'})(
                env, start_response)
예제 #27
0
    def PUT(self):
        """
        PUT handler on Proxy
        """
        if self.is_function_object_put:
            if not self._check_mandatory_metadata():
                msg = ('Mandatory function metadata not provided: ' +
                       str(self.mandatory_function_metadata) + '\n')
                raise HTTPUnauthorized(msg)
        elif self.function_data:
            self.logger.info('There are functions to execute: ' +
                             str(self.function_data))
            return self._handle_put_trough_compute_node()

        return self.req.get_response(self.app)
예제 #28
0
def create_error_response(error, message):
    if error == 400:
        response = HTTPBadRequest(body=message)
    elif error == 401:
        response = HTTPUnauthorized(body=message)
    elif error == 403:
        response = HTTPForbidden(body=message)
    elif error == 404:
        response = HTTPNotFound(body=message)
    elif error == 405:
        response = HTTPMethodNotAllowed(body=message)
    else:
        response = HTTPServerError(body=message)

    return response
예제 #29
0
    def _get_function_set_data(self):
        params = dict()
        header = [
            i for i in self.available_set_headers
            if i in self.req.headers.keys()
        ]
        if len(header) > 1:
            raise HTTPUnauthorized('The system can only set 1 '
                                   'function at a time.\n')

        trigger = header[0].lower().split('-', 2)[2]
        function = self.req.headers[header[0]]

        if self.req.body:
            params = self.req.body

        return trigger, function, params
예제 #30
0
 def __call__(self, env, start_response):
     if self.status == 200:
         start_response(Response().status, [('Content-Type', 'text/xml')])
         json_pattern = ['"name":%s', '"count":%s', '"bytes":%s']
         json_pattern = '{' + ','.join(json_pattern) + '}'
         json_out = []
         for b in self.buckets:
             name = simplejson.dumps(b[0])
             json_out.append(json_pattern % (name, b[1], b[2]))
         account_list = '[' + ','.join(json_out) + ']'
         return account_list
     elif self.status == 401:
         start_response(HTTPUnauthorized().status, [])
     elif self.status == 403:
         start_response(HTTPForbidden().status, [])
     else:
         start_response(HTTPBadRequest().status, [])
     return []
예제 #31
0
    def __call__(self, req):
        if not self.allow_full_urls:
            sync_to = req.headers.get('x-container-sync-to')
            if sync_to and not sync_to.startswith('//'):
                raise HTTPBadRequest(
                    body='Full URLs are not allowed for X-Container-Sync-To '
                         'values. Only realm values of the format '
                         '//realm/cluster/account/container are allowed.\n',
                    request=req)
        auth = req.headers.get('x-container-sync-auth')
        if auth:
            valid = False
            auth = auth.split()
            if len(auth) != 3:
                req.environ.setdefault('swift.log_info', []).append(
                    'cs:not-3-args')
            else:
                realm, nonce, sig = auth
                realm_key = self.realms_conf.key(realm)
                realm_key2 = self.realms_conf.key2(realm)
                if not realm_key:
                    req.environ.setdefault('swift.log_info', []).append(
                        'cs:no-local-realm-key')
                else:
                    info = get_container_info(
                        req.environ, self.app, swift_source='CS')
                    user_key = info.get('sync_key')
                    if not user_key:
                        req.environ.setdefault('swift.log_info', []).append(
                            'cs:no-local-user-key')
                    else:
                        # x-timestamp headers get shunted by gatekeeper
                        if 'x-backend-inbound-x-timestamp' in req.headers:
                            req.headers['x-timestamp'] = req.headers.pop(
                                'x-backend-inbound-x-timestamp')

                        expected = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key, user_key)
                        expected2 = self.realms_conf.get_sig(
                            req.method, req.path,
                            req.headers.get('x-timestamp', '0'), nonce,
                            realm_key2, user_key) if realm_key2 else expected
                        if not streq_const_time(sig, expected) and \
                                not streq_const_time(sig, expected2):
                            req.environ.setdefault(
                                'swift.log_info', []).append('cs:invalid-sig')
                        else:
                            req.environ.setdefault(
                                'swift.log_info', []).append('cs:valid')
                            valid = True
            if not valid:
                exc = HTTPUnauthorized(
                    body='X-Container-Sync-Auth header not valid; '
                         'contact cluster operator for support.',
                    headers={'content-type': 'text/plain'},
                    request=req)
                exc.headers['www-authenticate'] = ' '.join([
                    'SwiftContainerSync',
                    exc.www_authenticate().split(None, 1)[1]])
                raise exc
            else:
                req.environ['swift.authorize_override'] = True
                # An SLO manifest will already be in the internal manifest
                # syntax and might be synced before its segments, so stop SLO
                # middleware from performing the usual manifest validation.
                req.environ['swift.slo_override'] = True

        if req.path == '/info':
            # Ensure /info requests get the freshest results
            self.register_info()
        return self.app
예제 #32
0
 def __call__(self, req):
     if not self.allow_full_urls:
         sync_to = req.headers.get('x-container-sync-to')
         if sync_to and not sync_to.startswith('//'):
             raise HTTPBadRequest(
                 body='Full URLs are not allowed for X-Container-Sync-To '
                      'values. Only realm values of the format '
                      '//realm/cluster/account/container are allowed.\n',
                 request=req)
     auth = req.headers.get('x-container-sync-auth')
     if auth:
         valid = False
         auth = auth.split()
         if len(auth) != 3:
             req.environ.setdefault('swift.log_info', []).append(
                 'cs:not-3-args')
         else:
             realm, nonce, sig = auth
             realm_key = self.realms_conf.key(realm)
             realm_key2 = self.realms_conf.key2(realm)
             if not realm_key:
                 req.environ.setdefault('swift.log_info', []).append(
                     'cs:no-local-realm-key')
             else:
                 info = get_container_info(
                     req.environ, self.app, swift_source='CS')
                 user_key = info.get('sync_key')
                 if not user_key:
                     req.environ.setdefault('swift.log_info', []).append(
                         'cs:no-local-user-key')
                 else:
                     expected = self.realms_conf.get_sig(
                         req.method, req.path,
                         req.headers.get('x-timestamp', '0'), nonce,
                         realm_key, user_key)
                     expected2 = self.realms_conf.get_sig(
                         req.method, req.path,
                         req.headers.get('x-timestamp', '0'), nonce,
                         realm_key2, user_key) if realm_key2 else expected
                     if not streq_const_time(sig, expected) and \
                             not streq_const_time(sig, expected2):
                         req.environ.setdefault(
                             'swift.log_info', []).append('cs:invalid-sig')
                     else:
                         req.environ.setdefault(
                             'swift.log_info', []).append('cs:valid')
                         valid = True
         if not valid:
             exc = HTTPUnauthorized(
                 body='X-Container-Sync-Auth header not valid; '
                      'contact cluster operator for support.',
                 headers={'content-type': 'text/plain'},
                 request=req)
             exc.headers['www-authenticate'] = ' '.join([
                 'SwiftContainerSync',
                 exc.www_authenticate().split(None, 1)[1]])
             raise exc
         else:
             req.environ['swift.authorize_override'] = True
     if req.path == '/info':
         # Ensure /info requests get the freshest results
         dct = {}
         for realm in self.realms_conf.realms():
             clusters = self.realms_conf.clusters(realm)
             if clusters:
                 dct[realm] = {'clusters': dict((c, {}) for c in clusters)}
         register_swift_info('container_sync', realms=dct)
     return self.app