Allow user ID for authentication
In Keystone V3 user names are no longer necessarily unique accross domains. A user can still authenticate a user in the non default domain via the V2 API providng they use IDs instead of names. Tenant_ID is already supported, this change adds support for user ID Change-Id: I36ba75f3e67c8cdb959e31923d5e557414ab6f9b
This commit is contained in:
parent
d0b6550d66
commit
dd8bde71ff
@ -64,8 +64,9 @@ class HTTPClient(object):
|
||||
os_cache=False, no_cache=True,
|
||||
http_log_debug=False, auth_system='keystone',
|
||||
auth_plugin=None, auth_token=None,
|
||||
cacert=None, tenant_id=None):
|
||||
cacert=None, tenant_id=None, user_id=None):
|
||||
self.user = user
|
||||
self.user_id = user_id
|
||||
self.password = password
|
||||
self.projectid = projectid
|
||||
self.tenant_id = tenant_id
|
||||
@ -456,6 +457,10 @@ class HTTPClient(object):
|
||||
if self.auth_token:
|
||||
body = {"auth": {
|
||||
"token": {"id": self.auth_token}}}
|
||||
elif self.user_id:
|
||||
body = {"auth": {
|
||||
"passwordCredentials": {"userId": self.user_id,
|
||||
"password": self._get_password()}}}
|
||||
else:
|
||||
body = {"auth": {
|
||||
"passwordCredentials": {"username": self.user,
|
||||
|
@ -285,6 +285,11 @@ class OpenStackComputeShell(object):
|
||||
parser.add_argument('--os_username',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-user-id',
|
||||
metavar='<auth-user-id>',
|
||||
default=utils.env('OS_USER_ID'),
|
||||
help=_('Defaults to env[OS_USER_ID].'))
|
||||
|
||||
parser.add_argument('--os-password',
|
||||
metavar='<auth-password>',
|
||||
default=utils.env('OS_PASSWORD', 'NOVA_PASSWORD'),
|
||||
@ -550,6 +555,7 @@ class OpenStackComputeShell(object):
|
||||
return 0
|
||||
|
||||
os_username = args.os_username
|
||||
os_user_id = args.os_user_id
|
||||
os_password = None # Fetched and set later as needed
|
||||
os_tenant_name = args.os_tenant_name
|
||||
os_tenant_id = args.os_tenant_id
|
||||
@ -606,9 +612,10 @@ class OpenStackComputeShell(object):
|
||||
auth_plugin.parse_opts(args)
|
||||
|
||||
if not auth_plugin or not auth_plugin.opts:
|
||||
if not os_username:
|
||||
if not os_username and not os_user_id:
|
||||
raise exc.CommandError(_("You must provide a username "
|
||||
"via either --os-username or env[OS_USERNAME]"))
|
||||
"or user id via --os-username, --os-user-id, "
|
||||
"env[OS_USERNAME] or env[OS_USER_ID]"))
|
||||
|
||||
if not os_tenant_name and not os_tenant_id:
|
||||
raise exc.CommandError(_("You must provide a tenant name "
|
||||
@ -639,8 +646,9 @@ class OpenStackComputeShell(object):
|
||||
raise exc.CommandError(_("You must provide an auth url "
|
||||
"via either --os-auth-url or env[OS_AUTH_URL]"))
|
||||
|
||||
self.cs = client.Client(options.os_compute_api_version, os_username,
|
||||
os_password, os_tenant_name, tenant_id=os_tenant_id,
|
||||
self.cs = client.Client(options.os_compute_api_version,
|
||||
os_username, os_password, os_tenant_name,
|
||||
tenant_id=os_tenant_id, user_id=os_user_id,
|
||||
auth_url=os_auth_url, insecure=insecure,
|
||||
region_name=os_region_name, endpoint_type=endpoint_type,
|
||||
extensions=self.extensions, service_type=service_type,
|
||||
|
@ -32,7 +32,7 @@ FAKE_ENV = {'OS_USERNAME': 'username',
|
||||
'OS_TENANT_NAME': 'tenant_name',
|
||||
'OS_AUTH_URL': 'http://no.where'}
|
||||
|
||||
FAKE_ENV2 = {'OS_USERNAME': 'username',
|
||||
FAKE_ENV2 = {'OS_USER_ID': 'user_id',
|
||||
'OS_PASSWORD': 'password',
|
||||
'OS_TENANT_ID': 'tenant_id',
|
||||
'OS_AUTH_URL': 'http://no.where'}
|
||||
@ -133,25 +133,38 @@ class ShellTest(utils.TestCase):
|
||||
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
|
||||
|
||||
def test_no_username(self):
|
||||
required = ('You must provide a username'
|
||||
' via either --os-username or env[OS_USERNAME]',)
|
||||
required = ('You must provide a username or user id'
|
||||
' via --os-username, --os-user-id,'
|
||||
' env[OS_USERNAME] or env[OS_USER_ID]')
|
||||
self.make_env(exclude='OS_USERNAME')
|
||||
try:
|
||||
self.shell('list')
|
||||
except exceptions.CommandError as message:
|
||||
self.assertEqual(required, message.args)
|
||||
self.assertEqual(required, message.args[0])
|
||||
else:
|
||||
self.fail('CommandError not raised')
|
||||
|
||||
def test_no_user_id(self):
|
||||
required = ('You must provide a username or user id'
|
||||
' via --os-username, --os-user-id,'
|
||||
' env[OS_USERNAME] or env[OS_USER_ID]')
|
||||
self.make_env(exclude='OS_USER_ID', fake_env=FAKE_ENV2)
|
||||
try:
|
||||
self.shell('list')
|
||||
except exceptions.CommandError as message:
|
||||
self.assertEqual(required, message.args[0])
|
||||
else:
|
||||
self.fail('CommandError not raised')
|
||||
|
||||
def test_no_tenant_name(self):
|
||||
required = ('You must provide a tenant name or tenant id'
|
||||
' via --os-tenant-name, --os-tenant-id,'
|
||||
' env[OS_TENANT_NAME] or env[OS_TENANT_ID]',)
|
||||
' env[OS_TENANT_NAME] or env[OS_TENANT_ID]')
|
||||
self.make_env(exclude='OS_TENANT_NAME')
|
||||
try:
|
||||
self.shell('list')
|
||||
except exceptions.CommandError as message:
|
||||
self.assertEqual(required, message.args)
|
||||
self.assertEqual(required, message.args[0])
|
||||
else:
|
||||
self.fail('CommandError not raised')
|
||||
|
||||
|
@ -73,12 +73,13 @@ class Client(object):
|
||||
bypass_url=None, os_cache=False, no_cache=True,
|
||||
http_log_debug=False, auth_system='keystone',
|
||||
auth_plugin=None, auth_token=None,
|
||||
cacert=None, tenant_id=None):
|
||||
cacert=None, tenant_id=None, user_id=None):
|
||||
# FIXME(comstud): Rename the api_key argument above when we
|
||||
# know it's not being used as keyword argument
|
||||
password = api_key
|
||||
self.projectid = project_id
|
||||
self.tenant_id = tenant_id
|
||||
self.user_id = user_id
|
||||
self.flavors = flavors.FlavorManager(self)
|
||||
self.flavor_access = flavor_access.FlavorAccessManager(self)
|
||||
self.images = images.ImageManager(self)
|
||||
@ -126,6 +127,7 @@ class Client(object):
|
||||
|
||||
self.client = client.HTTPClient(username,
|
||||
password,
|
||||
user_id=user_id,
|
||||
projectid=project_id,
|
||||
tenant_id=tenant_id,
|
||||
auth_url=auth_url,
|
||||
|
@ -59,9 +59,10 @@ class Client(object):
|
||||
bypass_url=None, os_cache=False, no_cache=True,
|
||||
http_log_debug=False, auth_system='keystone',
|
||||
auth_plugin=None, auth_token=None,
|
||||
cacert=None, tenant_id=None):
|
||||
cacert=None, tenant_id=None, user_id=None):
|
||||
self.projectid = project_id
|
||||
self.tenant_id = tenant_id
|
||||
self.user_id = user_id
|
||||
self.os_cache = os_cache or not no_cache
|
||||
#TODO(bnemec): Add back in v3 extensions
|
||||
self.agents = agents.AgentsManager(self)
|
||||
@ -91,6 +92,7 @@ class Client(object):
|
||||
|
||||
self.client = client.HTTPClient(username,
|
||||
password,
|
||||
user_id=user_id,
|
||||
projectid=project_id,
|
||||
tenant_id=tenant_id,
|
||||
auth_url=auth_url,
|
||||
|
Loading…
Reference in New Issue
Block a user