def request(self, method, path, **kwargs):
        """Fakes out several http responses.

        If a POST request is made, we assume the calling code is trying
        to get a new admin token.

        If a GET request is made to validate a token, return success
        if the token is 'token1'. If a different token is provided, return
        a 404, indicating an unknown (therefore unauthorized) token.

        """
        FakeHTTPConnection.last_requested_url = path
        if method == 'POST':
            status = 200
            body = jsonutils.dumps({
                'access': {
                    'token': {
                        'id': 'admin_token2'
                    },
                },
            })

        else:
            token_id = path.rsplit('/', 1)[1]
            if token_id in TOKEN_RESPONSES.keys():
                status = 200
                body = jsonutils.dumps(TOKEN_RESPONSES[token_id])
            elif token_id == "revoked":
                status = 200
                body = SIGNED_REVOCATION_LIST
            else:
                status = 404
                body = str()

        self.resp = FakeHTTPResponse(status, body)
Ejemplo n.º 2
0
    def request(self, method, path, **kwargs):
        """Fakes out several http responses.

        If a POST request is made, we assume the calling code is trying
        to get a new admin token.

        If a GET request is made to validate a token, return success
        if the token is 'token1'. If a different token is provided, return
        a 404, indicating an unknown (therefore unauthorized) token.

        """
        FakeHTTPConnection.last_requested_url = path
        if method == 'POST':
            status = 200
            body = jsonutils.dumps({
                'access': {
                    'token': {'id': 'admin_token2'},
                },
            })

        else:
            token_id = path.rsplit('/', 1)[1]
            if token_id in TOKEN_RESPONSES.keys():
                status = 200
                body = jsonutils.dumps(TOKEN_RESPONSES[token_id])
            elif token_id == "revoked":
                status = 200
                body = SIGNED_REVOCATION_LIST
            else:
                status = 404
                body = str()

        self.resp = FakeHTTPResponse(status, body)
Ejemplo n.º 3
0
    def test_fetch_revocation_list_with_expire(self):
        # first response to revocation list should return 401 Unauthorized
        # to pretend to be an expired token
        resp1 = FakeHTTPResponse(200, jsonutils.dumps({
            'access': {
                'token': {'id': 'admin_token2'},
            },
        }))
        resp2 = FakeHTTPResponse(401, jsonutils.dumps(''))
        resp3 = FakeHTTPResponse(200, jsonutils.dumps({
            'access': {
                'token': {'id': 'admin_token2'},
            },
        }))
        resp4 = FakeHTTPResponse(200, SIGNED_REVOCATION_LIST)

        # first get_admin_token() call
        FAKE_RESPONSE_STACK.append(resp1)
        # request revocation list, get "unauthorized" due to simulated expired
        # token
        FAKE_RESPONSE_STACK.append(resp2)
        # request a new admin_token
        FAKE_RESPONSE_STACK.append(resp3)
        # request revocation list, get the revocation list properly
        FAKE_RESPONSE_STACK.append(resp4)

        fetched_list = jsonutils.loads(self.middleware.fetch_revocation_list())
        self.assertEqual(fetched_list, REVOCATION_LIST)
    def request(self, method, path, **kwargs):
        """Fakes out several http responses.

        If a POST request is made, we assume the calling code is trying
        to get a new admin token.

        If a GET request is made to validate a token, return success
        if the token is 'token1'. If a different token is provided, return
        a 404, indicating an unknown (therefore unauthorized) token.

        """
        if method == "POST":
            status = 200
            body = jsonutils.dumps({"access": {"token": {"id": "admin_token2"}}})

        else:
            token_id = path.rsplit("/", 1)[1]
            if token_id in TOKEN_RESPONSES.keys():
                status = 200
                body = jsonutils.dumps(TOKEN_RESPONSES[token_id])
            else:
                status = 404
                body = str()

        self.resp = FakeHTTPResponse(status, body)
Ejemplo n.º 5
0
def convert_ec2_to_v3_credential(ec2credential):
    blob = {'access': ec2credential.access,
            'secret': ec2credential.secret}
    return {'id': hash_access_key(ec2credential.access),
            'user_id': ec2credential.user_id,
            'project_id': ec2credential.tenant_id,
            'blob': jsonutils.dumps(blob),
            'type': 'ec2',
            'extra': jsonutils.dumps({})}
Ejemplo n.º 6
0
def convert_ec2_to_v3_credential(ec2credential):
    blob = {'access': ec2credential.access,
            'secret': ec2credential.secret}
    return {'id': hash_access_key(ec2credential.access),
            'user_id': ec2credential.user_id,
            'project_id': ec2credential.tenant_id,
            'blob': jsonutils.dumps(blob),
            'type': 'ec2',
            'extra': jsonutils.dumps({})}
Ejemplo n.º 7
0
    def __call__(self, target, creds, enforcer):
        """Check http: rules by calling to a remote server.

        This example implementation simply verifies that the response
        is exactly 'True'.
        """

        url = ("http:" + self.match) % target
        data = {"target": jsonutils.dumps(target), "credentials": jsonutils.dumps(creds)}
        post_data = urlparse.urlencode(data)
        f = urlrequest.urlopen(url, post_data)
        return f.read() == "True"
