def fake_auth_ref(fake_token, fake_service=None):
    """Create an auth_ref using keystoneauth's fixtures"""
    token_copy = copy.deepcopy(fake_token)
    token_copy['token_id'] = token_copy.pop('id')
    token = fixture.V2Token(**token_copy)
    # An auth_ref is actually an access info object
    auth_ref = access.create(body=token)

    # Create a service catalog
    if fake_service:
        service = token.add_service(
            fake_service.type,
            fake_service.name,
        )
        # TODO(dtroyer): Add an 'id' element to KSA's _Service fixure
        service['id'] = fake_service.id
        for e in fake_service.endpoints:
            # KSA's _Service fixture copies publicURL to internalURL and
            # adminURL if they do not exist.  Soooo helpful...
            internal = e.get('internalURL', None)
            admin = e.get('adminURL', None)
            region = e.get('region_id') or e.get('region', '<none>')
            endpoint = service.add_endpoint(
                public=e['publicURL'],
                internal=internal,
                admin=admin,
                region=region,
            )
            # ...so undo that helpfulness
            if not internal:
                endpoint['internalURL'] = None
            if not admin:
                endpoint['adminURL'] = None

    return auth_ref
Beispiel #2
0
    def _create_auth_plugin(self):
        if self.auth_token_info:
            access_info = access.create(body=self.auth_token_info,
                                        auth_token=self.auth_token)
            return access_plugin.AccessInfoPlugin(
                auth_ref=access_info, auth_url=self.keystone_v3_endpoint)

        if self.auth_token:
            # FIXME(jamielennox): This is broken but consistent. If you
            # only have a token but don't load a service catalog then
            # url_for wont work. Stub with the keystone endpoint so at
            # least it might be right.
            return token_endpoint.Token(endpoint=self.keystone_v3_endpoint,
                                        token=self.auth_token)

        if self.password:
            return generic.Password(username=self.username,
                                    password=self.password,
                                    project_id=self.tenant_id,
                                    user_domain_id=self.user_domain,
                                    auth_url=self.keystone_v3_endpoint)

        LOG.error("Keystone API connection failed, no password "
                  "trust or auth_token!")
        raise exception.AuthorizationFailure()
def fake_auth_ref(fake_token, fake_service=None):
    """Create an auth_ref using keystoneauth's fixtures"""
    token_copy = copy.deepcopy(fake_token)
    token_id = token_copy.pop('id')
    token = fixture.V3Token(**token_copy)
    # An auth_ref is actually an access info object
    auth_ref = access.create(
        body=token,
        auth_token=token_id,
    )

    # Create a service catalog
    if fake_service:
        service = token.add_service(
            fake_service['type'],
            fake_service['name'],
        )
        # TODO(dtroyer): Add an 'id' element to KSA's _Service fixure
        service['id'] = fake_service['id']
        for e in fake_service['endpoints']:
            region = e.get('region_id') or e.get('region', '<none>')
            service.add_endpoint(
                e['interface'],
                e['url'],
                region=region,
            )

    return auth_ref
 def test_will_expire_soon(self):
     expires = timeutils.utcnow() + datetime.timedelta(minutes=5)
     token = fixture.V3Token(expires=expires)
     auth_ref = access.create(body=token)
     self.assertFalse(auth_ref.will_expire_soon(stale_duration=120))
     self.assertTrue(auth_ref.will_expire_soon(stale_duration=301))
     self.assertFalse(auth_ref.will_expire_soon())
Beispiel #5
0
    def test_building_unscoped_accessinfo(self):
        token = fixture.V2Token(expires='2012-10-03T16:58:01Z')

        auth_ref = access.create(body=token)

        self.assertIsInstance(auth_ref, access.AccessInfoV2)
        self.assertFalse(auth_ref.has_service_catalog())

        self.assertEqual(auth_ref.auth_token, token.token_id)
        self.assertEqual(auth_ref.username, token.user_name)
        self.assertEqual(auth_ref.user_id, token.user_id)

        self.assertEqual(auth_ref.role_ids, [])
        self.assertEqual(auth_ref.role_names, [])

        self.assertIsNone(auth_ref.tenant_name)
        self.assertIsNone(auth_ref.tenant_id)

        self.assertFalse(auth_ref.domain_scoped)
        self.assertFalse(auth_ref.project_scoped)
        self.assertFalse(auth_ref.trust_scoped)

        self.assertIsNone(auth_ref.project_domain_id)
        self.assertIsNone(auth_ref.project_domain_name)
        self.assertIsNone(auth_ref.user_domain_id)
        self.assertIsNone(auth_ref.user_domain_name)

        self.assertEqual(auth_ref.expires, token.expires)
        self.assertEqual(auth_ref.issued, token.issued)

        self.assertEqual(token.audit_id, auth_ref.audit_id)
        self.assertIsNone(auth_ref.audit_chain_id)
        self.assertIsNone(token.audit_chain_id)
        self.assertIsNone(auth_ref.bind)
    def test_multi_region(self):
        token = fixture.V3Token()
        s = token.add_service(type='identity')

        s.add_endpoint('internal', self.INTERNAL_URL, region=self.REGION_ONE)
        s.add_endpoint('public', self.PUBLIC_URL, region=self.REGION_TWO)
        s.add_endpoint('admin', self.ADMIN_URL, region=self.REGION_THREE)

        auth_ref = access.create(body=token)
        catalog_data = auth_ref.service_catalog.catalog
        catalog = _request._v3_to_v2_catalog(catalog_data)

        self.assertEqual(1, len(catalog))
        service = catalog[0]

        # the 3 regions will come through as 3 separate endpoints
        expected = [{'internalURL': self.INTERNAL_URL,
                    'region': self.REGION_ONE},
                    {'publicURL': self.PUBLIC_URL,
                     'region': self.REGION_TWO},
                    {'adminURL': self.ADMIN_URL,
                     'region': self.REGION_THREE}]

        self.assertEqual('identity', service['type'])
        self.assertEqual(3, len(service['endpoints']))
        for e in expected:
            self.assertIn(e, expected)
