Esempio n. 1
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Moving volume mapping %s -> %s at %s' %
              (payload['volume_id'], payload['tenant_id'], self.sp_name))
     mapping = ResourceMapping.find("volumes", payload['volume_id'])
     # Since we're manually updating a field, we have to sanitize the UUID
     # ourselves.
     mapping.tenant_id = payload['tenant_id'].replace("-", "")
Esempio n. 2
0
    def _do_request_on(self, sp, project_id=None):
        if sp == 'default':
            auth_session = auth.get_local_auth(self.local_token)
        else:
            auth_session = auth.get_sp_auth(sp,
                                            self.local_token,
                                            project_id)
        headers = self._prepare_headers(self.headers)
        headers['X-AUTH-TOKEN'] = auth_session.get_token()

        url = services.construct_url(
            sp,
            self.service_type,
            self.version,
            self.action,
            project_id=auth_session.get_project_id()
        )

        LOG.info('%s: %s' % (self.method, url))

        if self.chunked:
            return requests.request(method=self.method,
                                    url=url,
                                    headers=headers,
                                    data=chunked_reader())
        else:
            return requests.request(method=self.method,
                                    url=url,
                                    headers=headers,
                                    data=request.data,
                                    stream=self.stream,
                                    params=self._prepare_args(request.args))
Esempio n. 3
0
    def _do_request_on(self, sp, project_id=None):
        if sp == 'default':
            auth_session = auth.get_local_auth(self.local_token)
        else:
            auth_session = auth.get_sp_auth(sp, self.local_token, project_id)
        headers = self._prepare_headers(self.headers)
        headers['X-AUTH-TOKEN'] = auth_session.get_token()

        url = services.construct_url(sp,
                                     self.service_type,
                                     self.version,
                                     self.action,
                                     project_id=auth_session.get_project_id())

        LOG.info('%s: %s' % (self.method, url))

        if self.chunked:
            return requests.request(method=self.method,
                                    url=url,
                                    headers=headers,
                                    data=chunked_reader())
        else:
            return requests.request(method=self.method,
                                    url=url,
                                    headers=headers,
                                    data=request.data,
                                    stream=self.stream,
                                    params=self._prepare_args(request.args))
Esempio n. 4
0
def get_unscoped_sp_auth(service_provider, user_token):
    """Perform K2K auth, and return an unscoped session."""
    conf = get_conf_for_sp(service_provider)
    local_auth = get_local_auth(user_token).auth
    LOG.info("Getting unscoped session for (%s, %s)" %
             (service_provider, user_token))
    remote_auth = identity.v3.Keystone2Keystone(local_auth, conf.sp_name)
    return session.Session(auth=remote_auth)
Esempio n. 5
0
    def __init__(self, method, path, headers):
        self.details = RequestDetails(method, path, headers)
        self.extensions = extend.get_matched_extensions(self.details)
        self._set_strip_details(self.details)
        self.enabled_sps = filter(
            lambda sp: (self.details.service in service_providers.get(
                CONF, sp).enabled_services), CONF.service_providers)

        for extension in self.extensions:
            extension.handle_request(self.details)

        if not self.details.version:
            if CONF.aggregation:
                # unversioned calls with no action
                self._forward = self._list_api_versions
            else:
                self._forward = self._local_forward
            return

        if not self.details.resource_type:
            # versioned calls with no action
            abort(400)

        mapping = None

        if self.details.resource_id:
            mapping = model.ResourceMapping.find(
                resource_type=self.details.action[0],
                resource_id=self.details.resource_id)

        LOG.debug('Local Token: %s ' % self.details.token)

        if 'MM-SERVICE-PROVIDER' in self.details.headers:
            # The user wants a specific service provider, use that SP.
            # FIXME(knikolla): This isn't exercised by any unit test
            (self.service_provider,
             self.project_id) = (self.details.headers['MM-SERVICE-PROVIDER'],
                                 self.details.headers.get(
                                     'MM-PROJECT-ID', None))
            if self.service_provider not in self.enabled_sps:
                abort(400)
            if not self.project_id and self.service_provider != 'default':
                self.project_id = auth.get_projects_at_sp(
                    self.service_provider, self.details.token)[0]
            self._forward = self._targeted_forward
        elif mapping:
            # Which we already know the location of, use that SP.
            self.service_provider = mapping.resource_sp
            self.project_id = mapping.project_id
            self._forward = self._targeted_forward
        else:
            self._forward = self._forward

        LOG.info(
            format_for_log(title="Request to proxy",
                           method=self.details.method,
                           url=self.details.path,
                           headers=dict(self.details.headers)))
Esempio n. 6
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Creating snapshot mapping %s -> %s at %s' % (
              payload['snapshot_id'],
              payload['tenant_id'],
              self.sp_name))
     insert(ResourceMapping("snapshots",
            payload['snapshot_id'],
            payload['tenant_id'],
            self.sp_name))