Ejemplo n.º 8
0
    def __call__(self, target, creds, enforcer):
        """Check http: rules by calling to a remote server.

        This example implementation simply verifies that the response
        is exactly 'True'.
        """

        url = ('http:' + self.match) % target
        data = {'target': jsonutils.dumps(target),
                'credentials': jsonutils.dumps(creds)}
        post_data = urlparse.urlencode(data)
        f = urlrequest.urlopen(url, post_data)
        return f.read() == "True"
Ejemplo n.º 9
0
    def __call__(self, target, creds):
        """
        Check http: rules by calling to a remote server.

        This example implementation simply verifies that the response
        is exactly 'True'.
        """

        url = ('http:' + self.match) % target
        data = {'target': jsonutils.dumps(target),
                'credentials': jsonutils.dumps(creds)}
        post_data = urllib.urlencode(data)
        f = urllib2.urlopen(url, post_data)
        return f.read() == "True"
Ejemplo n.º 10
0
    def _check_http(self, match, target_dict, cred_dict):
        """Check http: rules by calling to a remote server.

        This example implementation simply verifies that the response is
        exactly 'True'. A custom brain using response codes could easily
        be implemented.

        """
        url = match % target_dict
        data = {'target': jsonutils.dumps(target_dict),
                'credentials': jsonutils.dumps(cred_dict)}
        post_data = urllib.urlencode(data)
        f = urllib2.urlopen(url, post_data)
        return f.read() == "True"
Ejemplo n.º 11
0
    def _pack_json_msg(self, msg):
        """Qpid cannot serialize dicts containing strings longer than 65535
           characters.  This function dumps the message content to a JSON
           string, which Qpid is able to handle.

        :param msg: May be either a Qpid Message object or a bare dict.
        :returns: A Qpid Message with its content field JSON encoded.
        """
        try:
            msg.content = jsonutils.dumps(msg.content)
        except AttributeError:
            # Need to have a Qpid message so we can set the content_type.
            msg = qpid_messaging.Message(jsonutils.dumps(msg))
        msg.content_type = JSON_CONTENT_TYPE
        return msg
Ejemplo n.º 12
0
    def _pack_json_msg(self, msg):
        """Qpid cannot serialize dicts containing strings longer than 65535
           characters.  This function dumps the message content to a JSON
           string, which Qpid is able to handle.

        :param msg: May be either a Qpid Message object or a bare dict.
        :returns: A Qpid Message with its content field JSON encoded.
        """
        try:
            msg.content = jsonutils.dumps(msg.content)
        except AttributeError:
            # Need to have a Qpid message so we can set the content_type.
            msg = qpid_messaging.Message(jsonutils.dumps(msg))
        msg.content_type = JSON_CONTENT_TYPE
        return msg
Ejemplo n.º 13
0
def render_response(body=None, status=None, headers=None):
    """Forms a WSGI response."""
    if headers is None:
        headers = []
    else:
        headers = list(headers)
    headers.append(('Vary', 'X-Auth-Token'))

    if body is None:
        body = ''
        status = status or (204, 'No Content')
    else:
        content_types = [v for h, v in headers if h == 'Content-Type']
        if content_types:
            content_type = content_types[0]
        else:
            content_type = None
        if content_type is None or content_type == 'application/json':
            body = jsonutils.dumps(body, cls=utils.SmarterEncoder)
            if content_type is None:
                headers.append(('Content-Type', 'application/json'))
        status = status or (200, 'OK')

    return webob.Response(body=body,
                          status='%s %s' % status,
                          headerlist=headers)
Ejemplo n.º 14
0
    def get_ticket(self, source, target, crypto, key):

        # prepare metadata
        md = {'requestor': source,
              'target': target,
              'timestamp': time.time(),
              'nonce': struct.unpack('Q', os.urandom(8))[0]}
        metadata = base64.b64encode(jsonutils.dumps(md))

        # sign metadata
        signature = crypto.sign(key, metadata)

        # HTTP request
        reply = self._get_ticket({'metadata': metadata,
                                  'signature': signature})

        # verify reply
        signature = crypto.sign(key, (reply['metadata'] + reply['ticket']))
        if signature != reply['signature']:
            raise InvalidEncryptedTicket(md['source'], md['destination'])
        md = jsonutils.loads(base64.b64decode(reply['metadata']))
        if ((md['source'] != source or
             md['destination'] != target or
             md['expiration'] < time.time())):
            raise InvalidEncryptedTicket(md['source'], md['destination'])

        # return ticket data
        tkt = jsonutils.loads(crypto.decrypt(key, reply['ticket']))

        return tkt, md['expiration']