Beispiel #7
0
    def _plugin(self, **kwargs):
        token = fixture.V3Token()
        s = token.add_service('identity')
        s.add_standard_endpoints(public=self.TEST_ROOT_URL)

        auth_ref = access.create(body=token, auth_token=self.auth_token)
        return access_plugin.AccessInfoPlugin(auth_ref, **kwargs)
    def test_service_catalog_get_endpoints_region_names(self):
        sc = access.create(auth_token=uuid.uuid4().hex,
                           body=self.AUTH_RESPONSE_BODY).service_catalog

        endpoints = sc.get_endpoints(service_type='image', region_name='North')
        self.assertEqual(len(endpoints), 1)
        for endpoint in endpoints['image']:
            self.assertEqual(endpoint['url'],
                             self.north_endpoints[endpoint['interface']])

        endpoints = sc.get_endpoints(service_type='image', region_name='South')
        self.assertEqual(len(endpoints), 1)
        for endpoint in endpoints['image']:
            self.assertEqual(endpoint['url'],
                             self.south_endpoints[endpoint['interface']])

        endpoints = sc.get_endpoints(service_type='compute')
        self.assertEqual(len(endpoints['compute']), 3)

        endpoints = sc.get_endpoints(service_type='compute',
                                     region_name='North')
        self.assertEqual(len(endpoints['compute']), 3)

        endpoints = sc.get_endpoints(service_type='compute',
                                     region_name='West')
        self.assertEqual(len(endpoints['compute']), 0)
Beispiel #9
0
    def get_unscoped_auth_ref(self, session):
        """Authenticate with OpenID Connect and get back claims.

        This is a multi-step process. First an access token must be retrieved,
        to do this, an authorization code and redirect URL must be given.

        Secondly, we then exchange the access token upon accessing the
        protected Keystone endpoint (federated auth URL). This will trigger
        the OpenID Connect Provider to perform a user introspection and
        retrieve information (specified in the scope) about the user in
        the form of an OpenID Connect Claim. These claims will be sent
        to Keystone in the form of environment variables.

        :param session: a session object to send out HTTP requests.
        :type session: keystoneauth1.session.Session

        :returns: a token data representation
        :rtype: :py:class:`keystoneauth1.access.AccessInfoV3`
        """
        # get an access token
        payload = {'grant_type': self.grant_type,
                   'redirect_uri': self.redirect_uri,
                   'code': self.code}
        access_token = self._get_access_token(session, payload)

        response = self._get_keystone_token(session, access_token)

        # grab the unscoped token
        return access.create(resp=response)
Beispiel #10
0
    def test_password_change_auth_state(self):
        self.stub_auth(json=self.TEST_RESPONSE_DICT)

        expired = ksa_utils.before_utcnow(days=2)
        token = fixture.V2Token(expires=expired)

        auth_ref = access.create(body=token)

        a = v2.Password(self.TEST_URL,
                        username=self.TEST_USER,
                        password=self.TEST_PASS,
                        tenant_id=uuid.uuid4().hex)

        initial_cache_id = a.get_cache_id()

        state = a.get_auth_state()
        self.assertIsNone(state)

        state = json.dumps({'auth_token': auth_ref.auth_token,
                            'body': auth_ref._data})
        a.set_auth_state(state)

        self.assertEqual(token.token_id, a.auth_ref.auth_token)

        s = session.Session()
        self.assertEqual(self.TEST_TOKEN, a.get_token(s))  # updates expired
        self.assertEqual(initial_cache_id, a.get_cache_id())
    def test_service_catalog_service_name(self):
        sc = access.create(auth_token=uuid.uuid4().hex,
                           body=self.AUTH_RESPONSE_BODY).service_catalog

        url = sc.url_for(service_name='glance', interface='public',
                         service_type='image', region_name='North')
        self.assertEqual('http://glance.north.host/glanceapi/public', url)

        url = sc.url_for(service_name='glance', interface='public',
                         service_type='image', region_name='South')
        self.assertEqual('http://glance.south.host/glanceapi/public', url)

        self.assertRaises(exceptions.EndpointNotFound, sc.url_for,
                          service_name='glance', service_type='compute')

        urls = sc.get_urls(service_type='image', service_name='glance',
                           interface='public')

        self.assertIn('http://glance.north.host/glanceapi/public', urls)
        self.assertIn('http://glance.south.host/glanceapi/public', urls)

        urls = sc.get_urls(service_type='image',
                           service_name='Servers',
                           interface='public')

        self.assertEqual(0, len(urls))
    def test_service_catalog_endpoint_id(self):
        token = fixture.V2Token()
        token.set_scope()
        endpoint_id = uuid.uuid4().hex
        public_url = uuid.uuid4().hex

        s = token.add_service('compute')
        s.add_endpoint(public=public_url, id=endpoint_id)
        s.add_endpoint(public=uuid.uuid4().hex)

        auth_ref = access.create(body=token)

        # initially assert that we get back all our urls for a simple filter
        urls = auth_ref.service_catalog.get_urls(interface='public')
        self.assertEqual(2, len(urls))

        urls = auth_ref.service_catalog.get_urls(endpoint_id=endpoint_id,
                                                 interface='public')

        self.assertEqual((public_url, ), urls)

        # with bad endpoint_id nothing should be found
        urls = auth_ref.service_catalog.get_urls(endpoint_id=uuid.uuid4().hex,
                                                 interface='public')

        self.assertEqual(0, len(urls))

        # we ignore a service_id because v2 doesn't know what it is
        urls = auth_ref.service_catalog.get_urls(endpoint_id=endpoint_id,
                                                 service_id=uuid.uuid4().hex,
                                                 interface='public')

        self.assertEqual((public_url, ), urls)
 def test_service_catalog_empty(self):
     self.AUTH_RESPONSE_BODY['access']['serviceCatalog'] = []
     auth_ref = access.create(body=self.AUTH_RESPONSE_BODY)
     self.assertRaises(exceptions.EmptyCatalog,
                       auth_ref.service_catalog.url_for,
                       service_type='image',
                       interface='internalURL')