Esempio n. 7
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Moving volume mapping %s -> %s at %s' % (
              payload['volume_id'],
              payload['tenant_id'],
              self.sp_name))
     mapping = ResourceMapping.find("volumes", payload['volume_id'])
     # Since we're manually updating a field, we have to sanitize the UUID
     # ourselves.
     mapping.tenant_id = payload['tenant_id'].replace("-", "")
Esempio n. 8
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Creating image mapping %s -> %s at %s' % (
              payload['id'],
              payload['owner'],
              self.sp_name))
     insert(ResourceMapping("images",
            payload['id'],
            payload['owner'],
            self.sp_name))
Esempio n. 9
0
def get_unscoped_sp_auth(service_provider, user_token):
    """Perform K2K auth, and return an unscoped session."""
    conf = get_conf_for_sp(service_provider)
    local_auth = get_local_auth(user_token).auth
    LOG.info("Getting unscoped session for (%s, %s)" % (service_provider,
                                                        user_token))
    remote_auth = identity.v3.Keystone2Keystone(
        local_auth,
        conf.sp_name
    )
    return session.Session(auth=remote_auth)
Esempio n. 10
0
def get_client():
    """Return a Keystone client capable of validating tokens."""
    LOG.info("Getting Admin Client")
    service_auth = identity.Password(
        auth_url=CONF.keystone.auth_url,
        username=CONF.keystone.username,
        password=CONF.keystone.password,
        project_name=CONF.keystone.project_name,
        project_domain_id=CONF.keystone.project_domain_id,
        user_domain_id=CONF.keystone.user_domain_id)
    local_session = session.Session(auth=service_auth)
    return v3.client.Client(session=local_session)
Esempio n. 11
0
def get_client():
    """Return a Keystone client capable of validating tokens."""
    LOG.info("Getting Admin Client")
    service_auth = identity.Password(
        auth_url=CONF.keystone.auth_url,
        username=CONF.keystone.username,
        password=CONF.keystone.password,
        project_name=CONF.keystone.project_name,
        project_domain_id=CONF.keystone.project_domain_id,
        user_domain_id=CONF.keystone.user_domain_id
    )
    local_session = session.Session(auth=service_auth)
    return v3.client.Client(session=local_session)
Esempio n. 12
0
def get_sp_auth(service_provider, user_token, remote_project_id):
    """Perform K2K auth, and return a session for a remote cluster."""
    conf = get_conf_for_sp(service_provider)
    local_auth = get_local_auth(user_token).auth

    LOG.info("Getting session for (%s, %s, %s)" %
             (service_provider, user_token, remote_project_id))

    remote_auth = identity.v3.Keystone2Keystone(local_auth,
                                                conf.sp_name,
                                                project_id=remote_project_id)

    return session.Session(auth=remote_auth)
Esempio n. 13
0
    def _finalize(self, response):
        if self.stream and not is_json_response(response):
            text = flask.stream_with_context(stream_response(response))
        else:
            text = response.text

        final_response = flask.Response(text,
                                        response.status_code,
                                        headers=self._prepare_headers(
                                            response.headers, fix_case=True))
        LOG.info(
            format_for_log(title='Response from proxy',
                           status_code=final_response.status_code,
                           headers=dict(final_response.headers)))
        return final_response
Esempio n. 14
0
def get_sp_auth(service_provider, user_token, remote_project_id):
    """Perform K2K auth, and return a session for a remote cluster."""
    conf = get_conf_for_sp(service_provider)
    local_auth = get_local_auth(user_token).auth

    LOG.info("Getting session for (%s, %s, %s)" % (service_provider,
                                                   user_token,
                                                   remote_project_id))

    remote_auth = identity.v3.Keystone2Keystone(
        local_auth,
        conf.sp_name,
        project_id=remote_project_id
    )

    return session.Session(auth=remote_auth)
Esempio n. 15
0
def get_local_auth(user_token):
    """Return a Keystone session for the local cluster."""
    LOG.info("Getting session for %s" % user_token)
    client = get_client()
    token = v3.tokens.TokenManager(client)

    try:
        token_data = token.validate(token=user_token, include_catalog=False)
    except http.NotFound:
        abort(401)

    project_id = token_data['project']['id']

    local_auth = identity.v3.Token(auth_url=CONF.keystone.auth_url,
                                   token=user_token,
                                   project_id=project_id)

    return session.Session(auth=local_auth)