Ejemplo n.º 15
0
    def create_credential(self, context, user_id, tenant_id):
        """Create a secret/access pair for use with ec2 style auth.

        Generates a new set of credentials that map the user/tenant
        pair.

        :param context: standard context
        :param user_id: id of user
        :param tenant_id: id of tenant
        :returns: credential: dict of ec2 credential
        """

        self.identity_api.get_user(user_id)
        self.assignment_api.get_project(tenant_id)
        trust_id = self._get_trust_id_for_request(context)
        blob = {"access": uuid.uuid4().hex, "secret": uuid.uuid4().hex, "trust_id": trust_id}
        credential_id = utils.hash_access_key(blob["access"])
        cred_ref = {
            "user_id": user_id,
            "project_id": tenant_id,
            "blob": jsonutils.dumps(blob),
            "id": credential_id,
            "type": "ec2",
        }
        self.credential_api.create_credential(credential_id, cred_ref)
        return {"credential": self._convert_v3_to_ec2_credential(cred_ref)}
Ejemplo n.º 16
0
    def encode(self, version, target, json_msg):
        """This is the main encoding function.

        It takes a target and a message and returns a tuple consisting of a
        JSON serialized metadata object, a JSON serialized (and optionally
        encrypted) message, and a signature.

        :param version: the current envelope version
        :param target: The name of the target service (usually with hostname)
        :param json_msg: a serialized json message object
        """
        ticket = self._get_ticket(target)

        metadata = jsonutils.dumps({'source': self._name,
                                    'destination': target,
                                    'timestamp': time.time(),
                                    'nonce': _get_nonce(),
                                    'esek': ticket.esek,
                                    'encryption': self._encrypt})

        message = json_msg
        if self._encrypt:
            message = self._crypto.encrypt(ticket.ekey, message)

        signature = self._crypto.sign(ticket.skey,
                                      version + metadata + message)

        return (metadata, message, signature)
Ejemplo n.º 17
0
    def _json_request(self, method, path, body=None, additional_headers=None):
        """HTTP request helper used to make json requests.

        :param method: http method
        :param path: relative request url
        :param body: dict to encode to json as request body. Optional.
        :param additional_headers: dict of additional headers to send with
                                   http request. Optional.
        :return (http response object, response body parsed as json)
        :raise ServerError when unable to communicate with keystone

        """
        conn = self._get_http_connection()

        kwargs = {
            'headers': {
                'Content-type': 'application/json',
                'Accept': 'application/json',
            },
        }

        if additional_headers:
            kwargs['headers'].update(additional_headers)

        if body:
            kwargs['body'] = jsonutils.dumps(body)

        full_path = self.auth_admin_prefix + path
        try:
            conn.request(method, full_path, **kwargs)
            response = conn.getresponse()
            body = response.read()
        except Exception, e:
            LOG.error('HTTP connection exception: %s' % e)
            raise ServiceError('Unable to communicate with keystone')
Ejemplo n.º 18
0
 def _assign_unique_id(self, ref, trust_id=None):
     # Generates and assigns a unique identifier to
     # a credential reference.
     if ref.get('type', '').lower() == 'ec2':
         try:
             blob = jsonutils.loads(ref.get('blob'))
         except (ValueError, TypeError):
             raise exception.ValidationError(
                 message=_('Invalid blob in credential'))
         if not blob or not isinstance(blob, dict):
             raise exception.ValidationError(attribute='blob',
                                             target='credential')
         if blob.get('access') is None:
             raise exception.ValidationError(attribute='access',
                                             target='blob')
         ret_ref = ref.copy()
         ret_ref['id'] = hashlib.sha256(blob['access']).hexdigest()
         # Update the blob with the trust_id, so credentials created
         # with a trust scoped token will result in trust scoped
         # tokens when authentication via ec2tokens happens
         if trust_id is not None:
             blob['trust_id'] = trust_id
             ret_ref['blob'] = jsonutils.dumps(blob)
         return ret_ref
     else:
         return super(CredentialV3, self)._assign_unique_id(ref)
Ejemplo n.º 19
0
 def _add_to_revocation_list(self, data):
     data_json = jsonutils.dumps(data)
     if not self.client.append(self.revocation_key, ",%s" % data_json):
         if not self.client.add(self.revocation_key, data_json):
             if not self.client.append(self.revocation_key, ",%s" % data_json):
                 msg = _("Unable to add token to revocation list.")
                 raise exception.UnexpectedError(msg)
Ejemplo n.º 20
0
    def __init__(self, session, node_name, node_opts=None):
        """Init the Publisher class with the exchange_name, routing_key,
        and other options
        """
        self.sender = None
        self.session = session

        addr_opts = {
            "create": "always",
            "node": {
                "type": "topic",
                "x-declare": {
                    "durable": False,
                    # auto-delete isn't implemented for exchanges in qpid,
                    # but put in here anyway
                    "auto-delete": True,
                },
            },
        }
        if node_opts:
            addr_opts["node"]["x-declare"].update(node_opts)

        self.address = "%s ; %s" % (node_name, jsonutils.dumps(addr_opts))

        self.reconnect(session)
