コード例 #1
0
ファイル: __init__.py プロジェクト: isolosun/nova
    def __call__(self, req):
        request_id = context.generate_request_id()
        signature = req.params.get('Signature')
        if not signature:
            msg = _("Signature not provided")
            return ec2_error(req, request_id, "Unauthorized", msg)
        access = req.params.get('AWSAccessKeyId')
        if not access:
            msg = _("Access key not provided")
            return ec2_error(req, request_id, "Unauthorized", msg)

        # Make a copy of args for authentication and signature verification.
        auth_params = dict(req.params)
        # Not part of authentication args
        auth_params.pop('Signature')

        cred_dict = {
            'access': access,
            'signature': signature,
            'host': req.host,
            'verb': req.method,
            'path': req.path,
            'params': auth_params,
        }
        if "ec2" in CONF.keystone_ec2_url:
            creds = {'ec2Credentials': cred_dict}
        else:
            creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}}
        creds_json = jsonutils.dumps(creds)
        headers = {'Content-Type': 'application/json'}

        o = urlparse.urlparse(CONF.keystone_ec2_url)
        if o.scheme == "http":
            conn = httplib.HTTPConnection(o.netloc)
        else:
            conn = httplib.HTTPSConnection(o.netloc)
        conn.request('POST', o.path, body=creds_json, headers=headers)
        response = conn.getresponse()
        data = response.read()
        if response.status != 200:
            if response.status == 401:
                msg = response.reason
            else:
                msg = _("Failure communicating with keystone")
            return ec2_error(req, request_id, "Unauthorized", msg)
        result = jsonutils.loads(data)
        conn.close()

        try:
            token_id = result['access']['token']['id']
            user_id = result['access']['user']['id']
            project_id = result['access']['token']['tenant']['id']
            user_name = result['access']['user'].get('name')
            project_name = result['access']['token']['tenant'].get('name')
            roles = [role['name'] for role
                     in result['access']['user']['roles']]
        except (AttributeError, KeyError), e:
            LOG.exception("Keystone failure: %s" % e)
            msg = _("Failure communicating with keystone")
            return ec2_error(req, request_id, "Unauthorized", msg)
コード例 #2
0
class EC2Token(wsgi.Middleware):
    """Authenticate an EC2 request with keystone and convert to token."""
    @webob.dec.wsgify(RequestClass=wsgi.Request)
    def __call__(self, req):
        # Read request signature and access id.
        try:
            signature = req.params['Signature']
            access = req.params['AWSAccessKeyId']
        except KeyError, e:
            LOG.exception(e)
            raise webob.exc.HTTPBadRequest()

        # Make a copy of args for authentication and signature verification.
        auth_params = dict(req.params)
        # Not part of authentication args
        auth_params.pop('Signature')

        # Authenticate the request.
        creds = {
            'ec2Credentials': {
                'access': access,
                'signature': signature,
                'host': req.host,
                'verb': req.method,
                'path': req.path,
                'params': auth_params,
            }
        }
        creds_json = utils.dumps(creds)
        headers = {'Content-Type': 'application/json'}

        # Disable "has no x member" pylint error
        # for httplib and urlparse
        # pylint: disable-msg=E1101
        o = urlparse.urlparse(FLAGS.keystone_ec2_url)
        if o.scheme == "http":
            conn = httplib.HTTPConnection(o.netloc)
        else:
            conn = httplib.HTTPSConnection(o.netloc)
        conn.request('POST', o.path, body=creds_json, headers=headers)
        response = conn.getresponse().read()
        conn.close()

        # NOTE(vish): We could save a call to keystone by
        #             having keystone return token, tenant,
        #             user, and roles from this call.

        result = utils.loads(response)
        try:
            token_id = result['access']['token']['id']
        except (AttributeError, KeyError), e:
            LOG.exception(e)
            raise webob.exc.HTTPBadRequest()
