예제 #1
0
def fake_catalog(tenant, token):
    """Generate a fake Service Catalog

    """
    catalog_gen = servicecatalog.ServiceCatalogGenerator(token, tenant)
    catalog = catalog_gen.generate_full_catalog()['access']
    return access.AccessInfoV2(**catalog)
예제 #2
0
    def get_auth_ref(self, session, **kwargs):
        headers = {'Accept': 'application/json'}
        url = self.auth_url.rstrip('/') + '/tokens'
        params = {'auth': self.get_auth_data(headers)}

        if self.tenant_id:
            params['auth']['tenantId'] = self.tenant_id
        elif self.tenant_name:
            params['auth']['tenantName'] = self.tenant_name
        if self.trust_id:
            params['auth']['trust_id'] = self.trust_id

        _logger.debug('Making authentication request to %s', url)
        resp = session.post(url,
                            json=params,
                            headers=headers,
                            authenticated=False,
                            log=False)

        try:
            resp_data = resp.json()['access']
        except (KeyError, ValueError):
            raise exceptions.InvalidResponse(response=resp)

        return access.AccessInfoV2(**resp_data)
예제 #3
0
def _retrieve_data_from_cache(redis_client, url, tenant, token):
    """Retrieve the authentication data from cache

    :param redis_client: redis.Redis object connected to the redis cache
    :param url: URL used for authentication
    :param tenant: tenant id of the user
    :param token: auth_token for the user

    :returns: a keystoneclient.access.AccessInfo on success or None
    """
    cached_data = None
    cache_key = None
    try:
        # Try to get the data from the cache
        cache_key_tuple = (tenant, token, url)
        cache_key = _tuple_to_cache_key(cache_key_tuple)
        cached_data = redis_client.get(cache_key)
    except Exception as ex:
        LOG.debug(
            (
                'Failed to retrieve data to cache for key {0}'
                'Exception: {1}'
            ).format(cache_key, str(ex))
        )
        return None

    if cached_data is not None:
        # So 'data' can be used in the exception handler...
        data = None

        try:
            data = __unpacker(cached_data)
            return access.AccessInfoV2(data)

        except Exception as ex:
            # The cached object didn't match what we expected
            msg = (
                'Stored Data does not contain any credentials - '
                'Exception: {0}; Data: {1}'
            ).format(str(ex), data)
            LOG.error(msg)
            return None
    else:
        LOG.debug('No data in cache for key {0}'.format(cache_key))
        # It wasn't cached
        return None
예제 #4
0
    def get_auth_ref(self, session, **kwargs):
        headers = {}
        url = self.auth_url + '/tokens'
        params = {'auth': self.get_auth_data(headers)}

        if self.tenant_id:
            params['auth']['tenantId'] = self.tenant_id
        elif self.tenant_name:
            params['auth']['tenantName'] = self.tenant_name
        if self.trust_id:
            params['auth']['trust_id'] = self.trust_id

        resp = session.post(url,
                            json=params,
                            headers=headers,
                            authenticated=False)
        return access.AccessInfoV2(**resp.json()['access'])
예제 #5
0
    def get_raw_token_from_identity_service(self, auth_url, tenant_id, token):
        LOG.debug('URL: {0}'.format(auth_url))
        LOG.debug('Token: {0}'.format(token))
        LOG.debug('Tenant: {0}'.format(tenant_id))

        if token == 'valid_token' and tenant_id == 'valid_projectid':
            catalog_gen = servicecatalog.ServiceCatalogGenerator(
                token, tenant_id)
            catalog = catalog_gen.generate_full_catalog()['access']
            return access.AccessInfoV2(**catalog)
        else:
            if token == 'valid_token':
                raise exceptions.AuthorizationFailure(
                    'mocking - invalid project id')
            elif tenant_id == 'valid_projectid':
                raise exceptions.AuthorizationFailure(
                    'mocking - invalid token')
            else:
                raise exceptions.AuthorizationFailure(
                    'mocking - invalid or missing token or project id')