Beispiel #14
0
    def get_unscoped_auth_ref(self, session):
        """Authenticate with OpenID Connect and get back claims.

        This is a multi-step process. First an access token must be retrieved,
        to do this, the username and password, the OpenID Connect client ID
        and secret, and the access token endpoint must be known.

        Secondly, we then exchange the access token upon accessing the
        protected Keystone endpoint (federated auth URL). This will trigger
        the OpenID Connect Provider to perform a user introspection and
        retrieve information (specified in the scope) about the user in
        the form of an OpenID Connect Claim. These claims will be sent
        to Keystone in the form of environment variables.

        :param session: a session object to send out HTTP requests.
        :type session: keystoneauth1.session.Session

        :returns: a token data representation
        :rtype: :py:class:`keystoneauth1.access.AccessInfoV3`
        """
        # get an access token
        client_auth = (self.client_id, self.client_secret)
        payload = {'grant_type': self.grant_type, 'username': self.username,
                   'password': self.password, 'scope': self.scope}
        response = self._get_access_token(session, client_auth, payload,
                                          self.access_token_endpoint)
        access_token = response.json()[self.access_token_type]

        # use access token against protected URL
        headers = {'Authorization': 'Bearer ' + access_token}
        response = self._get_keystone_token(session, headers,
                                            self.federated_token_url)

        # grab the unscoped token
        return access.create(resp=response)
Beispiel #15
0
    def test_grizzly_token(self):
        grizzly_token = {
            'access': {
                'token': {
                    'id': uuid.uuid4().hex,
                    'expires': '2020-01-01T00:00:10.000123Z',
                },
                'user': {
                    'id': 'user_id1',
                    'name': 'user_name1',
                    'tenantId': 'tenant_id1',
                    'tenantName': 'tenant_name1',
                    'roles': [
                        {'name': 'role1'},
                        {'name': 'role2'},
                    ],
                },
            },
        }

        auth_ref = access.create(body=grizzly_token)
        self.assertIsInstance(auth_ref, access.AccessInfoV2)

        self.assertEqual(auth_ref.project_id, 'tenant_id1')
        self.assertEqual(auth_ref.project_name, 'tenant_name1')
        self.assertIsNone(auth_ref.project_domain_id)
        self.assertIsNone(auth_ref.project_domain_name)
        self.assertIsNone(auth_ref.user_domain_id, 'default')
        self.assertIsNone(auth_ref.user_domain_name, 'Default')
        self.assertEqual(auth_ref.role_names, ['role1', 'role2'])
Beispiel #16
0
    def get_unscoped_auth_ref(self, session, **kwargs):
        sp_auth_url = self._local_cloud_plugin.get_sp_auth_url(session, self._sp_id)
        sp_url = self._local_cloud_plugin.get_sp_url(session, self._sp_id)
        self.auth_url = self._remote_auth_url(sp_auth_url)

        response = self._send_service_provider_ecp_authn_response(session, sp_url, sp_auth_url)
        return access.create(resp=response)
    def test_service_catalog_regions(self):
        self.AUTH_RESPONSE_BODY['token']['region_name'] = "North"
        auth_ref = access.create(auth_token=uuid.uuid4().hex,
                                 body=self.AUTH_RESPONSE_BODY)
        sc = auth_ref.service_catalog

        url = sc.url_for(service_type='image', interface='public')
        self.assertEqual(url, "http://glance.north.host/glanceapi/public")

        self.AUTH_RESPONSE_BODY['token']['region_name'] = "South"
        auth_ref = access.create(auth_token=uuid.uuid4().hex,
                                 body=self.AUTH_RESPONSE_BODY)
        sc = auth_ref.service_catalog
        url = sc.url_for(service_type='image',
                         region_name="South",
                         interface='internal')
        self.assertEqual(url, "http://glance.south.host/glanceapi/internal")
 def test_service_catalog_endpoints(self):
     auth_ref = access.create(body=self.AUTH_RESPONSE_BODY)
     sc = auth_ref.service_catalog
     public_ep = sc.get_endpoints(service_type='compute',
                                  interface='publicURL')
     self.assertEqual(public_ep['compute'][1]['tenantId'], '2')
     self.assertEqual(public_ep['compute'][1]['versionId'], '1.1')
     self.assertEqual(public_ep['compute'][1]['internalURL'],
                      "https://compute.north.host/v1.1/3456")
    def test_project_scoped_service_headers(self):
        token = fixture.V3Token()
        token.set_project_scope()
        token_id = uuid.uuid4().hex

        auth_ref = access.create(auth_token=token_id, body=token)
        self.request.set_service_headers(auth_ref)

        self._test_v3_headers(token, '-Service')
    def _do_fetch_token(self, token):
        """Helper method to fetch a token and convert it into an AccessInfo"""
        data = self.fetch_token(token)

        try:
            return data, access.create(body=data, auth_token=token)
        except Exception:
            self.log.warning(_LW('Invalid token contents.'), exc_info=True)
            raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