コード例 #3
0
ファイル: ec2_token.py プロジェクト: nonameentername/keystone
    def __call__(self, req):
        # Read request signature and access id.
        try:
            signature = req.params['Signature']
            access = req.params['AWSAccessKeyId']
        except KeyError:
            raise webob.exc.HTTPBadRequest()

        # Make a copy of args for authentication and signature verification.
        auth_params = dict(req.params)
        # Not part of authentication args
        auth_params.pop('Signature')

        # Authenticate the request.
        creds = {
            'ec2Credentials': {
                'access': access,
                'signature': signature,
                'host': req.host,
                'verb': req.method,
                'path': req.path,
                'params': auth_params,
            }
        }
        creds_json = jsonutils.dumps(creds)
        headers = {'Content-Type': 'application/json'}

        # Disable 'has no x member' pylint error
        # for httplib and urlparse
        # pylint: disable-msg=E1101
        o = urllib.parse.urlparse(CONF.keystone_ec2_url)
        if o.scheme == 'http':
            conn = httplib.HTTPConnection(o.netloc)
        else:
            conn = httplib.HTTPSConnection(o.netloc)
        conn.request('POST', o.path, body=creds_json, headers=headers)
        response = conn.getresponse().read()
        conn.close()

        # NOTE(vish): We could save a call to keystone by
        #             having keystone return token, tenant,
        #             user, and roles from this call.

        result = jsonutils.loads(response)
        try:
            token_id = result['access']['token']['id']
        except (AttributeError, KeyError):
            raise webob.exc.HTTPBadRequest()

        # Authenticated!
        req.headers['X-Auth-Token'] = token_id
        return self.application
コード例 #4
0
ファイル: bufferedhttp.py プロジェクト: runRanrun/keystone
def http_connect_raw(ipaddr,
                     port,
                     method,
                     path,
                     headers=None,
                     query_string=None,
                     ssl=False,
                     key_file=None,
                     cert_file=None):
    """Helper function to create an HTTPConnection object.

    If ssl is set True, HTTPSConnection will be used. However, if ssl=False,
    BufferedHTTPConnection will be used, which is buffered for backend Swift
    services.

    :param ipaddr: IPv4 address to connect to
    :param port: port to connect to
    :param method: HTTP method to request ('GET', 'PUT', 'POST', etc.)
    :param path: request path
    :param headers: dictionary of headers
    :param query_string: request query string
    :param ssl: set True if SSL should be used (default: False)
    :param key_file Private key file (not needed if cert_file has private key)
    :param cert_file Certificate file (Keystore)
    :returns: HTTPConnection object

    """
    if ssl:
        conn = httplib.HTTPSConnection('%s:%s' % (ipaddr, port),
                                       key_file=key_file,
                                       cert_file=cert_file)
    else:
        conn = BufferedHTTPConnection('%s:%s' % (ipaddr, port))
    if query_string:
        path += '?' + query_string
    conn.path = path
    conn.putrequest(method, path)
    if headers:
        for header, value in headers.iteritems():
            conn.putheader(header, value)
    conn.endheaders()
    return conn
コード例 #5
0
    def __call__(self, req):
        # NOTE(alevine) We need to calculate the hash here because
        # subsequent access to request modifies the req.body so the hash
        # calculation will yield invalid results.
        body_hash = hashlib.sha256(req.body).hexdigest()

        request_id = context.generate_request_id()
        signature = self._get_signature(req)
        if not signature:
            msg = _("Signature not provided")
            return faults.ec2_error_response(request_id,
                                             "AuthFailure",
                                             msg,
                                             status=400)
        access = self._get_access(req)
        if not access:
            msg = _("Access key not provided")
            return faults.ec2_error_response(request_id,
                                             "AuthFailure",
                                             msg,
                                             status=400)

        if 'X-Amz-Signature' in req.params or 'Authorization' in req.headers:
            auth_params = {}
        else:
            # Make a copy of args for authentication and signature verification
            auth_params = dict(req.params)
            # Not part of authentication args
            auth_params.pop('Signature', None)

        cred_dict = {
            'access': access,
            'signature': signature,
            'host': req.host,
            'verb': req.method,
            'path': req.path,
            'params': auth_params,
            'headers': req.headers,
            'body_hash': body_hash
        }
        if "ec2" in CONF.keystone_ec2_url:
            creds = {'ec2Credentials': cred_dict}
        else:
            creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}}
        creds_json = jsonutils.dumps(creds)
        headers = {'Content-Type': 'application/json'}

        o = urlparse.urlparse(CONF.keystone_ec2_url)
        if o.scheme == "http":
            conn = httplib.HTTPConnection(o.netloc)
        else:
            conn = httplib.HTTPSConnection(o.netloc)
        conn.request('POST', o.path, body=creds_json, headers=headers)
        response = conn.getresponse()
        data = response.read()
        if response.status != 200:
            if response.status == 401:
                msg = response.reason
            else:
                msg = _("Failure communicating with keystone")
            return faults.ec2_error_response(request_id,
                                             "AuthFailure",
                                             msg,
                                             status=response.status)
        result = jsonutils.loads(data)
        conn.close()

        try:
            token_id = result['access']['token']['id']
            user_id = result['access']['user']['id']
            project_id = result['access']['token']['tenant']['id']
            user_name = result['access']['user'].get('name')
            project_name = result['access']['token']['tenant'].get('name')
            roles = [
                role['name'] for role in result['access']['user']['roles']
            ]
        except (AttributeError, KeyError) as e:
            LOG.error(_LE("Keystone failure: %s"), e)
            msg = _("Failure communicating with keystone")
            return faults.ec2_error_response(request_id,
                                             "AuthFailure",
                                             msg,
                                             status=400)

        remote_address = req.remote_addr
        if CONF.use_forwarded_for:
            remote_address = req.headers.get('X-Forwarded-For', remote_address)

        catalog = result['access']['serviceCatalog']
        ctxt = context.RequestContext(user_id,
                                      project_id,
                                      user_name=user_name,
                                      project_name=project_name,
                                      roles=roles,
                                      auth_token=token_id,
                                      remote_address=remote_address,
                                      service_catalog=catalog)

        req.environ['nova.context'] = ctxt

        return self.application
