Drop deprecated Keystone V2 API support
Keystone V2 API was deprecated in Stein release in Horizon and removed from Keystone in Queens release. Change-Id: I917e273d3174adf0874e516b3d635ccb8ba58a27
This commit is contained in:
parent
7c897b677c
commit
f33e5fd8ac
@ -492,7 +492,7 @@ OpenStack dashboard to use a specific API version for a given service API.
|
||||
|
||||
The version should be formatted as it appears in the URL for the
|
||||
service API. For example, the identity service APIs have inconsistent
|
||||
use of the decimal point, so valid options would be "2.0" or "3".
|
||||
use of the decimal point, so valid options would be "3".
|
||||
For example:
|
||||
|
||||
.. code-block:: python
|
||||
@ -1313,7 +1313,7 @@ Default: ``["admin"]``
|
||||
|
||||
The list of roles that have administrator privileges in this OpenStack
|
||||
installation. This check is very basic and essentially only works with
|
||||
keystone v2.0 and v3 with the default policy file. The setting assumes there
|
||||
keystone v3 with the default policy file. The setting assumes there
|
||||
is a common ``admin`` like role(s) across services. Example uses of this
|
||||
setting are:
|
||||
|
||||
|
@ -149,9 +149,7 @@ class KeystoneBackend(object):
|
||||
scoped_auth = domain_auth
|
||||
scoped_auth_ref = domain_auth_ref
|
||||
elif not scoped_auth_ref and not domain_auth_ref:
|
||||
msg = _('You are not authorized for any projects.')
|
||||
if utils.get_keystone_version() >= 3:
|
||||
msg = _('You are not authorized for any projects or domains.')
|
||||
msg = _('You are not authorized for any projects or domains.')
|
||||
raise exceptions.KeystoneAuthException(msg)
|
||||
|
||||
# Check expiry for our new scoped token.
|
||||
@ -170,16 +168,10 @@ class KeystoneBackend(object):
|
||||
|
||||
interface = settings.OPENSTACK_ENDPOINT_TYPE
|
||||
|
||||
endpoint, url_fixed = utils.fix_auth_url_version_prefix(
|
||||
scoped_auth_ref.service_catalog.url_for(
|
||||
service_type='identity',
|
||||
interface=interface,
|
||||
region_name=region_name))
|
||||
if url_fixed:
|
||||
LOG.warning("The Keystone URL in service catalog points to a v2.0 "
|
||||
"Keystone endpoint, but v3 is specified as the API "
|
||||
"version to use by Horizon. Using v3 endpoint for "
|
||||
"authentication.")
|
||||
endpoint = scoped_auth_ref.service_catalog.url_for(
|
||||
service_type='identity',
|
||||
interface=interface,
|
||||
region_name=region_name)
|
||||
|
||||
# If we made it here we succeeded. Create our User!
|
||||
unscoped_token = unscoped_auth_ref.auth_token
|
||||
|
@ -15,7 +15,6 @@ import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from keystoneauth1 import exceptions as keystone_exceptions
|
||||
from keystoneclient.v2_0 import client as v2_client
|
||||
from keystoneclient.v3 import client as v3_client
|
||||
import six
|
||||
|
||||
@ -82,16 +81,11 @@ class BasePlugin(object):
|
||||
or v3 keystoneclient projects objects.
|
||||
"""
|
||||
try:
|
||||
if self.keystone_version >= 3:
|
||||
client = v3_client.Client(session=session, auth=auth_plugin)
|
||||
if auth_ref.is_federated:
|
||||
return client.federation.projects.list()
|
||||
else:
|
||||
return client.projects.list(user=auth_ref.user_id)
|
||||
|
||||
client = v3_client.Client(session=session, auth=auth_plugin)
|
||||
if auth_ref.is_federated:
|
||||
return client.federation.projects.list()
|
||||
else:
|
||||
client = v2_client.Client(session=session, auth=auth_plugin)
|
||||
return client.tenants.list()
|
||||
return client.projects.list(user=auth_ref.user_id)
|
||||
|
||||
except (keystone_exceptions.ClientException,
|
||||
keystone_exceptions.AuthorizationFailure):
|
||||
@ -100,11 +94,8 @@ class BasePlugin(object):
|
||||
|
||||
def list_domains(self, session, auth_plugin, auth_ref=None):
|
||||
try:
|
||||
if self.keystone_version >= 3:
|
||||
client = v3_client.Client(session=session, auth=auth_plugin)
|
||||
return client.auth.domains()
|
||||
else:
|
||||
return []
|
||||
client = v3_client.Client(session=session, auth=auth_plugin)
|
||||
return client.auth.domains()
|
||||
except (keystone_exceptions.ClientException,
|
||||
keystone_exceptions.AuthorizationFailure):
|
||||
msg = _('Unable to retrieve authorized domains.')
|
||||
@ -203,8 +194,6 @@ class BasePlugin(object):
|
||||
session = utils.get_session()
|
||||
auth_url = unscoped_auth.auth_url
|
||||
|
||||
if utils.get_keystone_version() < 3:
|
||||
return None, None
|
||||
if domain_name:
|
||||
domains = [domain_name]
|
||||
else:
|
||||
|
@ -44,10 +44,8 @@ class K2KAuthPlugin(base.BasePlugin):
|
||||
|
||||
# Avoid mutable default arg for plugins
|
||||
plugins = plugins or []
|
||||
|
||||
# service_provider being None prevents infinite recursion
|
||||
if utils.get_keystone_version() < 3 or not service_provider:
|
||||
return None
|
||||
if not service_provider:
|
||||
return
|
||||
|
||||
keystone_idp_id = settings.KEYSTONE_PROVIDER_IDP_ID
|
||||
if service_provider == keystone_idp_id:
|
||||
|
@ -12,11 +12,9 @@
|
||||
|
||||
import logging
|
||||
|
||||
from keystoneauth1.identity import v2 as v2_auth
|
||||
from keystoneauth1.identity import v3 as v3_auth
|
||||
|
||||
from openstack_auth.plugin import base
|
||||
from openstack_auth import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -38,14 +36,8 @@ class PasswordPlugin(base.BasePlugin):
|
||||
|
||||
LOG.debug('Attempting to authenticate for %s', username)
|
||||
|
||||
if utils.get_keystone_version() >= 3:
|
||||
return v3_auth.Password(auth_url=auth_url,
|
||||
username=username,
|
||||
password=password,
|
||||
user_domain_name=user_domain_name,
|
||||
unscoped=True)
|
||||
|
||||
else:
|
||||
return v2_auth.Password(auth_url=auth_url,
|
||||
username=username,
|
||||
password=password)
|
||||
return v3_auth.Password(auth_url=auth_url,
|
||||
username=username,
|
||||
password=password,
|
||||
user_domain_name=user_domain_name,
|
||||
unscoped=True)
|
||||
|
@ -10,11 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from keystoneauth1.identity import v2 as v2_auth
|
||||
from keystoneauth1.identity import v3 as v3_auth
|
||||
|
||||
from openstack_auth.plugin import base
|
||||
from openstack_auth import utils
|
||||
|
||||
|
||||
__all__ = ['TokenPlugin']
|
||||
@ -28,14 +26,7 @@ class TokenPlugin(base.BasePlugin):
|
||||
if not all((auth_url, token)):
|
||||
return None
|
||||
|
||||
if utils.get_keystone_version() >= 3:
|
||||
return v3_auth.Token(auth_url=auth_url,
|
||||
token=token,
|
||||
project_id=project_id,
|
||||
reauthenticate=False)
|
||||
|
||||
else:
|
||||
return v2_auth.Token(auth_url=auth_url,
|
||||
token=token,
|
||||
tenant_id=project_id,
|
||||
reauthenticate=False)
|
||||
return v3_auth.Token(auth_url=auth_url,
|
||||
token=token,
|
||||
project_id=project_id,
|
||||
reauthenticate=False)
|
||||
|
@ -1,143 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from django.utils import datetime_safe
|
||||
from keystoneauth1.access import access
|
||||
from keystoneauth1.access import service_catalog
|
||||
from keystoneclient.v2_0 import roles
|
||||
from keystoneclient.v2_0 import tenants
|
||||
from keystoneclient.v2_0 import users
|
||||
|
||||
|
||||
class TestDataContainer(object):
|
||||
"""Arbitrary holder for test data in an object-oriented fashion."""
|
||||
pass
|
||||
|
||||
|
||||
def generate_test_data():
|
||||
'''Builds a set of test_data data as returned by Keystone V2.'''
|
||||
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': 'gabriel@example.com',
|
||||
'password': 'swordfish',
|
||||
'token': '',
|
||||
'enabled': True}
|
||||
test_data.user = users.User(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': 'tenant_two',
|
||||
'description': '',
|
||||
'enabled': False}
|
||||
test_data.tenant_one = tenants.Tenant(None, tenant_dict_1, loaded=True)
|
||||
test_data.tenant_two = tenants.Tenant(None, tenant_dict_2, loaded=True)
|
||||
|
||||
nova_service = {
|
||||
'type': 'compute',
|
||||
'name': 'nova',
|
||||
'endpoint_links': [],
|
||||
'endpoints': [
|
||||
{
|
||||
'region': 'RegionOne',
|
||||
'adminURL': ('http://nova-admin.localhost:8774/v2.0/%s'
|
||||
% (tenant_dict_1['id'])),
|
||||
'internalURL': ('http://nova-internal.localhost:8774/v2.0/%s'
|
||||
% (tenant_dict_1['id'])),
|
||||
'publicURL': ('http://nova-public.localhost:8774/v2.0/%s'
|
||||
% (tenant_dict_1['id']))
|
||||
},
|
||||
{
|
||||
'region': 'RegionTwo',
|
||||
'adminURL': ('http://nova2-admin.localhost:8774/v2.0/%s'
|
||||
% (tenant_dict_1['id'])),
|
||||
'internalURL': ('http://nova2-internal.localhost:8774/v2.0/%s'
|
||||
% (tenant_dict_1['id'])),
|
||||
'publicURL': ('http://nova2-public.localhost:8774/v2.0/%s'
|
||||
% (tenant_dict_1['id']))
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Roles
|
||||
role_dict = {'id': uuid.uuid4().hex,
|
||||
'name': 'Member'}
|
||||
test_data.role = roles.Role(roles.RoleManager, role_dict)
|
||||
|
||||
# Tokens
|
||||
tomorrow = datetime_safe.datetime.now() + datetime.timedelta(days=1)
|
||||
expiration = datetime_safe.datetime.isoformat(tomorrow)
|
||||
|
||||
scoped_token_dict = {
|
||||
'access': {
|
||||
'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, nova_service]
|
||||
}
|
||||
}
|
||||
|
||||
test_data.scoped_access_info = access.create(
|
||||
resp=None,
|
||||
body=scoped_token_dict)
|
||||
|
||||
unscoped_token_dict = {
|
||||
'access': {
|
||||
'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_access_info = access.create(
|
||||
resp=None,
|
||||
body=unscoped_token_dict)
|
||||
|
||||
# Service Catalog
|
||||
test_data.service_catalog = service_catalog.ServiceCatalogV2(
|
||||
[keystone_service, nova_service])
|
||||
|
||||
return test_data
|
@ -19,16 +19,13 @@ from django import test
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from keystoneauth1 import exceptions as keystone_exceptions
|
||||
from keystoneauth1.identity import v2 as v2_auth
|
||||
from keystoneauth1.identity import v3 as v3_auth
|
||||
from keystoneauth1 import session
|
||||
from keystoneauth1 import token_endpoint
|
||||
from keystoneclient.v2_0 import client as client_v2
|
||||
from keystoneclient.v3 import client as client_v3
|
||||
from mox3 import mox
|
||||
from testscenarios import load_tests_apply_scenarios
|
||||
|
||||
from openstack_auth.tests import data_v2
|
||||
from openstack_auth.tests import data_v3
|
||||
from openstack_auth import utils
|
||||
|
||||
@ -143,333 +140,6 @@ class OpenStackAuthFederatedTestsMixin(object):
|
||||
self._mock_unscoped_list_domains(client, domains)
|
||||
|
||||
|
||||
class OpenStackAuthTestsV2(OpenStackAuthTestsMixin, test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(OpenStackAuthTestsV2, self).setUp()
|
||||
|
||||
if getattr(self, 'interface', None):
|
||||
override = self.settings(OPENSTACK_ENDPOINT_TYPE=self.interface)
|
||||
override.enable()
|
||||
self.addCleanup(override.disable)
|
||||
|
||||
self.mox = mox.Mox()
|
||||
self.addCleanup(self.mox.VerifyAll)
|
||||
self.addCleanup(self.mox.UnsetStubs)
|
||||
|
||||
self.data = data_v2.generate_test_data()
|
||||
self.ks_client_module = client_v2
|
||||
|
||||
settings.OPENSTACK_API_VERSIONS['identity'] = 2.0
|
||||
settings.OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v2.0"
|
||||
|
||||
self.mox.StubOutClassWithMocks(token_endpoint, 'Token')
|
||||
self.mox.StubOutClassWithMocks(v2_auth, 'Token')
|
||||
self.mox.StubOutClassWithMocks(v2_auth, 'Password')
|
||||
self.mox.StubOutClassWithMocks(client_v2, 'Client')
|
||||
|
||||
def _mock_unscoped_list_tenants(self, client, tenants):
|
||||
client.tenants = self.mox.CreateMockAnything()
|
||||
client.tenants.list().AndReturn(tenants)
|
||||
|
||||
def _mock_unscoped_client_list_tenants(self, user, tenants):
|
||||
client = self._mock_unscoped_client(user)
|
||||
self._mock_unscoped_list_tenants(client, tenants)
|
||||
|
||||
def _create_password_auth(self, username=None, password=None, url=None):
|
||||
if not username:
|
||||
username = self.data.user.name
|
||||
|
||||
if not password:
|
||||
password = self.data.user.password
|
||||
|
||||
if not url:
|
||||
url = settings.OPENSTACK_KEYSTONE_URL
|
||||
|
||||
return v2_auth.Password(auth_url=url,
|
||||
password=password,
|
||||
username=username)
|
||||
|
||||
def _create_token_auth(self, project_id, token=None, url=None):
|
||||
if not token:
|
||||
token = self.data.unscoped_access_info.auth_token
|
||||
|
||||
if not url:
|
||||
url = settings.OPENSTACK_KEYSTONE_URL
|
||||
|
||||
return v2_auth.Token(auth_url=url,
|
||||
token=token,
|
||||
tenant_id=project_id,
|
||||
reauthenticate=False)
|
||||
|
||||
def _login(self):
|
||||
tenants = [self.data.tenant_one, self.data.tenant_two]
|
||||
user = self.data.user
|
||||
unscoped = self.data.unscoped_access_info
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
self._mock_unscoped_client_list_tenants(user, tenants)
|
||||
self._mock_scoped_client_for_tenant(unscoped, self.data.tenant_one.id)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
# GET the page to set the test cookie.
|
||||
response = self.client.get(url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# POST to the page to log in.
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
||||
|
||||
def test_login(self):
|
||||
self._login()
|
||||
|
||||
def test_login_with_disabled_tenant(self):
|
||||
# Test to validate that authentication will not try to get
|
||||
# scoped token for disabled project.
|
||||
tenants = [self.data.tenant_two, self.data.tenant_one]
|
||||
user = self.data.user
|
||||
unscoped = self.data.unscoped_access_info
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
self._mock_unscoped_client_list_tenants(user, tenants)
|
||||
self._mock_scoped_client_for_tenant(unscoped, self.data.tenant_one.id)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
# GET the page to set the test cookie.
|
||||
response = self.client.get(url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# POST to the page to log in.
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
||||
|
||||
def test_login_w_bad_region_cookie(self):
|
||||
self.client.cookies['services_region'] = "bad_region"
|
||||
self._login()
|
||||
self.assertNotEqual("bad_region",
|
||||
self.client.session['services_region'])
|
||||
self.assertEqual("RegionOne",
|
||||
self.client.session['services_region'])
|
||||
|
||||
def test_no_enabled_tenants(self):
|
||||
tenants = [self.data.tenant_two]
|
||||
user = self.data.user
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
self._mock_unscoped_client_list_tenants(user, tenants)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
# GET the page to set the test cookie.
|
||||
response = self.client.get(url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# POST to the page to log in.
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertTemplateUsed(response, 'auth/login.html')
|
||||
self.assertContains(response,
|
||||
'You are not authorized for any projects.')
|
||||
|
||||
def test_no_tenants(self):
|
||||
user = self.data.user
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
self._mock_unscoped_client_list_tenants(user, [])
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
# GET the page to set the test cookie.
|
||||
response = self.client.get(url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# POST to the page to log in.
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertTemplateUsed(response, 'auth/login.html')
|
||||
self.assertContains(response,
|
||||
'You are not authorized for any projects.')
|
||||
|
||||
def test_invalid_credentials(self):
|
||||
user = self.data.user
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
form_data['password'] = "invalid"
|
||||
|
||||
exc = keystone_exceptions.Unauthorized(401)
|
||||
self._mock_client_password_auth_failure(user.name, "invalid", exc)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
# GET the page to set the test cookie.
|
||||
response = self.client.get(url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# POST to the page to log in.
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertTemplateUsed(response, 'auth/login.html')
|
||||
self.assertContains(response, "Invalid credentials.")
|
||||
|
||||
def test_exception(self):
|
||||
user = self.data.user
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
exc = keystone_exceptions.ClientException(500)
|
||||
self._mock_client_password_auth_failure(user.name, user.password, exc)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
# GET the page to set the test cookie.
|
||||
response = self.client.get(url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# POST to the page to log in.
|
||||
response = self.client.post(url, form_data)
|
||||
|
||||
self.assertTemplateUsed(response, 'auth/login.html')
|
||||
self.assertContains(response,
|
||||
("An error occurred authenticating. Please try "
|
||||
"again later."))
|
||||
|
||||
def test_redirect_when_already_logged_in(self):
|
||||
self._login()
|
||||
|
||||
response = self.client.get(reverse('login'))
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertNotIn(reverse('login'), response['location'])
|
||||
|
||||
def test_dont_redirect_when_already_logged_in_if_next_is_set(self):
|
||||
self._login()
|
||||
|
||||
expected_url = "%s?%s=/%s/" % (reverse('login'),
|
||||
auth.REDIRECT_FIELD_NAME,
|
||||
'special')
|
||||
|
||||
response = self.client.get(expected_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'auth/login.html')
|
||||
|
||||
def test_switch(self, next=None):
|
||||
tenant = self.data.tenant_two
|
||||
tenants = [self.data.tenant_one, self.data.tenant_two]
|
||||
user = self.data.user
|
||||
unscoped = self.data.unscoped_access_info
|
||||
scoped = self.data.scoped_access_info
|
||||
sc = self.data.service_catalog
|
||||
et = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'publicURL')
|
||||
endpoint = sc.url_for(service_type='identity', interface=et)
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
|
||||
self._mock_unscoped_client_list_tenants(user, tenants)
|
||||
self._mock_scoped_client_for_tenant(unscoped, self.data.tenant_one.id)
|
||||
self._mock_scoped_client_for_tenant(scoped, tenant.id, url=endpoint,
|
||||
client=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
||||
|
||||
url = reverse('switch_tenants', args=[tenant.id])
|
||||
|
||||
scoped._token['tenant']['id'] = self.data.tenant_two.id
|
||||
|
||||
if next:
|
||||
form_data.update({auth.REDIRECT_FIELD_NAME: next})
|
||||
|
||||
response = self.client.get(url, form_data)
|
||||
|
||||
if next:
|
||||
expected_url = next
|
||||
self.assertEqual(response['location'], expected_url)
|
||||
else:
|
||||
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
||||
|
||||
self.assertEqual(self.client.session['token'].tenant['id'],
|
||||
scoped.tenant_id)
|
||||
|
||||
def test_switch_with_next(self):
|
||||
self.test_switch(next='/next_url')
|
||||
|
||||
def test_switch_region(self, next=None):
|
||||
tenants = [self.data.tenant_one, self.data.tenant_two]
|
||||
user = self.data.user
|
||||
scoped = self.data.scoped_access_info
|
||||
sc = self.data.service_catalog
|
||||
|
||||
form_data = self.get_form_data(user)
|
||||
|
||||
self._mock_unscoped_client_list_tenants(user, tenants)
|
||||
self._mock_scoped_client_for_tenant(scoped, self.data.tenant_one.id)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('login')
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
response = self.client.post(url, form_data)
|
||||
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
||||
|
||||
old_region = sc.get_endpoints()['compute'][0]['region']
|
||||
self.assertEqual(self.client.session['services_region'], old_region)
|
||||
|
||||
region = sc.get_endpoints()['compute'][1]['region']
|
||||
url = reverse('switch_services_region', args=[region])
|
||||
|
||||
form_data['region_name'] = region
|
||||
|
||||
if next:
|
||||
form_data.update({auth.REDIRECT_FIELD_NAME: next})
|
||||
|
||||
response = self.client.get(url, form_data)
|
||||
|
||||
if next:
|
||||
expected_url = next
|
||||
self.assertEqual(response['location'], expected_url)
|
||||
else:
|
||||
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
|
||||
|
||||
self.assertEqual(self.client.session['services_region'], region)
|
||||
self.assertEqual(self.client.cookies['services_region'].value, region)
|
||||
|
||||
def test_switch_region_with_next(self, next=None):
|
||||
self.test_switch_region(next='/next_url')
|
||||
|
||||
def test_tenant_sorting(self):
|
||||
tenants = [self.data.tenant_two, self.data.tenant_one]
|
||||
expected_tenants = [self.data.tenant_one, self.data.tenant_two]
|
||||
user = self.data.user
|
||||
unscoped = self.data.unscoped_access_info
|
||||
|
||||
client = self._mock_unscoped_client_with_token(user, unscoped)
|
||||
self._mock_unscoped_list_tenants(client, tenants)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
tenant_list = utils.get_project_list(
|
||||
user_id=user.id,
|
||||
auth_url=settings.OPENSTACK_KEYSTONE_URL,
|
||||
token=unscoped.auth_token)
|
||||
self.assertEqual(tenant_list, expected_tenants)
|
||||
|
||||
|
||||
class OpenStackAuthTestsV3(OpenStackAuthTestsMixin,
|
||||
OpenStackAuthFederatedTestsMixin,
|
||||
test.TestCase):
|
||||
|
@ -11,7 +11,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from django.conf import settings
|
||||
from django import http
|
||||
from django import test
|
||||
from django.test import client
|
||||
@ -55,41 +54,6 @@ class RoleTestCaseAdmin(test.TestCase):
|
||||
|
||||
class UtilsTestCase(test.TestCase):
|
||||
|
||||
def test_fix_auth_url_version_v20(self):
|
||||
settings.OPENSTACK_API_VERSIONS['identity'] = 2.0
|
||||
test_urls = [
|
||||
("http://a/", ("http://a/v2.0", False)),
|
||||
("http://a", ("http://a/v2.0", False)),
|
||||
("http://a:8080/", ("http://a:8080/v2.0", False)),
|
||||
("http://a/v2.0", ("http://a/v2.0", False)),
|
||||
("http://a/v2.0/", ("http://a/v2.0/", False)),
|
||||
("http://a/identity", ("http://a/identity/v2.0", False)),
|
||||
("http://a/identity/", ("http://a/identity/v2.0", False)),
|
||||
("http://a:5000/identity/v2.0",
|
||||
("http://a:5000/identity/v2.0", False)),
|
||||
("http://a/identity/v2.0/", ("http://a/identity/v2.0/", False))
|
||||
]
|
||||
for src, expected in test_urls:
|
||||
self.assertEqual(expected, utils.fix_auth_url_version_prefix(src))
|
||||
|
||||
def test_fix_auth_url_version_v3(self):
|
||||
settings.OPENSTACK_API_VERSIONS['identity'] = 3
|
||||
test_urls = [
|
||||
("http://a/", ("http://a/v3", False)),
|
||||
("http://a", ("http://a/v3", False)),
|
||||
("http://a:8080/", ("http://a:8080/v3", False)),
|
||||
("http://a/v3", ("http://a/v3", False)),
|
||||
("http://a/v3/", ("http://a/v3/", False)),
|
||||
("http://a/v2.0/", ("http://a/v3/", True)),
|
||||
("http://a/v2.0", ("http://a/v3", True)),
|
||||
("http://a/identity", ("http://a/identity/v3", False)),
|
||||
("http://a:5000/identity/", ("http://a:5000/identity/v3", False)),
|
||||
("http://a/identity/v3", ("http://a/identity/v3", False)),
|
||||
("http://a/identity/v3/", ("http://a/identity/v3/", False))
|
||||
]
|
||||
for src, expected in test_urls:
|
||||
self.assertEqual(expected, utils.fix_auth_url_version_prefix(src))
|
||||
|
||||
@override_settings(DEFAULT_SERVICE_REGIONS={
|
||||
'http://example.com': 'RegionThree', '*': 'RegionFour'})
|
||||
def test_default_services_region_precedence(self):
|
||||
|
@ -19,11 +19,9 @@ from django.conf import settings
|
||||
from django.contrib import auth
|
||||
from django.contrib.auth import models
|
||||
from django.utils import timezone
|
||||
from keystoneauth1.identity import v2 as v2_auth
|
||||
from keystoneauth1.identity import v3 as v3_auth
|
||||
from keystoneauth1 import session
|
||||
from keystoneauth1 import token_endpoint
|
||||
from keystoneclient.v2_0 import client as client_v2
|
||||
from keystoneclient.v3 import client as client_v3
|
||||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
@ -116,17 +114,12 @@ def get_session():
|
||||
|
||||
|
||||
def get_keystone_client():
|
||||
if get_keystone_version() < 3:
|
||||
return client_v2
|
||||
else:
|
||||
return client_v3
|
||||
return client_v3
|
||||
|
||||
|
||||
def is_websso_enabled():
|
||||
"""Websso is supported in Keystone version 3."""
|
||||
websso_enabled = settings.WEBSSO_ENABLED
|
||||
keystonev3_plus = (get_keystone_version() >= 3)
|
||||
return websso_enabled and keystonev3_plus
|
||||
return settings.WEBSSO_ENABLED
|
||||
|
||||
|
||||
def is_websso_default_redirect():
|
||||
@ -275,26 +268,24 @@ def _augment_url_with_version(auth_url):
|
||||
the identity URLs returned by Keystone might no longer contain API
|
||||
versions, leaving the version choice up to the user.
|
||||
"""
|
||||
if has_in_url_path(auth_url, ["/v2.0", "/v3"]):
|
||||
if has_in_url_path(auth_url, ["/v3"]):
|
||||
return auth_url
|
||||
|
||||
if get_keystone_version() >= 3:
|
||||
return url_path_append(auth_url, "/v3")
|
||||
else:
|
||||
return url_path_append(auth_url, "/v2.0")
|
||||
return url_path_append(auth_url, "/v3")
|
||||
|
||||
|
||||
def fix_auth_url_version_prefix(auth_url):
|
||||
"""Fix up the auth url if an invalid or no version prefix was given.
|
||||
|
||||
People still give a v2 auth_url even when they specify that they want v3
|
||||
authentication. Fix the URL to say v3 in this case and add version if it is
|
||||
Fix the URL to say v3 in this case and add version if it is
|
||||
missing entirely. This should be smarter and use discovery.
|
||||
Until version discovery is implemented we need this method to get
|
||||
everything working.
|
||||
"""
|
||||
auth_url = _augment_url_with_version(auth_url)
|
||||
|
||||
url_fixed = False
|
||||
if get_keystone_version() >= 3 and has_in_url_path(auth_url, ["/v2.0"]):
|
||||
if has_in_url_path(auth_url, ["/v2.0"]):
|
||||
url_fixed = True
|
||||
auth_url = url_path_replace(auth_url, "/v2.0", "/v3", 1)
|
||||
|
||||
@ -312,21 +303,15 @@ def clean_up_auth_url(auth_url):
|
||||
|
||||
|
||||
def get_token_auth_plugin(auth_url, token, project_id=None, domain_name=None):
|
||||
if get_keystone_version() >= 3:
|
||||
if domain_name:
|
||||
return v3_auth.Token(auth_url=auth_url,
|
||||
token=token,
|
||||
domain_name=domain_name,
|
||||
reauthenticate=False)
|
||||
else:
|
||||
return v3_auth.Token(auth_url=auth_url,
|
||||
token=token,
|
||||
project_id=project_id,
|
||||
reauthenticate=False)
|
||||
else:
|
||||
return v2_auth.Token(auth_url=auth_url,
|
||||
if domain_name:
|
||||
return v3_auth.Token(auth_url=auth_url,
|
||||
token=token,
|
||||
tenant_id=project_id,
|
||||
domain_name=domain_name,
|
||||
reauthenticate=False)
|
||||
else:
|
||||
return v3_auth.Token(auth_url=auth_url,
|
||||
token=token,
|
||||
project_id=project_id,
|
||||
reauthenticate=False)
|
||||
|
||||
|
||||
|
@ -33,12 +33,10 @@ from openstack_auth import backend
|
||||
from openstack_auth import utils as auth_utils
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import messages
|
||||
|
||||
from openstack_dashboard.api import base
|
||||
from openstack_dashboard.contrib.developer.profiler import api as profiler
|
||||
from openstack_dashboard import policy
|
||||
from openstack_dashboard.utils import settings as utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -56,25 +54,13 @@ class IdentityAPIVersionManager(base.APIVersionManager):
|
||||
return user
|
||||
|
||||
def get_project_manager(self, *args, **kwargs):
|
||||
if VERSIONS.active < 3:
|
||||
manager = keystoneclient(*args, **kwargs).tenants
|
||||
else:
|
||||
manager = keystoneclient(*args, **kwargs).projects
|
||||
return manager
|
||||
return keystoneclient(*args, **kwargs).projects
|
||||
|
||||
|
||||
VERSIONS = IdentityAPIVersionManager(
|
||||
"identity", preferred_version=auth_utils.get_keystone_version())
|
||||
|
||||
|
||||
# Import from oldest to newest so that "preferred" takes correct precedence.
|
||||
try:
|
||||
# pylint: disable=ungrouped-imports
|
||||
from keystoneclient.v2_0 import client as keystone_client_v2
|
||||
VERSIONS.load_supported_version(2.0, {"client": keystone_client_v2})
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
# pylint: disable=ungrouped-imports
|
||||
from keystoneclient.v3 import client as keystone_client_v3
|
||||
@ -266,12 +252,9 @@ def tenant_create(request, name, description=None, enabled=None,
|
||||
domain=None, **kwargs):
|
||||
manager = VERSIONS.get_project_manager(request, admin=True)
|
||||
try:
|
||||
if VERSIONS.active < 3:
|
||||
return manager.create(name, description, enabled, **kwargs)
|
||||
else:
|
||||
return manager.create(name, domain,
|
||||
description=description,
|
||||
enabled=enabled, **kwargs)
|
||||
return manager.create(name, domain,
|
||||
description=description,
|
||||
enabled=enabled, **kwargs)
|
||||
except keystone_exceptions.Conflict:
|
||||
raise exceptions.Conflict()
|
||||
|
||||
@ -364,25 +347,13 @@ def tenant_delete(request, project):
|
||||
def tenant_list(request, paginate=False, marker=None, domain=None, user=None,
|
||||
admin=True, filters=None):
|
||||
manager = VERSIONS.get_project_manager(request, admin=admin)
|
||||
page_size = utils.get_page_size(request)
|
||||
tenants = []
|
||||
limit = None
|
||||
if paginate:
|
||||
limit = page_size + 1
|
||||
|
||||
has_more_data = False
|
||||
|
||||
# if requesting the projects for the current user,
|
||||
# return the list from the cache
|
||||
if user == request.user.id:
|
||||
tenants = request.user.authorized_tenants
|
||||
|
||||
elif VERSIONS.active < 3:
|
||||
tenants = manager.list(limit, marker)
|
||||
if paginate and len(tenants) > page_size:
|
||||
tenants.pop(-1)
|
||||
has_more_data = True
|
||||
# V3 API
|
||||
else:
|
||||
domain_id = get_effective_domain_id(request)
|
||||
kwargs = {
|
||||
@ -408,12 +379,8 @@ def tenant_update(request, project, name=None, description=None,
|
||||
enabled=None, domain=None, **kwargs):
|
||||
manager = VERSIONS.get_project_manager(request, admin=True)
|
||||
try:
|
||||
if VERSIONS.active < 3:
|
||||
return manager.update(project, name, description, enabled,
|
||||
**kwargs)
|
||||
else:
|
||||
return manager.update(project, name=name, description=description,
|
||||
enabled=enabled, domain=domain, **kwargs)
|
||||
return manager.update(project, name=name, description=description,
|
||||
enabled=enabled, domain=domain, **kwargs)
|
||||
except keystone_exceptions.Conflict:
|
||||
raise exceptions.Conflict()
|
||||
|
||||
@ -421,16 +388,13 @@ def tenant_update(request, project, name=None, description=None,
|
||||
@profiler.trace
|
||||
def user_list(request, project=None, domain=None, group=None, filters=None):
|
||||
users = []
|
||||
if VERSIONS.active < 3:
|
||||
kwargs = {"tenant_id": project}
|
||||
else:
|
||||
kwargs = {
|
||||
"project": project,
|
||||
"domain": domain,
|
||||
"group": group
|
||||
}
|
||||
if filters is not None:
|
||||
kwargs.update(filters)
|
||||
kwargs = {
|
||||
"project": project,
|
||||
"domain": domain,
|
||||
"group": group
|
||||
}
|
||||
if filters is not None:
|
||||
kwargs.update(filters)
|
||||
if 'id' in kwargs:
|
||||
try:
|
||||
users = [user_get(request, kwargs['id'])]
|
||||
@ -446,14 +410,10 @@ def user_create(request, name=None, email=None, password=None, project=None,
|
||||
enabled=None, domain=None, description=None, **data):
|
||||
manager = keystoneclient(request, admin=True).users
|
||||
try:
|
||||
if VERSIONS.active < 3:
|
||||
user = manager.create(name, password, email, project, enabled)
|
||||
return VERSIONS.upgrade_v2_user(user)
|
||||
else:
|
||||
return manager.create(name, password=password, email=email,
|
||||
default_project=project, enabled=enabled,
|
||||
domain=domain, description=description,
|
||||
**data)
|
||||
return manager.create(name, password=password, email=email,
|
||||
default_project=project, enabled=enabled,
|
||||
domain=domain, description=description,
|
||||
**data)
|
||||
except keystone_exceptions.Conflict:
|
||||
raise exceptions.Conflict()
|
||||
|
||||
@ -472,59 +432,20 @@ def user_get(request, user_id, admin=True):
|
||||
@profiler.trace
|
||||
def user_update(request, user, **data):
|
||||
manager = keystoneclient(request, admin=True).users
|
||||
error = None
|
||||
|
||||
if not keystone_can_edit_user():
|
||||
raise keystone_exceptions.ClientException(
|
||||
405, _("Identity service does not allow editing user data."))
|
||||
|
||||
# The v2 API updates user model and default project separately
|
||||
if VERSIONS.active < 3:
|
||||
# Update user details
|
||||
try:
|
||||
user = manager.update(user, **data)
|
||||
except keystone_exceptions.Conflict:
|
||||
raise exceptions.Conflict()
|
||||
except Exception:
|
||||
error = exceptions.handle(request, ignore=True)
|
||||
|
||||
if "project" in data:
|
||||
project = data.pop('project')
|
||||
|
||||
# Update default tenant
|
||||
try:
|
||||
user_update_tenant(request, user, project)
|
||||
user.tenantId = project
|
||||
except Exception:
|
||||
error = exceptions.handle(request, ignore=True)
|
||||
|
||||
# Check for existing roles
|
||||
# Show a warning if no role exists for the project
|
||||
user_roles = roles_for_user(request, user, project)
|
||||
if not user_roles:
|
||||
messages.warning(request,
|
||||
_('User %s has no role defined for '
|
||||
'that project.')
|
||||
% data.get('name', None))
|
||||
|
||||
if error is not None:
|
||||
raise error
|
||||
|
||||
# v3 API is so much simpler...
|
||||
else:
|
||||
try:
|
||||
user = manager.update(user, **data)
|
||||
except keystone_exceptions.Conflict:
|
||||
raise exceptions.Conflict()
|
||||
try:
|
||||
user = manager.update(user, **data)
|
||||
except keystone_exceptions.Conflict:
|
||||
raise exceptions.Conflict()
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def user_update_enabled(request, user, enabled):
|
||||
manager = keystoneclient(request, admin=True).users
|
||||
if VERSIONS.active < 3:
|
||||
manager.update_enabled(user, enabled)
|
||||
else:
|
||||
manager.update(user, enabled=enabled)
|
||||
manager.update(user, enabled=enabled)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
@ -535,16 +456,13 @@ def user_update_password(request, user, password, admin=True):
|
||||
405, _("Identity service does not allow editing user password."))
|
||||
|
||||
manager = keystoneclient(request, admin=admin).users
|
||||
if VERSIONS.active < 3:
|
||||
manager.update_password(user, password)
|
||||
else:
|
||||
manager.update(user, password=password)
|
||||
manager.update(user, password=password)
|
||||
|
||||
|
||||
def user_verify_admin_password(request, admin_password):
|
||||
# attempt to create a new client instance with admin password to
|
||||
# verify if it's correct.
|
||||
client = keystone_client_v2 if VERSIONS.active < 3 else keystone_client_v3
|
||||
client = keystone_client_v3
|
||||
try:
|
||||
endpoint = _get_endpoint_url(request, 'publicURL')
|
||||
insecure = settings.OPENSTACK_SSL_NO_VERIFY
|
||||
@ -565,21 +483,14 @@ def user_verify_admin_password(request, admin_password):
|
||||
@profiler.trace
|
||||
def user_update_own_password(request, origpassword, password):
|
||||
client = keystoneclient(request, admin=False)
|
||||
if VERSIONS.active < 3:
|
||||
client.user_id = request.user.id
|
||||
return client.users.update_own_password(origpassword, password)
|
||||
else:
|
||||
client.users.client.session.auth.user_id = request.user.id
|
||||
return client.users.update_password(origpassword, password)
|
||||
client.users.client.session.auth.user_id = request.user.id
|
||||
return client.users.update_password(origpassword, password)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def user_update_tenant(request, user, project, admin=True):
|
||||
manager = keystoneclient(request, admin=admin).users
|
||||
if VERSIONS.active < 3:
|
||||
return manager.update_tenant(user, project)
|
||||
else:
|
||||
return manager.update(user, project=project)
|
||||
return manager.update(user, project=project)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
@ -689,9 +600,6 @@ def get_project_groups_roles(request, project):
|
||||
def role_assignments_list(request, project=None, user=None, role=None,
|
||||
group=None, domain=None, effective=False,
|
||||
include_subtree=True, include_names=False):
|
||||
if VERSIONS.active < 3:
|
||||
raise exceptions.NotAvailable
|
||||
|
||||
if include_subtree:
|
||||
domain = None
|
||||
|
||||
@ -751,10 +659,7 @@ def role_list(request, filters=None):
|
||||
def roles_for_user(request, user, project=None, domain=None):
|
||||
"""Returns a list of user roles scoped to a project or domain."""
|
||||
manager = keystoneclient(request, admin=True).roles
|
||||
if VERSIONS.active < 3:
|
||||
return manager.roles_for_user(user, project)
|
||||
else:
|
||||
return manager.list(user=user, domain=domain, project=project)
|
||||
return manager.list(user=user, domain=domain, project=project)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
@ -793,26 +698,18 @@ def remove_domain_user_role(request, user, role, domain=None):
|
||||
@profiler.trace
|
||||
def get_project_users_roles(request, project):
|
||||
users_roles = collections.defaultdict(list)
|
||||
if VERSIONS.active < 3:
|
||||
project_users = user_list(request, project=project)
|
||||
project_role_assignments = role_assignments_list(request,
|
||||
project=project)
|
||||
for role_assignment in project_role_assignments:
|
||||
if not hasattr(role_assignment, 'user'):
|
||||
continue
|
||||
user_id = role_assignment.user['id']
|
||||
role_id = role_assignment.role['id']
|
||||
|
||||
for user in project_users:
|
||||
roles = roles_for_user(request, user.id, project)
|
||||
roles_ids = [role.id for role in roles]
|
||||
users_roles[user.id].extend(roles_ids)
|
||||
else:
|
||||
project_role_assignments = role_assignments_list(request,
|
||||
project=project)
|
||||
for role_assignment in project_role_assignments:
|
||||
if not hasattr(role_assignment, 'user'):
|
||||
continue
|
||||
user_id = role_assignment.user['id']
|
||||
role_id = role_assignment.role['id']
|
||||
|
||||
# filter by project_id
|
||||
if ('project' in role_assignment.scope and
|
||||
role_assignment.scope['project']['id'] == project):
|
||||
users_roles[user_id].append(role_id)
|
||||
# filter by project_id
|
||||
if ('project' in role_assignment.scope and
|
||||
role_assignment.scope['project']['id'] == project):
|
||||
users_roles[user_id].append(role_id)
|
||||
return users_roles
|
||||
|
||||
|
||||
@ -821,11 +718,8 @@ def add_tenant_user_role(request, project=None, user=None, role=None,
|
||||
group=None, domain=None):
|
||||
"""Adds a role for a user on a tenant."""
|
||||
manager = keystoneclient(request, admin=True).roles
|
||||
if VERSIONS.active < 3:
|
||||
manager.add_user_role(user, role, project)
|
||||
else:
|
||||
manager.grant(role, user=user, project=project,
|
||||
group=group, domain=domain)
|
||||
manager.grant(role, user=user, project=project,
|
||||
group=group, domain=domain)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
@ -833,11 +727,8 @@ def remove_tenant_user_role(request, project=None, user=None, role=None,
|
||||
group=None, domain=None):
|
||||
"""Removes a given single role for a user from a tenant."""
|
||||
manager = keystoneclient(request, admin=True).roles
|
||||
if VERSIONS.active < 3:
|
||||
return manager.remove_user_role(user, role, project)
|
||||
else:
|
||||
return manager.revoke(role, user=user, project=project,
|
||||
group=group, domain=domain)
|
||||
return manager.revoke(role, user=user, project=project,
|
||||
group=group, domain=domain)
|
||||
|
||||
|
||||
def remove_tenant_user(request, project=None, user=None, domain=None):
|
||||
@ -907,9 +798,8 @@ def ec2_manager(request):
|
||||
if hasattr(client, 'ec2'):
|
||||
return client.ec2
|
||||
|
||||
# Keystoneclient 4.0 was released without the ec2 creds manager.
|
||||
from keystoneclient.v2_0 import ec2
|
||||
return ec2.CredentialsManager(client)
|
||||
from keystoneclient.v3 import ec2
|
||||
return ec2.EC2Manager(client)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
|
@ -128,7 +128,7 @@ def swift_api(request):
|
||||
preauthurl=endpoint,
|
||||
cacert=cacert,
|
||||
insecure=insecure,
|
||||
auth_version="2.0")
|
||||
auth_version="3")
|
||||
|
||||
|
||||
@profiler.trace
|
||||
|
@ -19,8 +19,6 @@ from django.urls import reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from openstack_auth import utils
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
@ -121,7 +119,6 @@ def _get_context(request):
|
||||
auth_url = api.base.url_for(request,
|
||||
'identity',
|
||||
endpoint_type='publicURL')
|
||||
auth_url, url_fixed = utils.fix_auth_url_version_prefix(auth_url)
|
||||
interface = 'public'
|
||||
region = getattr(request.user, 'services_region', '')
|
||||
app_cred = request.session['application_credential']
|
||||
|
@ -30,9 +30,6 @@ class Domains(horizon.Panel):
|
||||
return keystone.VERSIONS.active >= 3
|
||||
|
||||
def can_access(self, context):
|
||||
if keystone.VERSIONS.active < 3:
|
||||
return super(Domains, self).can_access(context)
|
||||
|
||||
request = context['request']
|
||||
domain_token = request.session.get('domain_token')
|
||||
return super(Domains, self).can_access(context) and domain_token
|
||||
|
@ -149,11 +149,8 @@ class ModifyQuotas(tables.LinkAction):
|
||||
policy_rules = (('compute', "os_compute_api:os-quota-sets:update"),)
|
||||
|
||||
def allowed(self, request, datum):
|
||||
if api.keystone.VERSIONS.active < 3:
|
||||
return True
|
||||
else:
|
||||
return (api.keystone.is_cloud_admin(request) and
|
||||
quotas.enabled_quotas(request))
|
||||
return (api.keystone.is_cloud_admin(request) and
|
||||
quotas.enabled_quotas(request))
|
||||
|
||||
def get_link_url(self, project):
|
||||
step = 'update_quotas'
|
||||
@ -198,13 +195,10 @@ class DeleteTenantsAction(policy.PolicyTargetMixin, tables.DeleteAction):
|
||||
|
||||
|
||||
class TenantFilterAction(tables.FilterAction):
|
||||
if api.keystone.VERSIONS.active < 3:
|
||||
filter_type = "query"
|
||||
else:
|
||||
filter_type = "server"
|
||||
filter_choices = (('name', _("Project Name ="), True),
|
||||
('id', _("Project ID ="), True),
|
||||
('enabled', _("Enabled ="), True, _('e.g. Yes/No')))
|
||||
filter_type = "server"
|
||||
filter_choices = (('name', _("Project Name ="), True),
|
||||
('id', _("Project ID ="), True),
|
||||
('enabled', _("Enabled ="), True, _('e.g. Yes/No')))
|
||||
|
||||
|
||||
class UpdateRow(tables.Row):
|
||||
|
@ -21,7 +21,6 @@ from openstack_dashboard import policy
|
||||
|
||||
ENABLE = 0
|
||||
DISABLE = 1
|
||||
KEYSTONE_V2_ENABLED = api.keystone.VERSIONS.active < 3
|
||||
|
||||
|
||||
class CreateUserLink(tables.LinkAction):
|
||||
@ -186,7 +185,6 @@ class UsersTable(tables.DataTable):
|
||||
form_field=forms.CharField(required=False))
|
||||
description = tables.Column(lambda obj: getattr(obj, 'description', None),
|
||||
verbose_name=_('Description'),
|
||||
hidden=KEYSTONE_V2_ENABLED,
|
||||
form_field=forms.CharField(
|
||||
widget=forms.Textarea(attrs={'rows': 4}),
|
||||
required=False))
|
||||
|
@ -16,8 +16,6 @@ from django.conf import settings
|
||||
from django.template.defaultfilters import title
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from openstack_auth import utils
|
||||
|
||||
from horizon import tables
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.api_access import forms
|
||||
@ -63,8 +61,7 @@ class DownloadOpenRC(tables.LinkAction):
|
||||
url = "horizon:project:api_access:openrc"
|
||||
|
||||
def allowed(self, request, datum=None):
|
||||
return (settings.SHOW_OPENRC_FILE and
|
||||
utils.get_keystone_version() >= 3)
|
||||
return settings.SHOW_OPENRC_FILE
|
||||
|
||||
|
||||
class ViewCredentials(tables.LinkAction):
|
||||
|
@ -24,8 +24,6 @@ from django.template.loader import render_to_string
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from openstack_auth import utils
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import messages
|
||||
@ -131,9 +129,6 @@ def download_rc_file(request):
|
||||
except KeyError:
|
||||
project_domain_id = ''
|
||||
context['project_domain_id'] = project_domain_id
|
||||
# sanity fix for removing v2.0 from the url if present
|
||||
context['auth_url'], _ = utils.fix_auth_url_version_prefix(
|
||||
context['auth_url'])
|
||||
context['os_identity_api_version'] = 3
|
||||
context['os_auth_version'] = 3
|
||||
return _download_rc_file_for_template(request, context, template)
|
||||
@ -150,14 +145,9 @@ def download_clouds_yaml_file(request):
|
||||
region_tuple[1] for region_tuple in settings.AVAILABLE_REGIONS
|
||||
]
|
||||
|
||||
if utils.get_keystone_version() >= 3:
|
||||
# make v3 specific changes
|
||||
context['user_domain_name'] = request.user.user_domain_name
|
||||
# sanity fix for removing v2.0 from the url if present
|
||||
context['auth_url'], _ = utils.fix_auth_url_version_prefix(
|
||||
context['auth_url'])
|
||||
context['os_identity_api_version'] = 3
|
||||
context['os_auth_version'] = 3
|
||||
context['user_domain_name'] = request.user.user_domain_name
|
||||
context['os_identity_api_version'] = 3
|
||||
context['os_auth_version'] = 3
|
||||
|
||||
return _download_rc_file_for_template(request, context, template,
|
||||
'clouds.yaml')
|
||||
|
@ -15,7 +15,6 @@ from os.path import join
|
||||
from os import remove
|
||||
|
||||
from horizon.test import firefox_binary
|
||||
from openstack_dashboard.test.integration_tests import decorators
|
||||
from openstack_dashboard.test.integration_tests import helpers
|
||||
|
||||
|
||||
@ -41,27 +40,6 @@ class TestDownloadRCFile(helpers.AdminTestCase):
|
||||
|
||||
self.addCleanup(cleanup)
|
||||
|
||||
@decorators.skip_because(bugs=['1792028'])
|
||||
def test_download_rc_v2_file(self):
|
||||
"""This is a basic scenario test:
|
||||
|
||||
Steps:
|
||||
1) Login to Horizon Dashboard as admin user
|
||||
2) Navigate to Project > API Access tab
|
||||
3) Click on "Download OpenStack RC File" dropdown button
|
||||
4) Click on "OpenStack RC File (Identity API v2.0" button
|
||||
5) File named by template "<tenant_name>-openrc.sh" must be downloaded
|
||||
6) Check that username, tenant name and tenant id correspond to current
|
||||
username, tenant name and tenant id
|
||||
"""
|
||||
api_access_page = self.home_pg.\
|
||||
go_to_project_apiaccesspage()
|
||||
api_access_page.download_openstack_rc_file(
|
||||
2, self._directory, self._openrc_template)
|
||||
cred_dict = api_access_page.get_credentials_from_file(
|
||||
2, self._directory, self._openrc_template)
|
||||
self.assertEqual(cred_dict, self.actual_dict)
|
||||
|
||||
def test_download_rc_v3_file(self):
|
||||
"""This is a basic scenario test:
|
||||
|
||||
|
@ -29,10 +29,10 @@ class KeystoneRestTestCase(test.TestCase):
|
||||
@test.create_mocks({api.keystone: ['get_version']})
|
||||
def test_version_get(self):
|
||||
request = self.mock_rest_request()
|
||||
self.mock_get_version.return_value = '2.0'
|
||||
self.mock_get_version.return_value = '3'
|
||||
response = keystone.Version().get(request)
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual(response.json, {"version": "2.0"})
|
||||
self.assertEqual(response.json, {"version": "3"})
|
||||
self.mock_get_version.assert_called_once_with()
|
||||
|
||||
#
|
||||
|
@ -237,7 +237,7 @@ class ApiVersionTests(test.TestCase):
|
||||
self.previous_settings = settings.OPENSTACK_API_VERSIONS
|
||||
settings.OPENSTACK_API_VERSIONS = {
|
||||
"data-processing": 1.1,
|
||||
"identity": "2.0",
|
||||
"identity": "3",
|
||||
"volume": 1
|
||||
}
|
||||
# Make sure cached data from other tests doesn't interfere
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
Keystone API V2 support has been dropped in Train release. Keystone V2 API
|
||||
support was deprecated in Stein release. If you use Keystone V2 before, you
|
||||
should update the `OPENSTACK_API_VERSIONS` configuration option to use
|
||||
Keystone V3 API.
|
Loading…
Reference in New Issue
Block a user