Ejemplo n.º 21
0
def render_response(body=None, status=None, headers=None, method=None):
    """Forms a WSGI response."""
    headers = headers or []
    headers.append(('Vary', 'X-Auth-Token'))

    if body is None:
        body = ''
        status = status or (204, 'No Content')
    else:
        body = jsonutils.dumps(body, cls=utils.SmarterEncoder)
        headers.append(('Content-Type', 'application/json'))
        status = status or (200, 'OK')

    resp = webob.Response(body=body,
                          status='%s %s' % status,
                          headerlist=headers)

    if method == 'HEAD':
        # NOTE(morganfainberg): HEAD requests should return the same status
        # as a GET request and same headers (including content-type and
        # content-length). The webob.Response object automatically changes
        # content-length (and other headers) if the body is set to b''. Capture
        # all headers and reset them on the response object after clearing the
        # body. The body can only be set to a binary-type (not TextType or
        # NoneType), so b'' is used here and should be compatible with
        # both py2x and py3x.
        stored_headers = resp.headers.copy()
        resp.body = b''
        for header, value in six.iteritems(stored_headers):
            resp.headers[header] = value

    return resp
Ejemplo n.º 22
0
def render_response(body=None, status=None, headers=None, method=None):
    """Forms a WSGI response."""
    headers = headers or []
    headers.append(('Vary', 'X-Auth-Token'))

    if body is None:
        body = ''
        status = status or (204, 'No Content')
    else:
        body = jsonutils.dumps(body, cls=utils.SmarterEncoder)
        headers.append(('Content-Type', 'application/json'))
        status = status or (200, 'OK')

    resp = webob.Response(body=body,
                          status='%s %s' % status,
                          headerlist=headers)

    if method == 'HEAD':
        # NOTE(morganfainberg): HEAD requests should return the same status
        # as a GET request and same headers (including content-type and
        # content-length). The webob.Response object automatically changes
        # content-length (and other headers) if the body is set to b''. Capture
        # all headers and reset them on the response object after clearing the
        # body. The body can only be set to a binary-type (not TextType or
        # NoneType), so b'' is used here and should be compatible with
        # both py2x and py3x.
        stored_headers = resp.headers.copy()
        resp.body = b''
        for header, value in six.iteritems(stored_headers):
            resp.headers[header] = value

    return resp
    def setUp(self, expected_env=None):
        expected_env = expected_env or {}

        conf = {
            'admin_token': 'admin_token1',
            'auth_host': 'keystone.example.com',
            'auth_port': 1234,
            'auth_admin_prefix': '/testadmin',
            'signing_dir': 'signing',
        }

        self.middleware = auth_token.AuthProtocol(FakeApp(expected_env), conf)
        self.middleware.http_client_class = FakeHTTPConnection
        self.middleware._iso8601 = iso8601

        self.response_status = None
        self.response_headers = None
        self.middleware.revoked_file_name = tempfile.mkstemp()[1]
        self.middleware.token_revocation_list_cache_timeout =\
            datetime.timedelta(days=1)
        self.middleware.token_revocation_list = jsonutils.dumps({
            "revoked": [],
            "extra":
            "success"
        })

        globals()['SIGNED_REVOCATION_LIST'] =\
            globals()['VALID_SIGNED_REVOCATION_LIST']

        super(BaseAuthTokenMiddlewareTest, self).setUp()
Ejemplo n.º 24
0
    def format(self, record):
        message = {
            'message': record.getMessage(),
            'asctime': self.formatTime(record, self.datefmt),
            'name': record.name,
            'msg': record.msg,
            'args': record.args,
            'levelname': record.levelname,
            'levelno': record.levelno,
            'pathname': record.pathname,
            'filename': record.filename,
            'module': record.module,
            'lineno': record.lineno,
            'funcname': record.funcName,
            'created': record.created,
            'msecs': record.msecs,
            'relative_created': record.relativeCreated,
            'thread': record.thread,
            'thread_name': record.threadName,
            'process_name': record.processName,
            'process': record.process,
            'traceback': None
        }

        if hasattr(record, 'extra'):
            message['extra'] = record.extra

        if record.exc_info:
            message['traceback'] = self.formatException(record.exc_info)

        return jsonutils.dumps(message)
Ejemplo n.º 25
0
    def _json_request(self, method, path, body=None, additional_headers=None):
        """HTTP request helper used to make json requests.

        :param method: http method
        :param path: relative request url
        :param body: dict to encode to json as request body. Optional.
        :param additional_headers: dict of additional headers to send with
                                   http request. Optional.
        :return (http response object, response body parsed as json)
        :raise ServerError when unable to communicate with keystone

        """
        conn = self._get_http_connection()

        kwargs = {
            'headers': {
                'Content-type': 'application/json',
                'Accept': 'application/json',
            },
        }

        if additional_headers:
            kwargs['headers'].update(additional_headers)

        if body:
            kwargs['body'] = jsonutils.dumps(body)

        full_path = self.auth_admin_prefix + path
        try:
            conn.request(method, full_path, **kwargs)
            response = conn.getresponse()
            body = response.read()
        except Exception, e:
            LOG.error('HTTP connection exception: %s' % e)
            raise ServiceError('Unable to communicate with keystone')