コード例 #6
0
def execute_task(task, headers, args):
  """ Executes a task to a url with the given args.

  Args:
    task: A celery Task instance.
    headers: A dictionary of headers for the task.
    args: A dictionary of arguments for the request.
          Contains the task body.
  Returns:
    The status code of the task fetch upon success.
  Raises:
    The current function to retry.
  """
  start_time = datetime.datetime.utcnow()

  content_length = len(args['body'])

  loggable_args = {key: args[key] for key in args
                   if key not in ['task_name', 'body', 'payload']}
  loggable_args['body_length'] = content_length
  logger.info('Running {}\n'
              'Headers: {}\n'
              'Args: {}'.format(args['task_name'], headers, loggable_args))
  url = urlparse(args['url'])

  redirects_left = 1
  while True:
    urlpath = url.path
    if url.query:
      urlpath += "?" + url.query

    method = args['method']
    if args['expires'] <= datetime.datetime.now():
      # We do this check because the expires attribute in
      # celery is not passed to retried tasks. This is a
      # documented bug in celery.
      logger.error(
        "Task %s with id %s has expired with expiration date %s" % (
         args['task_name'], task.request.id, args['expires']))
      item = TaskName.get_by_key_name(args['task_name'])
      celery.control.revoke(task.request.id)
      db.delete(item)
      return

    if (args['max_retries'] != 0 and
        task.request.retries >= args['max_retries']):
      logger.error("Task %s with id %s has exceeded retries: %s" % (
        args['task_name'], task.request.id,
        args['max_retries']))
      item = TaskName.get_by_key_name(args['task_name'])
      celery.control.revoke(task.request.id)
      db.delete(item)
      return
    # Targets do not get X-Forwarded-Proto from nginx, they use haproxy port.
    headers['X-Forwarded-Proto'] = url.scheme
    if url.scheme == 'http':
      connection = httplib.HTTPConnection(remote_host, url.port)
    elif url.scheme == 'https':
      connection = httplib.HTTPSConnection(remote_host, url.port)
    else:
      logger.error("Task %s tried to use url scheme %s, "
                   "which is not supported." % (
                   args['task_name'], url.scheme))

    skip_host = False
    if 'host' in headers or 'Host' in headers:
      skip_host = True

    skip_accept_encoding = False
    if 'accept-encoding' in headers or 'Accept-Encoding' in headers:
      skip_accept_encoding = True

    connection.putrequest(method,
                          urlpath,
                          skip_host=skip_host,
                          skip_accept_encoding=skip_accept_encoding)

    # Update the task headers
    headers['X-AppEngine-TaskRetryCount'] = str(task.request.retries)
    headers['X-AppEngine-TaskExecutionCount'] = str(task.request.retries)

    for header in headers:
      connection.putheader(header, headers[header])

    if 'content-type' not in headers or 'Content-Type' not in headers:
      if url.query:
        connection.putheader('content-type', 'application/octet-stream')
      else:
        connection.putheader('content-type',
                             'application/x-www-form-urlencoded')

    connection.putheader("Content-Length", str(content_length))

    retries = int(task.request.retries) + 1
    wait_time = get_wait_time(retries, args)

    try:
      connection.endheaders()
      if args["body"]:
        connection.send(args['body'])

      response = connection.getresponse()
      response.read()
      response.close()
    except (BadStatusLine, SocketError):
      logger.warning(
        '{task} failed before receiving response. It will retry in {wait} '
        'seconds.'.format(task=args['task_name'], wait=wait_time))
      raise task.retry(countdown=wait_time)

    if 200 <= response.status < 300:
      # Task successful.
      item = TaskName.get_by_key_name(args['task_name'])
      db.delete(item)
      time_elapsed = datetime.datetime.utcnow() - start_time
      logger.info(
        '{task} received status {status} from {url} [time elapsed: {te}]'. \
        format(task=args['task_name'], status=response.status,
               url=url, te=str(time_elapsed)))
      return response.status
    elif response.status == 302:
      redirect_url = response.getheader('Location')
      logger.info(
        "Task %s asked us to redirect to %s, so retrying there." % (
          args['task_name'], redirect_url))
      url = urlparse(redirect_url)
      if redirects_left == 0:
        raise task.retry(countdown=wait_time)
      redirects_left -= 1
    else:
      message = ('Received a {status} for {task}. '
                 'Retrying in {wait} secs.'.format(status=response.status,
                                                   task=args['task_name'],
                                                   wait=wait_time))
      logger.warning(message)
      raise task.retry(countdown=wait_time)