Esempio n. 16
0
def get_local_auth(user_token):
    """Return a Keystone session for the local cluster."""
    LOG.info("Getting session for %s" % user_token)
    client = get_client()
    token = v3.tokens.TokenManager(client)

    try:
        token_data = token.validate(token=user_token, include_catalog=False)
    except http.NotFound:
        abort(401)

    project_id = token_data['project']['id']

    local_auth = identity.v3.Token(auth_url=CONF.keystone.auth_url,
                                   token=user_token,
                                   project_id=project_id)

    return session.Session(auth=local_auth)
Esempio n. 17
0
    def _do_request_on(self, sp, project_id=None):
        headers = self._prepare_headers(self.details.headers)

        if self.details.token:
            if sp == 'default':
                auth_session = auth.get_local_auth(self.details.token)
            else:
                auth_session = auth.get_sp_auth(sp, self.details.token,
                                                project_id)
            headers['X-AUTH-TOKEN'] = auth_session.get_token()
            project_id = auth_session.get_project_id()
        else:
            project_id = None

        url = services.construct_url(sp,
                                     self.details.service,
                                     self.details.version,
                                     self.details.action,
                                     project_id=project_id)

        request_kwargs = {
            'method': self.details.method,
            'url': url,
            'headers': headers,
            'params': self._prepare_args(self.details.args)
        }
        if self.chunked:
            resp = self.session.request(data=chunked_reader(),
                                        **request_kwargs)
        else:
            resp = self.session.request(data=self.details.body,
                                        stream=self.stream,
                                        **request_kwargs)
        LOG.info(
            format_for_log(title='Request from proxy',
                           method=self.details.method,
                           url=url,
                           headers=headers))
        LOG.info(
            format_for_log(title='Response to proxy',
                           status_code=resp.status_code,
                           headers=resp.headers))
        return resp
Esempio n. 18
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Deleting image mapping %s -> %s at %s' % (
              payload['id'],
              payload['owner'],
              self.sp_name))
     delete(ResourceMapping.find("images", payload['id']))
Esempio n. 19
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Deleting image mapping %s -> %s at %s' %
              (payload['id'], payload['owner'], self.sp_name))
     delete(ResourceMapping.find("images", payload['id']))
Esempio n. 20
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Creating image mapping %s -> %s at %s' %
              (payload['id'], payload['owner'], self.sp_name))
     insert(
         ResourceMapping("images", payload['id'], payload['owner'],
                         self.sp_name))
Esempio n. 21
0
        ImageDeleteEndpoint(sp_name)
    ]


def get_server_for_sp(sp):
    """Get notification listener for a particular service provider.

    The server can be run in the background under eventlet using .start()
    """
    cfg = config.get_conf_for_sp(sp)
    transport = oslo_messaging.get_notification_transport(CONF, cfg.messagebus)
    targets = [oslo_messaging.Target(topic='notifications')]
    return oslo_messaging.get_notification_listener(transport,
                                                    targets,
                                                    get_endpoints_for_sp(
                                                        cfg.sp_name),
                                                    executor='eventlet')


if __name__ == "__main__":
    config.load_config()
    config.more_config()
    model.create_tables()

    LOG.info("Now listening for changes")
    for sp in CONF.proxy.service_providers:
        get_server_for_sp(sp).start()
    while True:
        eventlet.sleep(5)
        # XXX do something moderately more intelligent than this...
Esempio n. 22
0
    def __init__(self, method, path, headers):
        self.method = method
        self.path = path
        self.headers = headers

        self.request_path = path.split('/')

        # workaround to fix glance requests
        # that does not contain image directory
        if self.request_path[0] in ['v1', 'v2']:
            self.request_path.insert(0, 'image')

        self.service_type = self.request_path[0]

        if len(self.request_path) == 1:
            # unversioned calls with no action
            self._forward = self._list_api_versions
            return
        elif len(self.request_path) == 2:
            # versioned calls with no action
            abort(400)

        self.version = self.request_path[1]

        self.detailed = True
        if self.service_type == 'image':
            # /image/{version}/{action}
            self.action = self.request_path[2:]
        elif self.service_type == 'volume':
            # /volume/{version}/{project_id}/{action}
            self.action = self.request_path[3:]

            # if request is to /volumes, change it
            # to /volumes/detail for aggregation
            if self.method == 'GET' \
                    and self.action[-1] == 'volumes':
                self.detailed = False
                self.action.insert(len(self.action), 'detail')
        else:
            raise ValueError

        if self.method in ['GET']:
            self.stream = True
        else:
            self.stream = False

        resource_id = None
        mapping = None
        aggregate = False

        if len(self.action) > 1 and is_valid_uuid(self.action[1]):
            resource_id = self.action[1]
            mapping = model.ResourceMapping.find(resource_type=self.action[0],
                                                 resource_id=resource_id)
        else:
            if self.method == 'GET' \
                    and self.action[0] in ['images', 'volumes', 'snapshots']:
                aggregate = True

        self.local_token = headers['X-AUTH-TOKEN']
        LOG.info('Local Token: %s ' % self.local_token)

        if 'MM-SERVICE-PROVIDER' in headers and 'MM-PROJECT-ID' in headers:
            # The user wants a specific service provider, use that SP.
            self.service_provider = headers['MM-SERVICE-PROVIDER']
            self.project_id = headers['MM-PROJECT-ID']
            self._forward = self._targeted_forward
        elif aggregate:
            self._forward = self._aggregate_forward
        elif mapping:
            # Which we already know the location of, use that SP.
            self.service_provider = mapping.resource_sp
            self.project_id = mapping.tenant_id
            self._forward = self._targeted_forward
        else:
            self._forward = self._search_forward
