Esempio n. 1
0
    def __call__(self, env, start_response):
        req = swob.Request(env)
        is_search = False
        if req.headers.get('X-Context', None) == 'search':
            is_search = True
        else:
            try:
                version, account, path = swift_utils.split_path(
                    req.path, 2, 3, True)
                if version.lower() == self.path:
                    is_search = True
            except ValueError:
                return self.app(env, start_response)

        if is_search:
            try:
                if 'swift.authorize' in req.environ:
                    auth_response = req.environ['swift.authorize'](req)
                    if auth_response:
                        return auth_response
                else:  # This is bad, very bad.
                    return swob.HTTPForbidden(request=req)
                return self.GET(req)(env, start_response)
            except Exception:
                traceback.print_exc(file=sys.stdout)
                return swob.HTTPInternalServerError(request=req)
        return self.app(env, start_response)
Esempio n. 2
0
 def authorize_cb(req):
     # Assume swift owner, if not yet set
     req.environ.setdefault('REMOTE_USER', 'authorized')
     req.environ.setdefault('swift_owner', True)
     # But then default to blocking authz, to ensure we've replaced
     # the default auth system
     return swob.HTTPForbidden(request=req)
Esempio n. 3
0
    def __call__(self, req):
        try:
            vrs, acc, con, obj = req.split_path(2, 4, rest_with_last=True)
        except ValueError:
            # /info or similar...
            return self.app

        # Check if it's an account request...
        if con is None:
            return self.translate_sysmeta_and_complete(
                req, {'x-' + SYSMETA_UNDELETE_ENABLED: SYSMETA_ACCOUNT})

        # ...or a container request...
        if obj is None:
            return self.translate_sysmeta_and_complete(
                req, {'x-' + SYSMETA_UNDELETE_ENABLED: SYSMETA_CONTAINER})

        # ...must be object.
        # We only want to step in on object DELETE requests
        if req.method != 'DELETE':
            return self.app

        # Okay, this is definitely an object DELETE request; let's see if it's
        # one we want to step in for.
        if self.is_trash(con) and self.block_trash_deletes:
            return swob.HTTPMethodNotAllowed(
                content_type="text/plain",
                body=("Attempted to delete from a trash container, but "
                      "block_trash_deletes is enabled\n"))
        elif self.is_trash(con) and not self.is_superuser(req.environ):
            return swob.HTTPForbidden(
                content_type="text/plain",
                body=("Attempted to delete from a trash container, but "
                      "user is not a superuser\n"))
        elif not self.should_save_copy(req.environ, con, obj):
            return self.app

        trash_container = self.trash_prefix + con
        copy_status, copy_headers, copy_body = self.copy_object(
            req, trash_container, obj)
        if copy_status == 404:
            self.create_trash_container(req, vrs, acc, trash_container)
            copy_status, copy_headers, copy_body = self.copy_object(
                req, trash_container, obj)
        elif not http.is_success(copy_status):
            # other error; propagate this to the client
            return swob.Response(body=friendly_error(copy_body),
                                 status=copy_status,
                                 headers=copy_headers)
        return self.app
Esempio n. 4
0
    def __call__(self, req):

        # Get will never be locked
        if req.method.lower() in READ_METHODS or\
           self._is_obj_req(req) is False:
            return self.app

        locked_methods = self._get_req_lockers(req)

        if req.method.lower() in locked_methods:
            self.logger.info('{} {} blocked'.format(req.method, req.path_info))
            return swob.HTTPForbidden()

        return self.app
Esempio n. 5
0
    def _fake_auth_middleware(self, env):
        if 'swift.authorize_override' in env:
            return

        if 'HTTP_AUTHORIZATION' not in env:
            return

        _, authorization = env['HTTP_AUTHORIZATION'].split(' ')
        tenant_user, sign = authorization.rsplit(':', 1)
        tenant, user = tenant_user.rsplit(':', 1)

        path = env['PATH_INFO']
        env['PATH_INFO'] = path.replace(tenant_user, 'AUTH_' + tenant)

        env['REMOTE_USER'] = '******'

        # AccessDenied by default
        env['swift.authorize'] = lambda req: swob.HTTPForbidden(request=req)
Esempio n. 6
0
 def fake_authorize(req):
     authorize_call.append(req)
     return swob.HTTPForbidden()
Esempio n. 7
0
 def fake_authorize(req):
     # the container GET is pre-auth'd so here we deny the object DELETE
     authorize_call.append(req)
     return swob.HTTPForbidden()
Esempio n. 8
0
    def get_controller(self, req):
        # Maybe handle /info specially here, like our superclass'
        # get_controller() does?

        # Note: the only difference I can see between doing
        # "split_path(req.path, ...)" vs. req.split_path() is that req.path
        # will quote the path string with urllib.quote() prior to
        # splititng it.  Unlike our superclass' similarly-named method, we're
        # going to leave the acct/cont/obj values UTF8-encoded and unquoted.
        ver, acct, cont, obj = req.split_path(1, 4, True)
        if not obj and not cont:
            # We've decided to not support any actions on accounts...
            raise swob.HTTPForbidden(body="Account operations are not "
                                     "supported.")

        if not obj and req.method not in ('GET', 'HEAD'):
            # We've decided to only support container listings (GET)
            raise swob.HTTPForbidden(body="The only supported container "
                                     "operations are GET and HEAD.")

        profile_key1, profile_key2 = (acct, cont), (acct, '/*')
        profile = self.sync_profiles.get(
            profile_key1, self.sync_profiles.get(profile_key2, None))
        if not profile:
            self.logger.debug('No matching sync profile for %r or %r',
                              profile_key1, profile_key2)
            raise swob.HTTPForbidden(body="No matching sync profile.")

        # Cook up a Provider "profile" here that can talk to the onprem Swift
        # cluster (the "profile" details will depend on whether or not this
        # request came into cloud-connector via S3 API or Swift API because of
        # the differences in authentication between the two APIs.
        # For now, only S3 API access is supported.
        if S3_IDENTITY_ENV_KEY in req.environ:
            # We got a S3 API request
            s3_identity = req.environ[S3_IDENTITY_ENV_KEY]
            onprem_swift_profile = {
                # Other code will expect Unicode strings in here
                "account": acct.decode('utf8'),
                "container": profile['container'],
                # All the "aws_*" stuff will be pointing to the onprem Swift
                # cluster
                "aws_bucket": profile['container'],
                "aws_endpoint": self.swift_baseurl,
                "aws_identity": s3_identity['access_key'],  # already Unicode
                "aws_secret": s3_identity['secret_key'],  # already Unicode
                "protocol": "s3",
                "custom_prefix": "",  # "native" access
            }
        else:
            raise swob.HTTPNotImplemented(
                'UNEXPECTED: only S3 access supported, but '
                'S3_IDENTITY_ENV_KEY missing??')

        d = dict(local_to_me_profile=profile,
                 remote_to_me_profile=onprem_swift_profile,
                 version=ver,
                 account_name=acct,
                 container_name=cont,
                 object_name=obj)
        return CloudConnectorController, d