Allow tenant ID for authentication
Under the Keystone v3 API Tenant names are not necessarily uniques across Domains for a User, so the client should also allow authentication by tenant_id Fixes bug 1196486 Change-Id: I3f385a19c1d3d66f5539f901796bbaa22d315762
This commit is contained in:
parent
4e3be8d342
commit
037497da52
@ -94,7 +94,7 @@ class HTTPClient(httplib2.Http):
|
||||
|
||||
USER_AGENT = 'python-neutronclient'
|
||||
|
||||
def __init__(self, username=None, tenant_name=None,
|
||||
def __init__(self, username=None, tenant_name=None, tenant_id=None,
|
||||
password=None, auth_url=None,
|
||||
token=None, region_name=None, timeout=None,
|
||||
endpoint_url=None, insecure=False,
|
||||
@ -103,6 +103,7 @@ class HTTPClient(httplib2.Http):
|
||||
super(HTTPClient, self).__init__(timeout=timeout)
|
||||
self.username = username
|
||||
self.tenant_name = tenant_name
|
||||
self.tenant_id = tenant_id
|
||||
self.password = password
|
||||
self.auth_url = auth_url.rstrip('/') if auth_url else None
|
||||
self.endpoint_type = endpoint_type
|
||||
@ -183,10 +184,16 @@ class HTTPClient(httplib2.Http):
|
||||
def authenticate(self):
|
||||
if self.auth_strategy != 'keystone':
|
||||
raise exceptions.Unauthorized(message='unknown auth strategy')
|
||||
body = {'auth': {'passwordCredentials':
|
||||
{'username': self.username,
|
||||
'password': self.password, },
|
||||
'tenantName': self.tenant_name, }, }
|
||||
if self.tenant_id:
|
||||
body = {'auth': {'passwordCredentials':
|
||||
{'username': self.username,
|
||||
'password': self.password, },
|
||||
'tenantId': self.tenant_id, }, }
|
||||
else:
|
||||
body = {'auth': {'passwordCredentials':
|
||||
{'username': self.username,
|
||||
'password': self.password, },
|
||||
'tenantName': self.tenant_name, }, }
|
||||
|
||||
token_url = self.auth_url + "/tokens"
|
||||
|
||||
|
@ -76,6 +76,7 @@ class ClientManager(object):
|
||||
if not self._url:
|
||||
httpclient = client.HTTPClient(username=self._username,
|
||||
tenant_name=self._tenant_name,
|
||||
tenant_id=self._tenant_id,
|
||||
password=self._password,
|
||||
region_name=self._region_name,
|
||||
auth_url=self._auth_url,
|
||||
|
@ -295,6 +295,11 @@ class NeutronShell(app.App):
|
||||
'--os_tenant_name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
'--os-tenant-id', metavar='<auth-tenant-id>',
|
||||
default=env('OS_TENANT_ID'),
|
||||
help='Authentication tenant name (Env: OS_TENANT_ID)')
|
||||
|
||||
parser.add_argument(
|
||||
'--os-username', metavar='<auth-username>',
|
||||
default=utils.env('OS_USERNAME'),
|
||||
@ -482,10 +487,12 @@ class NeutronShell(app.App):
|
||||
"You must provide a password via"
|
||||
" either --os-password or env[OS_PASSWORD]")
|
||||
|
||||
if not (self.options.os_tenant_name):
|
||||
if (not self.options.os_tenant_name
|
||||
and not self.options.os_tenant_id):
|
||||
raise exc.CommandError(
|
||||
"You must provide a tenant_name via"
|
||||
" either --os-tenant-name or via env[OS_TENANT_NAME]")
|
||||
"You must provide a tenant_name or tenant_id via"
|
||||
" --os-tenant-name, env[OS_TENANT_NAME]"
|
||||
" --os-tenant-id, or via env[OS_TENANT_ID]")
|
||||
|
||||
if not self.options.os_auth_url:
|
||||
raise exc.CommandError(
|
||||
@ -502,6 +509,7 @@ class NeutronShell(app.App):
|
||||
url=self.options.os_url,
|
||||
auth_url=self.options.os_auth_url,
|
||||
tenant_name=self.options.os_tenant_name,
|
||||
tenant_id=self.options.os_tenant_id,
|
||||
username=self.options.os_username,
|
||||
password=self.options.os_password,
|
||||
region_name=self.options.os_region_name,
|
||||
|
@ -118,6 +118,7 @@ class Client(object):
|
||||
:param string password: Password for authentication. (optional)
|
||||
:param string token: Token for authentication. (optional)
|
||||
:param string tenant_name: Tenant name. (optional)
|
||||
:param string tenant_id: Tenant id. (optional)
|
||||
:param string auth_url: Keystone service endpoint for authorization.
|
||||
:param string endpoint_type: Network service endpoint type to pull from the
|
||||
keystone catalog (e.g. 'publicURL',
|
||||
|
@ -29,6 +29,7 @@ from neutronclient.common import exceptions
|
||||
|
||||
USERNAME = 'testuser'
|
||||
TENANT_NAME = 'testtenant'
|
||||
TENANT_ID = 'testtenantid'
|
||||
PASSWORD = 'password'
|
||||
AUTH_URL = 'authurl'
|
||||
ENDPOINT_URL = 'localurl'
|
||||
@ -67,6 +68,9 @@ ENDPOINTS_RESULT = {
|
||||
|
||||
class CLITestAuthKeystone(testtools.TestCase):
|
||||
|
||||
# Auth Body expected when using tenant name
|
||||
auth_type = 'tenantName'
|
||||
|
||||
def setUp(self):
|
||||
"""Prepare the test environment."""
|
||||
super(CLITestAuthKeystone, self).setUp()
|
||||
@ -87,7 +91,7 @@ class CLITestAuthKeystone(testtools.TestCase):
|
||||
|
||||
self.client.request(
|
||||
AUTH_URL + '/tokens', 'POST',
|
||||
body=mox.IsA(str), headers=mox.IsA(dict)
|
||||
body=mox.StrContains(self.auth_type), headers=mox.IsA(dict)
|
||||
).AndReturn((res200, json.dumps(KS_TOKEN_RESULT)))
|
||||
self.client.request(
|
||||
mox.StrContains(ENDPOINT_URL + '/resource'), 'GET',
|
||||
@ -318,3 +322,38 @@ class CLITestAuthKeystone(testtools.TestCase):
|
||||
self.assertRaises(exceptions.EndpointTypeNotFound,
|
||||
self.client._extract_service_catalog,
|
||||
resources)
|
||||
|
||||
|
||||
class CLITestAuthKeystoneWithId(CLITestAuthKeystone):
|
||||
|
||||
# Auth Body expected when using tenant Id
|
||||
auth_type = 'tenantId'
|
||||
|
||||
def setUp(self):
|
||||
"""Prepare the test environment."""
|
||||
super(CLITestAuthKeystone, self).setUp()
|
||||
self.mox = mox.Mox()
|
||||
self.client = client.HTTPClient(username=USERNAME,
|
||||
tenant_id=TENANT_ID,
|
||||
password=PASSWORD,
|
||||
auth_url=AUTH_URL,
|
||||
region_name=REGION)
|
||||
self.addCleanup(self.mox.VerifyAll)
|
||||
self.addCleanup(self.mox.UnsetStubs)
|
||||
|
||||
|
||||
class CLITestAuthKeystoneWithIdandName(CLITestAuthKeystone):
|
||||
|
||||
# Auth Body expected when using tenant Id
|
||||
auth_type = 'tenantId'
|
||||
|
||||
def setUp(self):
|
||||
"""Prepare the test environment."""
|
||||
super(CLITestAuthKeystone, self).setUp()
|
||||
self.mox = mox.Mox()
|
||||
self.client = client.HTTPClient(username=USERNAME,
|
||||
tenant_id=TENANT_ID,
|
||||
tenant_name=TENANT_NAME,
|
||||
password=PASSWORD,
|
||||
auth_url=AUTH_URL,
|
||||
region_name=REGION)
|
||||
|
Loading…
x
Reference in New Issue
Block a user