Ejemplo n.º 26
0
    def __init__(self, conf, session, node_name, node_opts=None):
        """Init the Publisher class with the exchange_name, routing_key,
        and other options
        """
        self.sender = None
        self.session = session

        if conf.qpid_topology_version == 1:
            addr_opts = {
                "create": "always",
                "node": {
                    "type": "topic",
                    "x-declare": {
                        "durable": False,
                        # auto-delete isn't implemented for exchanges in qpid,
                        # but put in here anyway
                        "auto-delete": True,
                    },
                },
            }
            if node_opts:
                addr_opts["node"]["x-declare"].update(node_opts)

            self.address = "%s ; %s" % (node_name, jsonutils.dumps(addr_opts))
        elif conf.qpid_topology_version == 2:
            self.address = node_name
        else:
            raise_invalid_topology_version()

        self.reconnect(session)
Ejemplo n.º 27
0
 def _assign_unique_id(self, ref, trust_id=None):
     # Generates and assigns a unique identifier to
     # a credential reference.
     if ref.get('type', '').lower() == 'ec2':
         try:
             blob = jsonutils.loads(ref.get('blob'))
         except (ValueError, TypeError):
             raise exception.ValidationError(
                 message=_('Invalid blob in credential'))
         if not blob or not isinstance(blob, dict):
             raise exception.ValidationError(attribute='blob',
                                             target='credential')
         if blob.get('access') is None:
             raise exception.ValidationError(attribute='access',
                                             target='blob')
         ret_ref = ref.copy()
         ret_ref['id'] = hashlib.sha256(blob['access']).hexdigest()
         # Update the blob with the trust_id, so credentials created
         # with a trust scoped token will result in trust scoped
         # tokens when authentication via ec2tokens happens
         if trust_id is not None:
             blob['trust_id'] = trust_id
             ret_ref['blob'] = jsonutils.dumps(blob)
         return ret_ref
     else:
         return super(CredentialV3, self)._assign_unique_id(ref)
Ejemplo n.º 28
0
def _migrate_enabled_to_extra(migrate_engine, endpoint_table):
    """Get enabled value from 'enabled' column and put it in 'extra' JSON.

    Only put the enabled value to the 'extra' JSON if it's False, since the
    default is True.

    """

    eps = list(endpoint_table.select().execute())

    for ep in eps:

        if ep.enabled:
            # Nothing to do since the endpoint is enabled.
            continue

        extra_dict = jsonutils.loads(ep.extra)
        extra_dict['enabled'] = False

        new_values = {
            'extra': jsonutils.dumps(extra_dict),
        }
        f = endpoint_table.c.id == ep.id
        update = endpoint_table.update().where(f).values(new_values)
        migrate_engine.execute(update)
Ejemplo n.º 29
0
def _migrate_enabled_from_extra(migrate_engine, endpoint_table):
    """Remove `enabled` from `extra`, put it in the `enabled` column."""

    eps = list(endpoint_table.select().execute())

    for ep in eps:
        extra_dict = jsonutils.loads(ep.extra)

        if 'enabled' not in extra_dict:
            # `enabled` and `extra` are already as expected.
            continue

        enabled = extra_dict.pop('enabled')

        if enabled is None:
            enabled = True
        else:
            enabled = strutils.bool_from_string(enabled, default=True)

        new_values = {
            'enabled': enabled,
            'extra': jsonutils.dumps(extra_dict),
        }
        f = endpoint_table.c.id == ep.id
        update = endpoint_table.update().where(f).values(new_values)
        migrate_engine.execute(update)
Ejemplo n.º 30
0
def good_request(cls, method, path, **kwargs):
    cls.status = 201
    ret = {'access': {'token':
                      {'id': 'TOKEN_ID',
                       'tenant': {'id': 'TENANT_ID'}}}}
    body = jsonutils.dumps(ret)
    cls.resp = FakeHTTPResponse(cls.status, body)
Ejemplo n.º 31
0
    def create_credential(self, context, user_id, tenant_id):
        """Create a secret/access pair for use with ec2 style auth.

        Generates a new set of credentials that map the user/tenant
        pair.

        :param context: standard context
        :param user_id: id of user
        :param tenant_id: id of tenant
        :returns: credential: dict of ec2 credential
        """

        self.identity_api.get_user(user_id)
        self.assignment_api.get_project(tenant_id)
        trust_id = self._get_trust_id_for_request(context)
        blob = {'access': uuid.uuid4().hex,
                'secret': uuid.uuid4().hex,
                'trust_id': trust_id}
        credential_id = utils.hash_access_key(blob['access'])
        cred_ref = {'user_id': user_id,
                    'project_id': tenant_id,
                    'blob': jsonutils.dumps(blob),
                    'id': credential_id,
                    'type': 'ec2'}
        self.credential_api.create_credential(credential_id, cred_ref)
        return {'credential': self._convert_v3_to_ec2_credential(cred_ref)}