Beispiel #21
0
 def test_will_expire_soon(self):
     token = fixture.V2Token()
     expires = timeutils.utcnow() + datetime.timedelta(minutes=5)
     token.expires = expires
     auth_ref = access.create(body=token)
     self.assertIsInstance(auth_ref, access.AccessInfoV2)
     self.assertFalse(auth_ref.will_expire_soon(stale_duration=120))
     self.assertTrue(auth_ref.will_expire_soon(stale_duration=300))
     self.assertFalse(auth_ref.will_expire_soon())
    def test_service_catalog_endpoints(self):
        sc = access.create(auth_token=uuid.uuid4().hex,
                           body=self.AUTH_RESPONSE_BODY).service_catalog

        public_ep = sc.get_endpoints(service_type='compute',
                                     interface='public')
        self.assertEqual(public_ep['compute'][0]['region_id'], 'North')
        self.assertEqual(public_ep['compute'][0]['url'],
                         'https://compute.north.host/novapi/public')
    def test_binding(self):
        token = fixture.V3Token()
        principal = uuid.uuid4().hex
        token.set_bind('kerberos', principal)

        auth_ref = access.create(body=token)
        self.assertIsInstance(auth_ref, access.AccessInfoV3)

        self.assertEqual({'kerberos': principal}, auth_ref.bind)
    def test_building_a_service_catalog(self):
        auth_ref = access.create(body=self.AUTH_RESPONSE_BODY)
        sc = auth_ref.service_catalog

        self.assertEqual(sc.url_for(service_type='compute'),
                         "https://compute.north.host/v1/1234")
        self.assertRaises(exceptions.EndpointNotFound,
                          sc.url_for,
                          region_name="South",
                          service_type='compute')
    def test_service_catalog_alias_find_exact_match(self):
        auth_ref = access.create(auth_token=uuid.uuid4().hex,
                                 body=self.AUTH_RESPONSE_BODY)
        sc = auth_ref.service_catalog

        # Tests that we find the volumev3 endpoint when we request it.
        public_ep = sc.get_endpoints(service_type='volumev3',
                                     interface='public')
        self.assertEqual(public_ep['volumev3'][0]['region'], 'South')
        self.assertEqual(public_ep['volumev3'][0]['url'],
                         "http://cinder.south.host/cinderapi/public/v3")
    def test_service_catalog_url_for_region_names(self):
        sc = access.create(auth_token=uuid.uuid4().hex,
                           body=self.AUTH_RESPONSE_BODY).service_catalog

        url = sc.url_for(service_type='image', region_name='North')
        self.assertEqual(url, self.north_endpoints['public'])

        url = sc.url_for(service_type='image', region_name='South')
        self.assertEqual(url, self.south_endpoints['public'])

        self.assertRaises(exceptions.EndpointNotFound, sc.url_for,
                          service_type='image', region_name='West')
    def _extract_service_catalog(self, body):
        """Set the client's service catalog from the response data."""
        self.auth_ref = access.create(body=body)
        self.service_catalog = self.auth_ref.service_catalog
        self.auth_token = self.auth_ref.auth_token
        self.auth_tenant_id = self.auth_ref.tenant_id
        self.auth_user_id = self.auth_ref.user_id

        if not self.endpoint_url:
            self.endpoint_url = self.service_catalog.url_for(
                region_name=self.region_name, service_type=self.service_type, interface=self.endpoint_type
            )
    def _do_fetch_token(self, token, **kwargs):
        """Helper method to fetch a token and convert it into an AccessInfo."""
        # NOTE(edmondsw): strip the token to remove any whitespace that may
        # have been passed along in the header per bug 1689468
        token = token.strip()
        data = self.fetch_token(token, **kwargs)

        try:
            return data, access.create(body=data, auth_token=token)
        except Exception:
            self.log.warning('Invalid token contents.', exc_info=True)
            raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
    def _create_expired_auth_plugin(self, **kwargs):
        expires = _utils.before_utcnow(minutes=20)
        expired_token = self.get_auth_data(expires=expires)
        expired_auth_ref = access.create(body=expired_token)

        body = 'SUCCESS'
        self.stub_url('GET', ['path'],
                      base_url=self.TEST_COMPUTE_ADMIN, text=body)

        a = self.create_auth_plugin(**kwargs)
        a.auth_ref = expired_auth_ref
        return a
Beispiel #30
0
    def set_auth_state(self, data):
        """Install existing authentication state for a plugin.

        Take the output of get_auth_state and install that authentication state
        into the current authentication plugin.
        """
        if data:
            auth_data = json.loads(data)
            self.auth_ref = access.create(body=auth_data['body'],
                                          auth_token=auth_data['auth_token'])
        else:
            self.auth_ref = None
    def test_building_project_scoped_accessinfo(self):
        token = fixture.V3Token()
        token.set_project_scope()

        s = token.add_service(type='identity')
        s.add_standard_endpoints(public='http://url')

        token_id = uuid.uuid4().hex

        auth_ref = access.create(body=token, auth_token=token_id)

        self.assertIn('methods', auth_ref._data['token'])
        self.assertIn('catalog', auth_ref._data['token'])
        self.assertTrue(auth_ref.has_service_catalog())
        self.assertTrue(auth_ref._data['token']['catalog'])

        self.assertEqual(token_id, auth_ref.auth_token)
        self.assertEqual(token.user_name, auth_ref.username)
        self.assertEqual(token.user_id, auth_ref.user_id)

        self.assertEqual(token.role_ids, auth_ref.role_ids)
        self.assertEqual(token.role_names, auth_ref.role_names)

        self.assertIsNone(auth_ref.domain_name)
        self.assertIsNone(auth_ref.domain_id)

        self.assertEqual(token.project_name, auth_ref.project_name)
        self.assertEqual(token.project_id, auth_ref.project_id)

        self.assertEqual(auth_ref.tenant_name, auth_ref.project_name)
        self.assertEqual(auth_ref.tenant_id, auth_ref.project_id)

        self.assertEqual(token.project_domain_id, auth_ref.project_domain_id)
        self.assertEqual(token.project_domain_name,
                         auth_ref.project_domain_name)

        self.assertEqual(token.user_domain_id, auth_ref.user_domain_id)
        self.assertEqual(token.user_domain_name, auth_ref.user_domain_name)

        self.assertFalse(auth_ref.domain_scoped)
        self.assertTrue(auth_ref.project_scoped)
        self.assertIsNone(auth_ref.project_is_domain)

        self.assertEqual(token.audit_id, auth_ref.audit_id)
        self.assertEqual(token.audit_chain_id, auth_ref.audit_chain_id)