예제 #6
0
    def test__retrieve_data_from_keystone_alt_auth(self):
        redis_client = fakeredis_connection()

        tenant_id = '172839405'
        token = 'AaBbCcDdEeFf'
        url = 'myurl'
        bttl = 5

        with mock.patch('eom.auth.get_conf') as mock_auth_conf:
            with mock.patch('requests.get') as mock_requests:
                mock_auth_conf.return_value.alternate_validation = True
                cat = servicecatalog.ServiceCatalogGenerator(token, tenant_id)
                resp_json = cat.generate_without_catalog()
                mock_requests.return_value.json.return_value = resp_json
                mock_requests.return_value.status_code = 200

                access_info = auth._retrieve_data_from_keystone(
                    redis_client, url, tenant_id, token, bttl,
                    self.default_max_cache_life)

                self.assertEqual(
                    access_info,
                    access.AccessInfoV2(
                        cat.generate_without_catalog()['access']))
예제 #7
0
def _retrieve_data_from_keystone(redis_client, url, tenant, token,
                                 blacklist_ttl, max_cache_life):
    """Retrieve the authentication data from OpenStack Keystone

    :param redis_client: redis.Redis object connected to the redis cache
    :param url: Keystone Identity URL to authenticate against
    :param tenant: tenant id of user data to retrieve
    :param token: auth_token for the tenant_id
    :param blacklist_ttl: time in milliseconds for blacklisting failed tokens
    :param max_cache_life: time in seconds for the maximum time a cache entry
                           should remain in the cache of valid data

    :returns: a keystoneclient.access.AccessInfo on success or None on error
    """
    try:
        # Try to authenticate the user and get the user information using
        # only the data provided, no special administrative tokens required.
        # When using the alternative validation method, the service catalog
        # identity does not return a service catalog for valid tokens.

        if get_conf().alternate_validation is True:
            _url = url.rstrip('/') + '/tokens'
            validation_url = _url + '/{0}'.format(token)
            headers = {
                'Accept': 'application/json',
                'X-Auth-Token': token
            }
            resp = requests.get(validation_url, headers=headers)
            if resp.status_code >= 400:
                LOG.debug('Request returned failure status: {0}'.format(
                    resp.status_code))
                raise exceptions.from_response(resp, 'GET', _url)

            try:
                resp_data = resp.json()['access']
            except (KeyError, ValueError):
                raise exceptions.InvalidResponse(response=resp)

            access_info = access.AccessInfoV2(**resp_data)
        else:
            keystone = keystonev2_client.Client(tenant_id=tenant,
                                                token=token,
                                                auth_url=url)
            access_info = keystone.get_raw_token_from_identity_service(
                auth_url=url, tenant_id=tenant, token=token)

        # cache the data so it is easier to access next time
        _send_data_to_cache(redis_client, url, access_info, max_cache_life)

        return access_info

    except (exceptions.AuthorizationFailure, exceptions.Unauthorized) as ex:
        # re-raise 413 here and later on respond with 503
        if 'HTTP 413' in str(ex):
            raise exceptions.RequestEntityTooLarge(
                method='POST',
                url=url,
                http_status=413
            )
        # Provided data was invalid and authorization failed
        msg = 'Failed to authenticate against {0} - {1}'.format(
            url,
            str(ex)
        )
        LOG.debug(msg)

        # Blacklist the token
        _blacklist_token(redis_client, token, blacklist_ttl)
        return None
    except exceptions.RequestEntityTooLarge:
        LOG.debug('Request entity too large error from authentication server.')
        raise
    except Exception as ex:
        # Provided data was invalid or something else went wrong
        msg = 'Failed to authenticate against {0} - {1}'.format(
            url,
            str(ex)
        )
        LOG.debug(msg)

        return None