Ejemplo n.º 32
0
    def setUp(self, expected_env=None):
        expected_env = expected_env or {}

        conf = {
            'admin_token': 'admin_token1',
            'auth_host': 'keystone.example.com',
            'auth_port': 1234,
            'auth_admin_prefix': '/testadmin',
            'signing_dir': CERTDIR,
        }

        self.middleware = auth_token.AuthProtocol(FakeApp(expected_env), conf)
        self.middleware.http_client_class = FakeHTTPConnection
        self.middleware._iso8601 = iso8601

        self.response_status = None
        self.response_headers = None
        self.middleware.revoked_file_name = tempfile.mkstemp()[1]
        cache_timeout = datetime.timedelta(days=1)
        self.middleware.token_revocation_list_cache_timeout = cache_timeout
        self.middleware.token_revocation_list = jsonutils.dumps(
            {"revoked": [], "extra": "success"})

        signed_list = 'SIGNED_REVOCATION_LIST'
        valid_signed_list = 'VALID_SIGNED_REVOCATION_LIST'
        globals()[signed_list] = globals()[valid_signed_list]

        super(BaseAuthTokenMiddlewareTest, self).setUp()
Ejemplo n.º 33
0
    def create_credential(self, context, user_id, tenant_id):
        """Create a secret/access pair for use with ec2 style auth.

        Generates a new set of credentials that map the user/tenant
        pair.

        :param context: standard context
        :param user_id: id of user
        :param tenant_id: id of tenant
        :returns: credential: dict of ec2 credential
        """
        if not self._is_admin(context):
            self._assert_identity(context, user_id)

        self._assert_valid_user_id(user_id)
        self._assert_valid_project_id(tenant_id)
        trust_id = self._get_trust_id_for_request(context)
        blob = {'access': uuid.uuid4().hex,
                'secret': uuid.uuid4().hex,
                'trust_id': trust_id}
        credential_id = utils.hash_access_key(blob['access'])
        cred_ref = {'user_id': user_id,
                    'project_id': tenant_id,
                    'blob': jsonutils.dumps(blob),
                    'id': credential_id,
                    'type': 'ec2'}
        self.credential_api.create_credential(credential_id, cred_ref)
        return {'credential': self._convert_v3_to_ec2_credential(cred_ref)}
Ejemplo n.º 34
0
def serialize_msg(raw_msg):
    # NOTE(russellb) See the docstring for _RPC_ENVELOPE_VERSION for more
    # information about this format.
    msg = {_VERSION_KEY: _RPC_ENVELOPE_VERSION,
           _MESSAGE_KEY: jsonutils.dumps(raw_msg)}

    return msg
Ejemplo n.º 35
0
    def format(self, record):
        message = {'message': record.getMessage(),
                   'asctime': self.formatTime(record, self.datefmt),
                   'name': record.name,
                   'msg': record.msg,
                   'args': record.args,
                   'levelname': record.levelname,
                   'levelno': record.levelno,
                   'pathname': record.pathname,
                   'filename': record.filename,
                   'module': record.module,
                   'lineno': record.lineno,
                   'funcname': record.funcName,
                   'created': record.created,
                   'msecs': record.msecs,
                   'relative_created': record.relativeCreated,
                   'thread': record.thread,
                   'thread_name': record.threadName,
                   'process_name': record.processName,
                   'process': record.process,
                   'traceback': None}

        if hasattr(record, 'extra'):
            message['extra'] = record.extra

        if record.exc_info:
            message['traceback'] = self.formatException(record.exc_info)

        return jsonutils.dumps(message)
Ejemplo n.º 36
0
def _migrate_enabled_to_extra(migrate_engine, endpoint_table):
    """Get enabled value from 'enabled' column and put it in 'extra' JSON.

    Only put the enabled value to the 'extra' JSON if it's False, since the
    default is True.

    """

    eps = list(endpoint_table.select().execute())

    for ep in eps:

        if ep.enabled:
            # Nothing to do since the endpoint is enabled.
            continue

        extra_dict = jsonutils.loads(ep.extra)
        extra_dict['enabled'] = False

        new_values = {
            'extra': jsonutils.dumps(extra_dict),
        }
        f = endpoint_table.c.id == ep.id
        update = endpoint_table.update().where(f).values(new_values)
        migrate_engine.execute(update)
Ejemplo n.º 37
0
def _migrate_enabled_from_extra(migrate_engine, endpoint_table):
    """Remove `enabled` from `extra`, put it in the `enabled` column."""

    eps = list(endpoint_table.select().execute())

    for ep in eps:
        extra_dict = jsonutils.loads(ep.extra)

        if 'enabled' not in extra_dict:
            # `enabled` and `extra` are already as expected.
            continue

        enabled = extra_dict.pop('enabled')

        if enabled is None:
            enabled = True
        else:
            enabled = strutils.bool_from_string(enabled, default=True)

        new_values = {
            'enabled': enabled,
            'extra': jsonutils.dumps(extra_dict),
        }
        f = endpoint_table.c.id == ep.id
        update = endpoint_table.update().where(f).values(new_values)
        migrate_engine.execute(update)