Beispiel #32
0
    def test_v2_roles(self):
        role_id = 'a'
        role_name = 'b'

        token = fixture.V2Token()
        token.set_scope()
        token.add_role(id=role_id, name=role_name)

        auth_ref = access.create(body=token)
        self.assertIsInstance(auth_ref, access.AccessInfoV2)

        self.assertEqual([role_id], auth_ref.role_ids)
        self.assertEqual([role_id],
                         auth_ref._data['access']['metadata']['roles'])
        self.assertEqual([role_name], auth_ref.role_names)
        self.assertEqual([{
            'name': role_name
        }], auth_ref._data['access']['user']['roles'])
Beispiel #33
0
    def get_unscoped_auth_ref(self, session):
        """Authenticate with OpenID Connect and get back claims.

        We exchange the access token upon accessing the protected Keystone
        endpoint (federated auth URL). This will trigger the OpenID Connect
        Provider to perform a user introspection and retrieve information
        (specified in the scope) about the user in the form of an OpenID
        Connect Claim. These claims will be sent to Keystone in the form of
        environment variables.

        :param session: a session object to send out HTTP requests.
        :type session: keystoneauth1.session.Session

        :returns: a token data representation
        :rtype: :py:class:`keystoneauth1.access.AccessInfoV3`
        """
        response = self._get_keystone_token(session, self.access_token)
        return access.create(resp=response)
    def test_oauth_access(self):
        consumer_id = uuid.uuid4().hex
        access_token_id = uuid.uuid4().hex

        token = fixture.V3Token()
        token.set_project_scope()
        token.set_oauth(access_token_id=access_token_id,
                        consumer_id=consumer_id)

        auth_ref = access.create(body=token)

        self.assertEqual(consumer_id, auth_ref.oauth_consumer_id)
        self.assertEqual(access_token_id, auth_ref.oauth_access_token_id)

        self.assertEqual(consumer_id,
                         auth_ref._data['token']['OS-OAUTH1']['consumer_id'])
        self.assertEqual(
            access_token_id,
            auth_ref._data['token']['OS-OAUTH1']['access_token_id'])
Beispiel #35
0
    def get_unscoped_auth_ref(self, session, *kwargs):
        """Retrieve unscoped token after authentcation with ADFS server.

        This is a multistep process:

        * Prepare ADFS Request Securty Token -
          build an etree.XML object filling certain attributes with proper user
          credentials, created/expires dates (ticket is be valid for 120
          seconds as currently we don't handle reusing ADFS issued security
          tokens).

        * Send ADFS Security token to the ADFS server. Step handled by

        * Receive and parse security token, extract actual SAML assertion and
          prepare a request addressed for the Service Provider endpoint.
          This also includes changing namespaces in the XML document. Step
          handled by ``ADFSPassword._prepare_sp_request()`` method.

        * Send prepared assertion to the Service Provider endpoint. Usually
          the server will respond with HTTP 301 code which should be ignored as
          the 'location' header doesn't contain protected area. The goal of
          this operation is fetching the session cookie which later allows for
          accessing protected URL endpoints. Step handed by
          ``ADFSPassword._send_assertion_to_service_provider()`` method.

        * Once the session cookie is issued, the protected endpoint can be
          accessed and an unscoped token can be retrieved. Step handled by
          ``ADFSPassword._access_service_provider()`` method.

        :param session: a session object to send out HTTP requests.
        :type session: keystoneauth1.session.Session

        :returns: AccessInfo
        :rtype: :py:class:`keystoneauth1.access.AccessInfo`

        """
        self._prepare_adfs_request()
        self._get_adfs_security_token(session)
        self._prepare_sp_request()
        self._send_assertion_to_service_provider(session)
        self._access_service_provider(session)

        return access.create(resp=self.authenticated_response)
Beispiel #36
0
    def _do_fetch_token(self, token, **kwargs):
        """Helper method to fetch a token and convert it into an AccessInfo."""
        # NOTE(edmondsw): strip the token to remove any whitespace that may
        # have been passed along in the header per bug 1689468
        token = token.strip()
        if self.kwargs_to_fetch_token:
            data = self.fetch_token(token, **kwargs)
        else:
            m = _('Implementations of auth_token must set '
                  'kwargs_to_fetch_token this will be the required and '
                  'assumed in Queens.')
            warnings.warn(m)
            data = self.fetch_token(token)

        try:
            return data, access.create(body=data, auth_token=token)
        except Exception:
            self.log.warning('Invalid token contents.', exc_info=True)
            raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
    def test_building_unscoped_accessinfo(self):
        token = fixture.V3Token()
        token_id = uuid.uuid4().hex

        auth_ref = access.create(body=token, auth_token=token_id)

        self.assertIn('methods', auth_ref._data['token'])
        self.assertFalse(auth_ref.has_service_catalog())
        self.assertNotIn('catalog', auth_ref._data['token'])

        self.assertEqual(token_id, auth_ref.auth_token)
        self.assertEqual(token.user_name, auth_ref.username)
        self.assertEqual(token.user_id, auth_ref.user_id)

        self.assertEqual(auth_ref.role_ids, [])
        self.assertEqual(auth_ref.role_names, [])

        self.assertIsNone(auth_ref.project_name)
        self.assertIsNone(auth_ref.project_id)

        self.assertFalse(auth_ref.domain_scoped)
        self.assertFalse(auth_ref.project_scoped)
        self.assertIsNone(auth_ref.project_is_domain)

        self.assertEqual(token.user_domain_id, auth_ref.user_domain_id)
        self.assertEqual(token.user_domain_name, auth_ref.user_domain_name)

        self.assertIsNone(auth_ref.project_domain_id)
        self.assertIsNone(auth_ref.project_domain_name)

        self.assertEqual(auth_ref.expires,
                         timeutils.parse_isotime(token['token']['expires_at']))
        self.assertEqual(auth_ref.issued,
                         timeutils.parse_isotime(token['token']['issued_at']))

        self.assertEqual(auth_ref.expires, token.expires)
        self.assertEqual(auth_ref.issued, token.issued)

        self.assertEqual(auth_ref.audit_id, token.audit_id)
        self.assertIsNone(auth_ref.audit_chain_id)
        self.assertIsNone(token.audit_chain_id)
        self.assertIsNone(auth_ref.bind)