コード例 #7
0
ファイル: __init__.py プロジェクト: akshatknsl/synaps
    def __call__(self, req):
        request_id = context.generate_request_id()
        signature = req.params.get('Signature')
        if not signature:
            msg = _("Signature not provided")
            return faults.ec2_error_response(request_id, "Unauthorized", msg,
                                             status=400)
        access = req.params.get('AWSAccessKeyId')
        if not access:
            msg = _("Access key not provided")
            return faults.ec2_error_response(request_id, "Unauthorized", msg,
                                             status=400)

        # Make a copy of args for authentication and signature verification.
        auth_params = dict(req.params)
        # Not part of authentication args
        auth_params.pop('Signature')

        cred_dict = {
            'access': access,
            'signature': signature,
            'host': req.host,
            'verb': req.method,
            'path': req.path,
            'params': auth_params,
        }
        if "ec2" in FLAGS.keystone_ec2_url:
            creds = {'ec2Credentials': cred_dict}
        else:
            creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}}
        creds_json = jsonutils.dumps(creds)
        headers = {'Content-Type': 'application/json'}

        o = urlparse.urlparse(FLAGS.keystone_ec2_url)
        if o.scheme == "http":
            conn = httplib.HTTPConnection(o.netloc)
        else:
            conn = httplib.HTTPSConnection(o.netloc)
        conn.request('POST', o.path, body=creds_json, headers=headers)
        response = conn.getresponse()
        data = response.read()
        if response.status != 200:
            if response.status == 401:
                msg = response.reason
            else:
                msg = _("Failure communicating with keystone")
            return faults.ec2_error_response(request_id, "Unauthorized", msg,
                                             status=400)
        result = jsonutils.loads(data)
        conn.close()

        try:
            token_id = result['access']['token']['id']
            user_id = result['access']['user']['id']
            project_id = result['access']['token']['tenant']['id']
            user_name = result['access']['user'].get('name')
            project_name = result['access']['token']['tenant'].get('name')
            roles = [role['name'] for role
                     in result['access']['user']['roles']]
        except (AttributeError, KeyError) as e:
            LOG.exception(_("Keystone failure: %s") % e)
            msg = _("Failure communicating with keystone")
            return faults.ec2_error_response(request_id, "Unauthorized", msg,
                                             status=400)

        remote_address = req.remote_addr
        if FLAGS.use_forwarded_for:
            remote_address = req.headers.get('X-Forwarded-For',
                                             remote_address)

        catalog = result['access']['serviceCatalog']
        ctxt = context.RequestContext(user_id,
                                      project_id,
                                      #user_name=user_name,
                                      #project_name=project_name,
                                      roles=roles,
                                      auth_token=token_id,
                                      remote_address=remote_address)
                                      #service_catalog=catalog)

        req.environ['synaps.context'] = ctxt

        return self.application