Ejemplo n.º 38
0
 def request(self, method, path, **kwargs):
     ret = {"error":
            {"message": "EC2 access key not found.",
             "code": 401,
             "title": "Unauthorized"}}
     body = jsonutils.dumps(ret)
     self.status = 403
     self.resp = FakeHTTPResponse(self.status, body)
Ejemplo n.º 39
0
 def _add_to_revocation_list(self, data):
     data_json = jsonutils.dumps(data)
     if not self.client.append(self.revocation_key, ',%s' % data_json):
         if not self.client.add(self.revocation_key, data_json):
             if not self.client.append(self.revocation_key,
                                       ',%s' % data_json):
                 msg = _('Unable to add token to revocation list.')
                 raise exception.UnexpectedError(msg)
 def request(self, method, path, **kwargs):
     if self.status == 503:
         raise Exception
     ret = {'access': {'token': {'id': 'TOKEN_ID',
                                 'tenant': {'id':  'TENANT_ID'}}}}
     body = jsonutils.dumps(ret)
     status = self.status
     self.resp = FakeHTTPResponse(status, body)
Ejemplo n.º 41
0
 def request(self, method, path, **kwargs):
     if self.status == 503:
         raise Exception
     ret = {'access': {'token': {'id': 'TOKEN_ID',
                                 'tenant': {'id': 'TENANT_ID'}}}}
     body = jsonutils.dumps(ret)
     status = self.status
     self.resp = FakeHTTPResponse(status, body)
Ejemplo n.º 42
0
 def create_token(self, token_id, data):
     data_copy = copy.deepcopy(data)
     user_id = data_copy.get('user', None)
     if 'expires' not in data_copy:
         data_copy['expires'] = self._get_default_expire_time()
     json_data = jsonutils.dumps(data_copy)
     self._set_keys(user_id, token_id, json_data, self.ttl_seconds)
     return data_copy
Ejemplo n.º 43
0
    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'}

        verify = True
        if CONF.keystone_ec2_insecure:
            verify = False
        elif CONF.keystone_ec2_cafile:
            verify = CONF.keystone_ec2_cafile

        cert = None
        if CONF.keystone_ec2_certfile and CONF.keystone_ec2_keyfile:
            cert = (CONF.keystone_ec2_certfile, CONF.keystone_ec2_keyfile)
        elif CONF.keystone_ec2_certfile:
            cert = CONF.keystone_ec2_certfile

        response = requests.post(CONF.keystone_ec2_url,
                                 data=creds_json,
                                 headers=headers,
                                 verify=verify,
                                 cert=cert)

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

        result = response.json()
        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
Ejemplo n.º 44
0
 def _get_token_id(self, token_data):
     try:
         token_id = cms.pkiz_sign(jsonutils.dumps(token_data),
                                  CONF.signing.certfile,
                                  CONF.signing.keyfile)
         return token_id
     except environment.subprocess.CalledProcessError:
         LOG.exception(ERROR_MESSAGE)
         raise exception.UnexpectedError(ERROR_MESSAGE)
Ejemplo n.º 45
0
    def __init__(self, conf, session, callback, node_name, node_opts,
                 link_name, link_opts):
        """Declare a queue on an amqp session.

        'session' is the amqp session to use
        'callback' is the callback to call when messages are received
        'node_name' is the first part of the Qpid address string, before ';'
        'node_opts' will be applied to the "x-declare" section of "node"
                    in the address string.
        'link_name' goes into the "name" field of the "link" in the address
                    string
        'link_opts' will be applied to the "x-declare" section of "link"
                    in the address string.
        """
        self.callback = callback
        self.receiver = None
        self.session = None

        if conf.qpid_topology_version == 1:
            addr_opts = {
                "create": "always",
                "node": {
                    "type": "topic",
                    "x-declare": {
                        "durable": True,
                        "auto-delete": True,
                    },
                },
                "link": {
                    "durable": True,
                    "x-declare": {
                        "durable": False,
                        "auto-delete": True,
                        "exclusive": False,
                    },
                },
            }
            addr_opts["node"]["x-declare"].update(node_opts)
        elif conf.qpid_topology_version == 2:
            addr_opts = {
                "link": {
                    "x-declare": {
                        "auto-delete": True,
                        "exclusive": False,
                    },
                },
            }
        else:
            raise_invalid_topology_version()

        addr_opts["link"]["x-declare"].update(link_opts)
        if link_name:
            addr_opts["link"]["name"] = link_name

        self.address = "%s ; %s" % (node_name, jsonutils.dumps(addr_opts))

        self.connect(session)
Ejemplo n.º 46
0
def serialize_msg(raw_msg):
    # NOTE(russellb) See the docstring for _RPC_ENVELOPE_VERSION for more
    # information about this format.
    msg = {
        _VERSION_KEY: _RPC_ENVELOPE_VERSION,
        _MESSAGE_KEY: jsonutils.dumps(raw_msg)
    }

    return msg
Ejemplo n.º 47
0
 def create_mapping(self, mapping_id, mapping):
     session = db_session.get_session()
     ref = {}
     ref['id'] = mapping_id
     ref['rules'] = jsonutils.dumps(mapping.get('rules'))
     with session.begin():
         mapping_ref = MappingModel.from_dict(ref)
         session.add(mapping_ref)
     return mapping_ref.to_dict()