Esempio n. 23
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Creating snapshot mapping %s -> %s at %s' %
              (payload['snapshot_id'], payload['tenant_id'], self.sp_name))
     insert(
         ResourceMapping("snapshots", payload['snapshot_id'],
                         payload['tenant_id'], self.sp_name))
Esempio n. 24
0
    def __init__(self, method, path, headers):
        self.method = method
        self.path = path
        self.headers = headers

        self.request_path = path.split('/')

        # workaround to fix glance requests
        # that does not contain image directory
        if self.request_path[0] in ['v1', 'v2']:
            self.request_path.insert(0, 'image')

        self.service_type = self.request_path[0]

        if len(self.request_path) == 1:
            # unversioned calls with no action
            self._forward = self._list_api_versions
            return
        elif len(self.request_path) == 2:
            # versioned calls with no action
            abort(400)

        self.version = self.request_path[1]

        self.detailed = True
        if self.service_type == 'image':
            # /image/{version}/{action}
            self.action = self.request_path[2:]
        elif self.service_type == 'volume':
            # /volume/{version}/{project_id}/{action}
            self.action = self.request_path[3:]

            # if request is to /volumes, change it
            # to /volumes/detail for aggregation
            if self.method == 'GET' \
                    and self.action[-1] == 'volumes':
                self.detailed = False
                self.action.insert(len(self.action), 'detail')
        else:
            raise ValueError

        if self.method in ['GET']:
            self.stream = True
        else:
            self.stream = False

        resource_id = None
        mapping = None
        aggregate = False

        if len(self.action) > 1 and is_valid_uuid(self.action[1]):
            resource_id = self.action[1]
            mapping = model.ResourceMapping.find(
                resource_type=self.action[0],
                resource_id=resource_id)
        else:
            if self.method == 'GET' \
                    and self.action[0] in ['images', 'volumes', 'snapshots']:
                aggregate = True

        self.local_token = headers['X-AUTH-TOKEN']
        LOG.info('Local Token: %s ' % self.local_token)

        if 'MM-SERVICE-PROVIDER' in headers and 'MM-PROJECT-ID' in headers:
            # The user wants a specific service provider, use that SP.
            self.service_provider = headers['MM-SERVICE-PROVIDER']
            self.project_id = headers['MM-PROJECT-ID']
            self._forward = self._targeted_forward
        elif aggregate:
            self._forward = self._aggregate_forward
        elif mapping:
            # Which we already know the location of, use that SP.
            self.service_provider = mapping.resource_sp
            self.project_id = mapping.tenant_id
            self._forward = self._targeted_forward
        else:
            self._forward = self._search_forward
Esempio n. 25
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Deleting volume mapping %s -> %s at %s' % (
              payload['volume_id'],
              payload['tenant_id'],
              self.sp_name))
     delete(ResourceMapping.find("volumes", payload['volume_id']))
Esempio n. 26
0
 def info(self, ctxt, publisher_id, event_type, payload, metadata):
     LOG.info('Deleting snapshot mapping %s -> %s at %s' %
              (payload['snapshot_id'], payload['tenant_id'], self.sp_name))
     delete(ResourceMapping.find("snapshots", payload['snapshot_id']))
Esempio n. 27
0
            ImageDeleteEndpoint(sp_name)
    ]


def get_server_for_sp(sp):
    """Get notification listener for a particular service provider.

    The server can be run in the background under eventlet using .start()
    """
    cfg = config.get_conf_for_sp(sp)
    transport = oslo_messaging.get_notification_transport(CONF, cfg.messagebus)
    targets = [oslo_messaging.Target(topic='notifications')]
    return oslo_messaging.get_notification_listener(
            transport,
            targets,
            get_endpoints_for_sp(cfg.sp_name),
            executor='eventlet')


if __name__ == "__main__":
    config.load_config()
    config.more_config()
    model.create_tables()

    LOG.info("Now listening for changes")
    for sp in CONF.proxy.service_providers:
        get_server_for_sp(sp).start()
    while True:
        eventlet.sleep(5)
        # XXX do something moderately more intelligent than this...