Beispiel #38
0
    def test_service_catalog_without_service_type(self):
        token = fixture.V3Token()
        token.set_project_scope()

        public_urls = []

        for i in range(0, 3):
            public_url = uuid.uuid4().hex
            public_urls.append(public_url)

            s = token.add_service(uuid.uuid4().hex)
            s.add_endpoint('public', public_url)

        auth_ref = access.create(body=token)
        urls = auth_ref.service_catalog.get_urls(interface='public')

        self.assertEqual(3, len(urls))

        for p in public_urls:
            self.assertIn(p, urls)
Beispiel #39
0
    def get_unscoped_auth_ref(self, session):
        """Authenticate with OpenID Connect and get back claims.

        This is a multi-step process:

        1.- An access token must be retrieved from the server. In order to do
            so, we need to exchange an authorization grant or refresh token
            with the token endpoint in order to obtain an access token. The
            authorization grant varies from plugin to plugin.

        2.- We then exchange the access token upon accessing the protected
            Keystone endpoint (federated auth URL). This will trigger the
            OpenID Connect Provider to perform a user introspection and
            retrieve information (specified in the scope) about the user in the
            form of an OpenID Connect Claim. These claims will be sent to
            Keystone in the form of environment variables.

        :param session: a session object to send out HTTP requests.
        :type session: keystoneauth1.session.Session

        :returns: a token data representation
        :rtype: :py:class:`keystoneauth1.access.AccessInfoV3`
        """
        # First of all, check if the grant type is supported
        discovery = self._get_discovery_document(session)
        grant_types = discovery.get("grant_types_supported")
        if (grant_types and self.grant_type is not None
                and self.grant_type not in grant_types):
            raise exceptions.OidcPluginNotSupported()

        # Get the payload
        payload = self.get_payload(session)
        payload.setdefault('grant_type', self.grant_type)

        # get an access token
        access_token = self._get_access_token(session, payload)

        response = self._get_keystone_token(session, access_token)

        # grab the unscoped token
        return access.create(resp=response)
    def create_trust_to_karbor(self, context):
        if not context.auth_token_info:
            msg = ("user=%s, project=%s" %
                   (context.user_id, context.project_id))
            raise exception.AuthorizationFailure(obj=msg)

        auth_ref = access.create(body=context.auth_token_info,
                                 auth_token=context.auth_token)
        user_auth_plugin = access_plugin.AccessInfoPlugin(
            auth_url=self._auth_uri, auth_ref=auth_ref)
        l_kc_v3 = self._get_keystone_client(user_auth_plugin)
        try:
            trust = l_kc_v3.trusts.create(trustor_user=context.user_id,
                                          trustee_user=self._karbor_user_id,
                                          project=context.project_id,
                                          impersonation=True,
                                          role_names=context.roles)
            return trust.id

        except Exception as e:
            raise exception.AuthorizationFailure(obj=str(e))
Beispiel #41
0
    def _extract_service_catalog(self, url, resp, body, extract_token=True):
        """See what the auth service told us and process the response.

        We may get redirected to another site, fail or actually get
        back a service catalog with a token and our endpoints.
        """
        # content must always present
        if resp.status_code == 200 or resp.status_code == 201:
            try:
                self.auth_url = url
                self.auth_ref = access.create(resp=resp, body=body)
                self.service_catalog = self.auth_ref.service_catalog

                if extract_token:
                    self.auth_token = self.auth_ref.auth_token

                management_url = self.service_catalog.url_for(
                    region_name=self.region_name,
                    interface=self.endpoint_type,
                    service_type=self.service_type,
                    service_name=self.service_name)
                self.management_url = management_url.rstrip('/')
                return None
            except exceptions.AmbiguousEndpoints:
                print("Found more than one valid endpoint. Use a more "
                      "restrictive filter")
                raise
            except ValueError:
                # ValueError is raised when you pass an invalid response to
                # access.create. This should never happen in reality if the
                # status code is 200.
                raise exceptions.AuthorizationFailure()
            except exceptions.EndpointNotFound:
                print("Could not find any suitable endpoint. Correct region?")
                raise

        elif resp.status_code == 305:
            return resp.headers['location']
        else:
            raise exceptions.from_response(resp, body)
Beispiel #42
0
    def get_unscoped_auth_ref(self, session):
        """Authenticate with OpenID Connect and get back claims.

        This is a multi-step process. First an access token must be retrieved,
        to do this, the username and password, the OpenID Connect client ID
        and secret, and the access token endpoint must be known.

        Secondly, we then exchange the access token upon accessing the
        protected Keystone endpoint (federated auth URL). This will trigger
        the OpenID Connect Provider to perform a user introspection and
        retrieve information (specified in the scope) about the user in
        the form of an OpenID Connect Claim. These claims will be sent
        to Keystone in the form of environment variables.

        :param session: a session object to send out HTTP requests.
        :type session: keystoneauth1.session.Session

        :returns: a token data representation
        :rtype: :py:class:`keystoneauth1.access.AccessInfoV3`
        """

        # get an access token
        client_auth = (self.client_id, self.client_secret)
        payload = {
            'grant_type': self.grant_type,
            'username': self.username,
            'password': self.password,
            'scope': self.scope
        }
        response = self._get_access_token(session, client_auth, payload,
                                          self.access_token_endpoint)
        access_token = response.json()[self.access_token_type]

        # use access token against protected URL
        headers = {'Authorization': 'Bearer ' + access_token}
        response = self._get_keystone_token(session, headers,
                                            self.federated_token_url)

        # grab the unscoped token
        return access.create(resp=response)
    def get_unscoped_auth_ref(self, session):
        """Authenticate with OpenID Connect and get back the access token.

        Exchange the refresh token to get a new access token issued by the
        authentication server.

        :param session: a session object to send out HTTP requests.
        :type session: keystoneclient.session.Session

        :returns: a token data representation
        :rtype: :py:class:`keystoneauth1.access.AccessInfoV3`
        """
        discovery = self._get_discovery_document(session)
        grant_types = discovery.get("grant_types_supported")
        if (grant_types and self.grant_type is not None
                and self.grant_type not in grant_types):
            raise exceptions.OidcPluginNotSupported()

        payload = self.get_payload(session)
        access_token = self._get_access_token(session, payload)
        response = self._get_keystone_token(session, access_token)
        return access.create(resp=response)