Ejemplo n.º 48
0
 def create_mapping(self, mapping_id, mapping):
     session = db_session.get_session()
     ref = {}
     ref['id'] = mapping_id
     ref['rules'] = jsonutils.dumps(mapping.get('rules'))
     with session.begin():
         mapping_ref = MappingModel.from_dict(ref)
         session.add(mapping_ref)
     return mapping_ref.to_dict()
Ejemplo n.º 49
0
 def test_cas_failure(self):
     self.token_api.driver.client.reject_cas = True
     token_id = uuid.uuid4().hex
     user_id = unicode(uuid.uuid4().hex)
     user_key = self.token_api.driver._prefix_user_id(user_id)
     token_data = jsonutils.dumps(token_id)
     self.assertRaises(exception.UnexpectedError,
                       self.token_api.driver._update_user_list_with_cas,
                       user_key, token_data)
 def test_is_signed_token_revoked_returns_false(self):
     #explicitly setting an empty revocation list here to document intent
     self.middleware.token_revocation_list = jsonutils.dumps({
         "revoked": [],
         "extra":
         "success"
     })
     result = self.middleware.is_signed_token_revoked(REVOKED_TOKEN)
     self.assertFalse(result)
def setUpModule(self):
    signing_path = os.path.join(os.path.dirname(__file__), 'signing')
    with open(os.path.join(signing_path, 'auth_token_scoped.pem')) as f:
        self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read())
    with open(os.path.join(signing_path, 'auth_token_unscoped.pem')) as f:
        self.SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read())
    with open(os.path.join(signing_path, 'auth_token_revoked.pem')) as f:
        self.REVOKED_TOKEN = cms.cms_to_token(f.read())
    self.REVOKED_TOKEN_HASH = utils.hash_signed_token(self.REVOKED_TOKEN)
    with open(os.path.join(signing_path, 'revocation_list.json')) as f:
        self.REVOCATION_LIST = jsonutils.loads(f.read())
    with open(os.path.join(signing_path, 'revocation_list.pem')) as f:
        self.VALID_SIGNED_REVOCATION_LIST = jsonutils.dumps(
            {'signed': f.read()})

    self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED] = {
        'access': {
            'token': {
                'id': self.SIGNED_TOKEN_SCOPED,
            },
            'user': {
                'id': 'user_id1',
                'name': 'user_name1',
                'tenantId': 'tenant_id1',
                'tenantName': 'tenant_name1',
                'roles': [
                    {
                        'name': 'role1'
                    },
                    {
                        'name': 'role2'
                    },
                ],
            },
        },
    }

    self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED] = {
        'access': {
            'token': {
                'id': self.SIGNED_TOKEN_UNSCOPED,
            },
            'user': {
                'id': 'user_id1',
                'name': 'user_name1',
                'roles': [
                    {
                        'name': 'role1'
                    },
                    {
                        'name': 'role2'
                    },
                ],
            },
        },
    },
Ejemplo n.º 52
0
 def _blob_to_json(ref):
     # credentials stored via ec2tokens before the fix for #1259584
     # need json serializing, as that's the documented API format
     blob = ref.get('blob')
     if isinstance(blob, dict):
         new_ref = ref.copy()
         new_ref['blob'] = jsonutils.dumps(blob)
         return new_ref
     else:
         return ref
 def get_revocation_list_json(self, token_ids=None):
     if token_ids is None:
         token_ids = [REVOKED_TOKEN_HASH]
     revocation_list = {
         'revoked': [{
             'id': x,
             'expires': timeutils.utcnow()
         } for x in token_ids]
     }
     return jsonutils.dumps(revocation_list)
Ejemplo n.º 54
0
def get_default_domain():
    # Return the reference used for the default domain structure during
    # sql migrations.
    return {
        'id': CONF.identity.default_domain_id,
        'name': 'Default',
        'enabled': True,
        'extra': jsonutils.dumps({'description': 'Owns users and tenants '
                                                 '(i.e. projects) available '
                                                 'on Identity API v2.'})}
Ejemplo n.º 55
0
def _serialize(data):
    """Serialization wrapper.

    We prefer using JSON, but it cannot encode all types.
    Error if a developer passes us bad data.
    """
    try:
        return jsonutils.dumps(data, ensure_ascii=True)
    except TypeError:
        with excutils.save_and_reraise_exception():
            LOG.error(_("JSON serialization failed."))
Ejemplo n.º 56
0
    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
Ejemplo n.º 57
0
 def process_request(self, request):
     """Transform the request from XML to JSON."""
     incoming_xml = 'application/xml' in str(request.content_type)
     if incoming_xml and request.body:
         request.content_type = 'application/json'
         try:
             request.body = jsonutils.dumps(
                 serializer.from_xml(request.body))
         except Exception:
             LOG.exception('Serializer failed')
             e = exception.ValidationError(attribute='valid XML',
                                           target='request body')
             return wsgi.render_exception(e, request=request)