def get_user(self, user_id): """ Returns the current user (if authenticated) based on the user ID and session data. Note: this required monkey-patching the ``contrib.auth`` middleware to make the ``request`` object available to the auth backend class. """ if user_id == self.request.session["user_id"]: token = Token(TokenManager(None), self.request.session['token'], loaded=True) endpoint = self.request.session['region_endpoint'] return create_user_from_token(self.request, token, endpoint) else: return None
def authenticate(self, request=None, username=None, password=None, tenant=None, auth_url=None, otp=None): """ Authenticates a user via the Keystone Identity API. """ LOG.debug('Beginning user authentication for user "%s".' % username) insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False) try: client = keystone_client.Client(username=username, password=password, tenant_id=tenant, auth_url=auth_url, insecure=insecure) unscoped_token_data = {"token": client.service_catalog.get_token()} unscoped_token = Token(TokenManager(None), unscoped_token_data, loaded=True) except (keystone_exceptions.Unauthorized, keystone_exceptions.Forbidden, keystone_exceptions.NotFound) as exc: msg = _('Invalid user name or password.') LOG.debug(exc.message) raise KeystoneAuthException(msg) except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure) as exc: msg = _("An error occurred authenticating. " "Please try again later.") LOG.debug(exc.message) raise KeystoneAuthException(msg) # Check expiry for our unscoped token. self.check_auth_expiry(unscoped_token) # FIXME: Log in to default tenant when the Keystone API returns it... # For now we list all the user's tenants and iterate through. try: tenants = client.tenants.list() except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure): msg = _('Unable to retrieve authorized projects.') raise KeystoneAuthException(msg) # Abort if there are no tenants for this user if not tenants: msg = _('You are not authorized for any projects.') raise KeystoneAuthException(msg) while tenants: tenant = tenants.pop() try: client = keystone_client.Client(tenant_id=tenant.id, token=unscoped_token.id, auth_url=auth_url, insecure=insecure) token = client.tokens.authenticate(username=username, token=unscoped_token.id, tenant_id=tenant.id) break except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure): token = None if token is None: msg = _("Unable to authenticate to any available projects.") raise KeystoneAuthException(msg) # Check expiry for our new scoped token. self.check_auth_expiry(token) # If we made it here we succeeded. Create our User! user = create_user_from_token(request, token, client.service_catalog.url_for()) if request is not None: if is_ans1_token(unscoped_token.id): hashed_token = hashlib.md5(unscoped_token.id).hexdigest() unscoped_token._info['token']['id'] = hashed_token request.session['unscoped_token'] = unscoped_token.id request.user = user # Support client caching to save on auth calls. setattr(request, KEYSTONE_CLIENT_ATTR, client) LOG.debug('Authentication completed for user "%s".' % username) return user
def authenticate(self, request=None, username=None, password=None, tenant=None, auth_url=None): """ Authenticates a user via the Keystone Identity API. """ LOG.debug('Beginning user authentication for user "%s".' % username) insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False) try: client = keystone_client.Client(username=username, password=password, tenant_id=tenant, auth_url=auth_url, insecure=insecure) unscoped_token_data = {"token": client.service_catalog.get_token()} unscoped_token = Token(TokenManager(None), unscoped_token_data, loaded=True) except (keystone_exceptions.Unauthorized, keystone_exceptions.Forbidden, keystone_exceptions.NotFound) as exc: msg = _('Invalid user name or password.') LOG.debug(exc.message) raise KeystoneAuthException(msg) except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure) as exc: msg = _("An error occurred authenticating. " "Please try again later.") LOG.debug(exc.message) raise KeystoneAuthException(msg) # Check expiry for our unscoped token. self.check_auth_expiry(unscoped_token) # FIXME: Log in to default tenant when the Keystone API returns it... # For now we list all the user's tenants and iterate through. try: tenants = client.tenants.list() except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure): msg = _('Unable to retrieve authorized projects.') raise KeystoneAuthException(msg) # Abort if there are no tenants for this user if not tenants: msg = _('You are not authorized for any projects.') raise KeystoneAuthException(msg) while tenants: tenant = tenants.pop() try: client = keystone_client.Client(tenant_id=tenant.id, token=unscoped_token.id, auth_url=auth_url, insecure=insecure) token = client.tokens.authenticate(username=username, token=unscoped_token.id, tenant_id=tenant.id) break except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure): token = None if token is None: msg = _("Unable to authenticate to any available projects.") raise KeystoneAuthException(msg) # Check expiry for our new scoped token. self.check_auth_expiry(token) # If we made it here we succeeded. Create our User! user = create_user_from_token(request, token, client.service_catalog.url_for()) if request is not None: if is_ans1_token(unscoped_token.id): hashed_token = hashlib.md5(unscoped_token.id).hexdigest() unscoped_token._info['token']['id'] = hashed_token request.session['unscoped_token'] = unscoped_token.id request.user = user # Support client caching to save on auth calls. setattr(request, KEYSTONE_CLIENT_ATTR, client) LOG.debug('Authentication completed for user "%s".' % username) return user
def set_user_admin_token(request): """ Via admin account login again when admin token is expired. """ from keystoneclient.v2_0 import client as keystone_client from keystoneclient import exceptions as keystone_exceptions from keystoneclient.v2_0.tokens import Token, TokenManager from openstack_auth.exceptions import KeystoneAuthException from openstack_auth.utils import is_ans1_token insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False) endpoint = request.user.endpoint try: password = getattr(settings, 'OPENSTACK_ADMIN_TOKEN', 'admin') client = keystone_client.Client(username=u'admin', password=password, tenant_id='', auth_url=endpoint, insecure=insecure) unscoped_token_data = {"token": client.service_catalog.get_token()} unscoped_token = Token(TokenManager(None), unscoped_token_data, loaded=True) except (keystone_exceptions.Unauthorized, keystone_exceptions.Forbidden, keystone_exceptions.NotFound) as exc: msg = _('Invalid user name or password.') LOG.debug(exc.message) raise KeystoneAuthException(msg) except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure) as exc: msg = _("An error occurred authenticating. " "Please try again later.") LOG.debug(exc.message) raise KeystoneAuthException(msg) # FIXME: Log in to default tenant when the Keystone API returns it... # For now we list all the user's tenants and iterate through. try: tenants = client.tenants.list() except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure): msg = _('Unable to retrieve authorized projects.') raise KeystoneAuthException(msg) # Abort if there are no tenants for this user if not tenants: msg = _('You are not authorized for any projects.') raise KeystoneAuthException(msg) while tenants: tenant = tenants.pop() try: token = api.token_create_scoped(request, tenant.id, unscoped_token.id) break except (keystone_exceptions.ClientException, keystone_exceptions.AuthorizationFailure): token = None if token is None: msg = _("Unable to authenticate to any available projects.") raise KeystoneAuthException(msg) # If we made it here we succeeded. Create our User! user = create_user_from_token(request, token, endpoint) if request is not None: if is_ans1_token(unscoped_token.id): hashed_token = hashlib.md5(unscoped_token.id).hexdigest() unscoped_token._info['token']['id'] = hashed_token request.session['unscoped_token'] = unscoped_token.id request.user = user set_session_from_user(request, request.user) return user
def generate_test_data(): ''' Builds a set of test_data data as returned by Keystone. ''' test_data = TestDataContainer() keystone_service = { 'type': 'identity', 'name': 'keystone', 'endpoints_links': [], 'endpoints': [{ 'region': 'RegionOne', 'adminURL': 'http://admin.localhost:35357/v2.0', 'internalURL': 'http://internal.localhost:5000/v2.0', 'publicURL': 'http://public.localhost:5000/v2.0' }] } # Users user_dict = { 'id': uuid.uuid4().hex, 'name': 'gabriel', 'email': '*****@*****.**', 'password': '******', 'token': '', 'enabled': True } test_data.user = User(UserManager(None), user_dict, loaded=True) # Tenants tenant_dict_1 = { 'id': uuid.uuid4().hex, 'name': 'tenant_one', 'description': '', 'enabled': True } tenant_dict_2 = { 'id': uuid.uuid4().hex, 'name': '', 'description': '', 'enabled': False } test_data.tenant_one = Tenant(TenantManager(None), tenant_dict_1, loaded=True) test_data.tenant_two = Tenant(TenantManager(None), tenant_dict_2, loaded=True) # Roles role_dict = {'id': uuid.uuid4().hex, 'name': 'Member'} test_data.role = Role(RoleManager, role_dict) # Tokens tomorrow = datetime_safe.datetime.now() + timedelta(days=1) expiration = datetime_safe.datetime.isoformat(tomorrow) scoped_token_dict = { 'token': { 'id': uuid.uuid4().hex, 'expires': expiration, 'tenant': tenant_dict_1, 'tenants': [tenant_dict_1, tenant_dict_2] }, 'user': { 'id': user_dict['id'], 'name': user_dict['name'], 'roles': [role_dict] }, 'serviceCatalog': [keystone_service] } test_data.scoped_token = Token(TokenManager(None), scoped_token_dict, loaded=True) unscoped_token_dict = { 'token': { 'id': uuid.uuid4().hex, 'expires': expiration }, 'user': { 'id': user_dict['id'], 'name': user_dict['name'], 'roles': [role_dict] }, 'serviceCatalog': [keystone_service] } test_data.unscoped_token = Token(TokenManager(None), unscoped_token_dict, loaded=True) # Service Catalog test_data.service_catalog = ServiceCatalog({ 'serviceCatalog': [keystone_service], 'token': { 'id': scoped_token_dict['token']['id'], 'expires': scoped_token_dict['token']['expires'], 'user_id': user_dict['id'], 'tenant_id': tenant_dict_1['id'] } }) return test_data
def setUp(self): self.token = "ff01eb8a8d69418c95f0009dda9bc1852" self.token_other_tenant = "gg01eb8a8d69418c95f0009dda9bc1852" self.token_not_found = "0001eb8a8d69418c95f0009dda9bc1852" self.token_not_authorized = "bbbbbbba8d69418c95f0009dda9bc1852" self.fakeToken = "fffffffffffffffffffffffffffffffff" self.authToken = "77d254b3caba4fb29747958138136ffa" self.url = "http://130.206.80.61:35357/v2.0" self.url_noResponse = "http://127.0.0.1:35357/v2.0" self.url_server_error = "http://serverWithErrors.com:35357/v2.0" self.tenantId = "6571e3422ad84f7d828ce2f30373b3d4" self.a = AuthorizationManager.AuthorizationManager() self.mockedClient = client self.auth = mock() self.tokenM = mock() manager = mock() requestsMock = mock() response = Response() response.status_code = 200 response._content = '{"access":{"token":{"expires":"2015-07-09T15:16:07Z",' \ '"id":{"token":"ff01eb8a8d69418c95f0009dda9bc1852",' \ '"tenant":"6571e3422ad84f7d828ce2f30373b3d4","name":"*****@*****.**",' \ '"access_token":' \ '"4HMIFCQOlswp1hZmPG-BmP6cXQWyqvIYV0WrvoKptV59O4r3_VpIJwwFx-JgJW-Lg0K_hWVmbb2ROYxnuy53jQ",' \ '"expires":"2014-09-13T07:23:51.000Z"}' \ ',"tenant":{"description":"Tenant from IDM","enabled":true,' \ '"id":"6571e3422ad84f7d828ce2f30373b3d4","name":"user"}},' \ '"user":{"username":"******","roles_links":[],"id":"user",' \ '"roles":[{"id":"8db87ccbca3b4d1ba4814c3bb0d63aab","name":"Member"}],"name":"user"}}}' response2 = Response() response2.status_code = 200 response2._content = '{"access":{"token":{"expires":"2015-07-09T15:16:07Z",' \ '"id":{"token":"gg01eb8a8d69418c95f0009dda9bc1852",' \ '"tenant":"1111e3422ad84f7d828ce2f30373b3d4","name":"*****@*****.**",' \ '"access_token":' \ '"4HMIFCQOlswp1hZmPG-BmP6cXQWyqvIYV0WrvoKptV59O4r3_VpIJwwFx-JgJW-Lg0K_hWVmbb2ROYxnuy53jQ",' \ '"expires":"2014-09-13T07:23:51.000Z"}' \ ',"tenant":{"description":"Different Tenant from IDM","enabled":true,' \ '"id":"1111e3422ad84f7d828ce2f30373b3d4","name":"user"}},' \ '"user":{"username":"******","roles_links":[],"id":"user",' \ '"roles":[{"id":"8db87ccbca3b4d1ba4814c3bb0d63aab","name":"Member"}],"name":"user"}}}' response_not_found = Response() response_not_found.status_code = 200 response_not_found._content = 'User token not found' response_not_authorized = Response() response_not_authorized.status_code = 200 response_not_authorized._content = 'Service not authorized' dic_valid = { "token": { "id": self.authToken, "tenant": { "enabled": True, "description": "Default tenant", "name": "admin", "id": "6571e3422ad84f7d828ce2f30373b3d4" } } } dic_invalid = { "token": { "id": self.authToken, "tenant": { "enabled": True, "description": "Default tenant", "name": "admin", "id": "anotherTenantId" } } } verification_expected = Token(manager, dic_valid) verification_expected_fail = Token(manager, dic_invalid) self.auth.__setattr__("auth_token", self.authToken) self.auth.__setattr__("tokens", self.tokenM) when(self.tokenM).authenticate( token=self.token, tenant_id=self.tenantId).thenReturn(verification_expected) when(self.tokenM).authenticate(token=self.fakeToken, tenant_id=self.tenantId)\ .thenReturn(verification_expected_fail) when(self.mockedClient).Client(username="******", password="******", auth_url=self.url)\ .thenReturn(self.auth) when(self.mockedClient).Client(token=self.authToken, endpoint=self.url).thenReturn(self.auth) when(self.mockedClient)\ .Client(token=self.authToken, endpoint=self.url_noResponse).thenRaise(InternalServerError()) when(self.mockedClient)\ .Client(token=self.authToken, endpoint=self.url_server_error).thenRaise(Exception()) when(self.mockedClient).Client(username="******", password="******", auth_url=self.url).thenRaise( Unauthorized()) when(self.mockedClient)\ .Client(username="******", password="******", auth_url=self.url_server_error)\ .thenRaise(AuthorizationFailure()) headers = { ACCEPT_HEADER: JSON_TYPE, X_AUTH_TOKEN_HEADER: self.authToken } when(requestsMock).get(self.url + "/" + TOKENS_PATH + self.token, headers=headers)\ .thenReturn(response) when(requestsMock).get(self.url + "/" + TOKENS_PATH + self.token_other_tenant, headers=headers)\ .thenReturn(response2) when(requestsMock).get(self.url + "/" + TOKENS_PATH + self.token_not_found, headers=headers)\ .thenReturn(response_not_found) when(requestsMock).get(self.url + "/" + TOKENS_PATH + self.token_not_authorized, headers=headers)\ .thenReturn(response_not_authorized) when(requestsMock).get(self.url + "/" + TOKENS_PATH + self.fakeToken, headers=headers)\ .thenRaise(Unauthorized()) when(requestsMock).get(self.url_noResponse + "/" + TOKENS_PATH + self.fakeToken, headers=headers)\ .thenRaise(InternalServerError()) when(requestsMock).get(self.url_server_error + "/" + TOKENS_PATH + self.token, headers=headers)\ .thenRaise(Exception()) self.a.client = requestsMock self.a.myClient = self.mockedClient
def setUp(self): self.user = "******" self.token = "ff01eb8a8d69418c95f0009dda9bc1852" self.token_not_expired = "aa01eb8a8d69418c95f0009dda9bc0000" self.token_other_tenant = "gg01eb8a8d69418c95f0009dda9bc1852" self.token_not_found = "0001eb8a8d69418c95f0009dda9bc1852" self.token_not_authorized = "bbbbbbba8d69418c95f0009dda9bc1852" self.fakeToken = "fffffffffffffffffffffffffffffffff" self.authToken = "77d254b3caba4fb29747958138136ffa" self.url = "http://*****:*****@mail.com", "access_token": "4HMIFCQOlswp1hZmPG-BmP6cXQWyqvIYV0WrvoKptV59O4r3_VpIJwwFx-JgJW", "expires": "2014-09-13T07:23:51.000Z" }, "tenant": { "description": "Tenant from IDM", "enabled": true, "id": "6571e3422ad84f7d828ce2f30373b3d4", "name": "user" } }, "user": { "username": "******", "roles_links": [], "id": "user", "roles": [{ "id": "8db87ccbca3b4d1ba4814c3bb0d63aab", "name": "Member" }], "name": "user" } } }''' response_not_expired = Response() response_not_expired.status_code = HTTP_RESPONSE_CODE_OK response_not_expired._content = ''' { "access": { "token": { "expires":"2115-07-09T15:16:07Z", "id": { "token":"aa01eb8a8d69418c95f0009dda9bc0000", "tenant":"6571e3422ad84f7d828ce2f30373b3d4", "name":"*****@*****.**", "access_token": "4HMIFCQOlswp1hZmPG-BmP6cXQWyqvIYV0WrvoKptV59O4r3_VpIJwwFx-JgJW", "expires":"2114-09-13T07:23:51.000Z" }, "tenant":{ "description":"Tenant from IDM","enabled":true, "id":"6571e3422ad84f7d828ce2f30373b3d4", "name":"user" } }, "user": { "username":"******", "roles_links":[], "id":"user", "roles":[{ "id":"8db87ccbca3b4d1ba4814c3bb0d63aab", "name":"Member" }], "name":"user" } } }''' response_v3 = Response() response_v3.status_code = HTTP_RESPONSE_CODE_OK response_v3._content = ''' { "token": { "methods": ["password"], "roles": [{ "id": "ff01eb8a8d69418c95f0009dda9bc1852", "name": "owner" }], "expires_at": "2015-05-26T13:01:49.632762Z", "project": { "domain": { "id": "default", "name": "Default" }, "id": "6571e3422ad84f7d828ce2f30373b3d4", "name": "*****@*****.**" }, "user": { "domain": { "id": "default","name": "Default" }, "id": "user", "name": "*****@*****.**" }, "audit_ids": ["XREoG4obSW69erG3fVjvjQ"], "issued_at": "2016-03-08T10:06:04.653858Z" } }''' response_v3_fail = Response() response_v3_fail.status_code = HTTP_RESPONSE_CODE_UNAUTHORIZED response_v3_fail._content = '''{"error": {"message": "The request you have made requires authentication.", "code": 401, "title": "Unauthorized"}}''' response2 = Response() response2.status_code = HTTP_RESPONSE_CODE_OK response2._content = ''' { "access":{ "token": { "expires":"2115-07-09T15:16:07Z", "id": { "token": "gg01eb8a8d69418c95f0009dda9bc1852", "tenant": "1111e3422ad84f7d828ce2f30373b3d4", "name": "*****@*****.**", "access_token": "4HMIFCQOlswp1hZmPG-BmP6cXQWyqvIYV0WrvoKptV59O4r3_VpIJwwFx-JgJW", "expires": "2114-09-13T07:23:51.000Z" }, "tenant": { "description": "Different Tenant from IDM", "enabled": true, "id":"1111e3422ad84f7d828ce2f30373b3d4", "name":"user" } }, "user": { "username": "******", "roles_links": [], "id": "user", "roles": [{ "id": "8db87ccbca3b4d1ba4814c3bb0d63aab", "name": "Member" }], "name":"user" } } }''' response_not_found = Response() response_not_found.status_code = HTTP_RESPONSE_CODE_UNAUTHORIZED response_not_found._content = 'User token not found' response_not_found._content = '{"unauthorized": {"message": {"error": {"message": "Could not find token: '\ + self.token_not_found + '", "code": 404, "title": "Not Found"}}, "code": 401}}' response_not_authorized = Response() response_not_authorized.status_code = HTTP_RESPONSE_CODE_OK response_not_authorized._content = 'Service not authorized' dic_valid = { "token": { "id": self.authToken, "tenant": { "enabled": True, "description": "Default tenant", "name": "admin", "id": "6571e3422ad84f7d828ce2f30373b3d4" } } } dic_invalid = { "token": { "id": self.authToken, "tenant": { "enabled": True, "description": "Default tenant", "name": "admin", "id": "anotherTenantId" } } } verification_expected = Token(manager, dic_valid) verification_expected_fail = Token(manager, dic_invalid) self.auth.__setattr__("auth_token", self.authToken) self.auth.__setattr__("tokens", self.tokenM) when(self.session_mocked).get_token().thenReturn(self.authToken) when(self.tokenM).authenticate( token=self.token, tenant_id=self.tenantId).thenReturn(verification_expected) when(self.tokenM).authenticate(token=self.fakeToken, tenant_id=self.tenantId)\ .thenReturn(verification_expected_fail) when(self.mockedClient).Client(username="******", password="******", auth_url=self.url)\ .thenReturn(self.auth) when(self.mockedClient).Client(username="******", password="******", auth_url=self.url_v3)\ .thenReturn(self.auth) when(self.mockedClient).Client(token=self.authToken, endpoint=self.url).thenReturn(self.auth) when(self.mockedClient)\ .Client(token=self.authToken, endpoint=self.url_noResponse).thenRaise(InternalServerError()) when(self.mockedClient)\ .Client(token=self.authToken, endpoint=self.url_server_error).thenRaise(Exception()) when(self.mockedClient).Client(username="******", password="******", auth_url=self.url).thenRaise( Unauthorized()) when(self.mockedClient)\ .Client(username="******", password="******", auth_url=self.url_server_error)\ .thenRaise(AuthorizationFailure()) headers = { ACCEPT_HEADER: JSON_TYPE, X_AUTH_TOKEN_HEADER: self.authToken } headers_v3 = { ACCEPT_HEADER: JSON_TYPE, X_AUTH_TOKEN_HEADER: self.authToken, X_SUBJECT_TOKEN_HEADER: self.token } headers_v3_fake = { ACCEPT_HEADER: JSON_TYPE, X_AUTH_TOKEN_HEADER: self.fakeToken, X_SUBJECT_TOKEN_HEADER: self.token } when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V2 + self.token, headers=headers)\ .thenReturn(response) when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V2 + self.token_not_expired, headers=headers)\ .thenReturn(response_not_expired) when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V3, headers=headers_v3)\ .thenReturn(response_v3) when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V3, headers=headers_v3_fake)\ .thenReturn(response_v3_fail) when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V2 + self.token_other_tenant, headers=headers)\ .thenReturn(response2) when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V2 + self.token_not_found, headers=headers)\ .thenReturn(response_not_found) when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V2 + self.token_not_authorized, headers=headers)\ .thenReturn(response_not_authorized) when(self.requestsMock).get(self.url + "/" + TOKENS_PATH_V2 + self.fakeToken, headers=headers)\ .thenRaise(Unauthorized()) when(self.requestsMock).get(self.url_noResponse + "/" + TOKENS_PATH_V2 + self.fakeToken, headers=headers)\ .thenRaise(InternalServerError()) when(self.requestsMock).get(self.url_server_error + "/" + TOKENS_PATH_V2 + self.token, headers=headers)\ .thenRaise(Exception()) self.a.client = self.requestsMock self.a.myClient = self.mockedClient self.a.session = self.session_client