Beispiel #44
0
    def test_basic_convert(self):
        token = fixture.V3Token()
        s = token.add_service(type='identity')
        s.add_standard_endpoints(public=self.PUBLIC_URL,
                                 admin=self.ADMIN_URL,
                                 internal=self.INTERNAL_URL,
                                 region=self.REGION_ONE)

        auth_ref = access.create(body=token)
        catalog_data = auth_ref.service_catalog.catalog
        catalog = _request._v3_to_v2_catalog(catalog_data)

        self.assertEqual(1, len(catalog))
        service = catalog[0]
        self.assertEqual(1, len(service['endpoints']))
        endpoints = service['endpoints'][0]

        self.assertEqual('identity', service['type'])
        self.assertEqual(4, len(endpoints))
        self.assertEqual(self.PUBLIC_URL, endpoints['publicURL'])
        self.assertEqual(self.ADMIN_URL, endpoints['adminURL'])
        self.assertEqual(self.INTERNAL_URL, endpoints['internalURL'])
        self.assertEqual(self.REGION_ONE, endpoints['region'])
Beispiel #45
0
    def test_service_catalog_multiple_service_types(self):
        token = fixture.V2Token()
        token.set_scope()

        for i in range(3):
            s = token.add_service('compute')
            s.add_endpoint(public='public-%d' % i,
                           admin='admin-%d' % i,
                           internal='internal-%d' % i,
                           region='region-%d' % i)

        auth_ref = access.create(body=token)

        urls = auth_ref.service_catalog.get_urls(service_type='compute',
                                                 interface='publicURL')

        self.assertEqual(set(['public-0', 'public-1', 'public-2']), set(urls))

        urls = auth_ref.service_catalog.get_urls(service_type='compute',
                                                 interface='publicURL',
                                                 region_name='region-1')

        self.assertEqual(('public-1', ), urls)
Beispiel #46
0
    def test_service_catalog_get_endpoints_region_names(self):
        auth_ref = access.create(body=self.AUTH_RESPONSE_BODY)
        sc = auth_ref.service_catalog

        endpoints = sc.get_endpoints(service_type='image', region_name='North')
        self.assertEqual(len(endpoints), 1)
        self.assertEqual(endpoints['image'][0]['publicURL'],
                         'https://image.north.host/v1/')

        endpoints = sc.get_endpoints(service_type='image', region_name='South')
        self.assertEqual(len(endpoints), 1)
        self.assertEqual(endpoints['image'][0]['publicURL'],
                         'https://image.south.host/v1/')

        endpoints = sc.get_endpoints(service_type='compute')
        self.assertEqual(len(endpoints['compute']), 2)

        endpoints = sc.get_endpoints(service_type='compute',
                                     region_name='North')
        self.assertEqual(len(endpoints['compute']), 2)

        endpoints = sc.get_endpoints(service_type='compute',
                                     region_name='West')
        self.assertEqual(len(endpoints['compute']), 0)
Beispiel #47
0
    def get_unscoped_auth_ref(self, session, **kwargs):
        """Obtain unscoped token after authenticating with SAML IdP.

        :param session:
        :type session: keystoneauth1.session.Session
        """
        saml_response = self._authenticate(session)

        # Exit if authentication failed
        if saml_response is False:
            sys.exit("Invalid username / password provided.")

        self._get_auth_cookie(session, saml_response)

        if self._cookies(session) is False:
            raise exceptions.AuthorizationFailure(
                "Session object doesn't contain a cookie, therefore you are "
                "not allowed to enter the Identity Provider's protected area.")

        resp = session.get(self.federated_token_url,
                           authenticated=False,
                           cookies=session.session.cookies.get_dict())

        return access.create(body=resp.json(), resp=resp)
Beispiel #48
0
    def test_building_scoped_accessinfo(self):
        token = fixture.V2Token()
        token.set_scope()
        s = token.add_service('identity')
        s.add_endpoint('http://url')

        role_data = token.add_role()

        auth_ref = access.create(body=token)

        self.assertIsInstance(auth_ref, access.AccessInfoV2)
        self.assertTrue(auth_ref.has_service_catalog())

        self.assertEqual(auth_ref.auth_token, token.token_id)
        self.assertEqual(auth_ref.username, token.user_name)
        self.assertEqual(auth_ref.user_id, token.user_id)

        self.assertEqual(auth_ref.role_ids, [role_data['id']])
        self.assertEqual(auth_ref.role_names, [role_data['name']])

        self.assertEqual(auth_ref.tenant_name, token.tenant_name)
        self.assertEqual(auth_ref.tenant_id, token.tenant_id)

        self.assertEqual(auth_ref.tenant_name, auth_ref.project_name)
        self.assertEqual(auth_ref.tenant_id, auth_ref.project_id)

        self.assertIsNone(auth_ref.project_domain_id, 'default')
        self.assertIsNone(auth_ref.project_domain_name, 'Default')
        self.assertIsNone(auth_ref.user_domain_id, 'default')
        self.assertIsNone(auth_ref.user_domain_name, 'Default')

        self.assertTrue(auth_ref.project_scoped)
        self.assertFalse(auth_ref.domain_scoped)

        self.assertEqual(token.audit_id, auth_ref.audit_id)
        self.assertEqual(token.audit_chain_id, auth_ref.audit_chain_id)
Beispiel #49
0
 def get_unscoped_auth_ref(self, session, **kwargs):
     with utils.BundleBuilder(session, self.x509_user_proxy) as p:
         auth_response = session.post(self.federated_token_url,
                                      authenticated=False)
     return access.create(auth_response)
Beispiel #50
0
    def get_unscoped_auth_ref(self, session, **kwargs):
        resp = session.get(self.federated_token_url,
                           requests_auth=_requests_auth(),
                           authenticated=False)

        return access.create(body=resp.json(), resp=resp)
Beispiel #51
0
 def test_token_without_catalog(self):
     token = fixture.V3Token()
     auth_ref = access.create(body=token)
     self.request.set_service_catalog_headers(auth_ref)
     self.assertNotIn('X-Service-Catalog', self.request.headers)
Beispiel #52
0
 def get_unscoped_auth_ref(self, sess, **kwargs):
     # This would go and talk to an idp or something
     resp = sess.post(self.federated_token_url, authenticated=False)
     return access.create(resp=resp)
Beispiel #53
0
    def test_service_catalog_without_name(self):
        f = fixture.V3Token(audit_chain_id=uuid.uuid4().hex)

        if not f.project_id:
            f.set_project_scope()

        f.add_role(name='admin')
        f.add_role(name='member')

        region = 'RegionOne'
        tenant = '225da22d3ce34b15877ea70b2a575f58'

        s = f.add_service('volume')
        s.add_standard_endpoints(
            public='http://public.com:8776/v1/%s' % tenant,
            internal='http://internal:8776/v1/%s' % tenant,
            admin='http://admin:8776/v1/%s' % tenant,
            region=region)

        s = f.add_service('image')
        s.add_standard_endpoints(public='http://public.com:9292/v1',
                                 internal='http://internal:9292/v1',
                                 admin='http://admin:9292/v1',
                                 region=region)

        s = f.add_service('compute')
        s.add_standard_endpoints(
            public='http://public.com:8774/v2/%s' % tenant,
            internal='http://internal:8774/v2/%s' % tenant,
            admin='http://admin:8774/v2/%s' % tenant,
            region=region)

        s = f.add_service('ec2')
        s.add_standard_endpoints(
            public='http://public.com:8773/services/Cloud',
            internal='http://internal:8773/services/Cloud',
            admin='http://admin:8773/services/Admin',
            region=region)

        s = f.add_service('identity')
        s.add_standard_endpoints(public='http://public.com:5000/v3',
                                 internal='http://internal:5000/v3',
                                 admin='http://admin:35357/v3',
                                 region=region)

        pr_auth_ref = access.create(body=f)
        pr_sc = pr_auth_ref.service_catalog

        # this will work because there are no service names on that token
        url_ref = 'http://public.com:8774/v2/225da22d3ce34b15877ea70b2a575f58'
        url = pr_sc.url_for(service_type='compute',
                            service_name='NotExist',
                            interface='public')
        self.assertEqual(url_ref, url)

        ab_auth_ref = access.create(body=self.AUTH_RESPONSE_BODY)
        ab_sc = ab_auth_ref.service_catalog

        # this won't work because there is a name and it's not this one
        self.assertRaises(exceptions.EndpointNotFound,
                          ab_sc.url_for,
                          service_type='compute',
                          service_name='NotExist',
                          interface='public')
 def test_federated_property_standard_token(self):
     """Check if is_federated property returns expected value."""
     token = fixture.V3Token()
     token.set_project_scope()
     auth_ref = access.create(body=token)
     self.assertFalse(auth_ref.is_federated)
 def test_is_admin_project_false(self):
     token = fixture.V3Token(is_admin_project=False)
     auth_ref = access.create(body=token)
     self.assertIsInstance(auth_ref, access.AccessInfoV3)
     self.assertIs(False, auth_ref.is_admin_project)
 def test_is_admin_project_unset(self):
     token = fixture.V3Token()
     auth_ref = access.create(body=token)
     self.assertIsInstance(auth_ref, access.AccessInfoV3)
     self.assertIs(True, auth_ref.is_admin_project)
Beispiel #57
0
    def get_unscoped_auth_ref(self, session):
        """Get unscoped OpenStack token after federated authentication.

        This is a multi-step process including multiple HTTP requests.

        The federated authentication consists of:

        * HTTP GET request to the Identity Service (acting as a Service
          Provider).

          It's crucial to include HTTP headers indicating we are expecting SOAP
          message in return. Service Provider should respond with such SOAP
          message.  This step is handed by a method
          ``Saml2Password_send_service_provider_request()``.

        * HTTP POST request to the external Identity Provider service with
          ECP extension enabled. The content sent is a header removed SOAP
          message  returned from the Service Provider. It's also worth noting
          that ECP extension to the SAML2 doesn't define authentication method.
          The most popular is HttpBasicAuth with just user and password.
          Other possibilities could be X509 certificates or Kerberos.
          Upon successful authentication the user should receive a SAML2
          assertion.
          This step is handed by a method
          ``Saml2Password_send_idp_saml2_authn_request(session)``

        * HTTP POST request again to the Service Provider. The body of the
          request includes SAML2 assertion issued by a trusted Identity
          Provider. The request should be sent to the Service Provider
          consumer url specified in the SAML2 assertion.
          Providing the authentication was successful and both Service Provider
          and Identity Providers are trusted to each other, the Service
          Provider will issue an unscoped token with a list of groups the
          federated user is a member of.
          This step is handed by a method
          ``Saml2Password_send_service_provider_saml2_authn_response()``

          Unscoped token example::

            {
                "token": {
                    "methods": [
                        "saml2"
                    ],
                    "user": {
                        "id": "username%40example.com",
                        "name": "*****@*****.**",
                        "OS-FEDERATION": {
                            "identity_provider": "ACME",
                            "protocol": "saml2",
                            "groups": [
                                {"id": "abc123"},
                                {"id": "bcd234"}
                            ]
                        }
                    }
                }
            }


        :param session : a session object to send out HTTP requests.
        :type session: keystoneauth1.session.Session

        :returns: AccessInfo
        :rtype: :py:class:`keystoneauth1.access.AccessInfo`
        """
        saml_authenticated = self._send_service_provider_request(session)
        if not saml_authenticated:
            self._send_idp_saml2_authn_request(session)
            self._send_service_provider_saml2_authn_response(session)

        return access.create(resp=self.authenticated_response)