[CLI] Fix token auth type
There are 2 known issues which breaks token auth method in CLI: * The wrong check of flag (the check should be for --os-token since arguments are not parsed at that moment) is performed in CLI inner method `_append_global_identity_args`. It led to usage of "password" auth type by default[1] even if `--os-token` cli argument is specified. If `--os-auth-type` is specified to token, keystoneauth1 library makes the right decision[2]. * Based on an auth type, keystoneauth library registers different CLI arguments[3]. It means that `--os-username` argument is available only in password auth type, `--os-token` is available only in token auth type, etc. It also affects the way in which the python code should access such arguments. The arguments which are unrelated to the selected auth type are omitted from the parsed arguments object. That sounds reasonable, but unfortunately the code assumes the unrelated arguments are always present which leads to an AttributeError. Combination of these 2 issues made token auth type broken in CLI layer. [1]ee2221f052/novaclient/shell.py (L255-L257)
[2]14dd37b34c/keystoneauth1/loading/cli.py (L51-L52)
[3]14dd37b34c/keystoneauth1/loading/cli.py (L65-L73)
Closes-Bug: #1659015 Change-Id: Ibc861d396b71fe105288d8336623cc22cf92523e
This commit is contained in:
parent
8cabab774c
commit
6049be67c0
@ -249,11 +249,11 @@ class OpenStackComputeShell(object):
|
||||
def _append_global_identity_args(self, parser, argv):
|
||||
# Register the CLI arguments that have moved to the session object.
|
||||
loading.register_session_argparse_arguments(parser)
|
||||
# Peek into argv to see if os-auth-token or os-token were given,
|
||||
# Peek into argv to see if os-token was given,
|
||||
# in which case, the token auth plugin is what the user wants
|
||||
# else, we'll default to password
|
||||
default_auth_plugin = 'password'
|
||||
if 'os-token' in argv:
|
||||
if "--os-token" in argv:
|
||||
default_auth_plugin = 'token'
|
||||
loading.register_auth_argparse_arguments(
|
||||
parser, argv, default=default_auth_plugin)
|
||||
@ -513,8 +513,10 @@ class OpenStackComputeShell(object):
|
||||
api_version = api_versions.get_api_version(
|
||||
args.os_compute_api_version)
|
||||
|
||||
os_username = args.os_username
|
||||
os_user_id = args.os_user_id
|
||||
auth_token = getattr(args, "os_token", None)
|
||||
|
||||
os_username = getattr(args, "os_username", None)
|
||||
os_user_id = getattr(args, "os_user_id", None)
|
||||
os_password = None # Fetched and set later as needed
|
||||
os_project_name = getattr(
|
||||
args, 'os_project_name', getattr(args, 'os_tenant_name', None))
|
||||
@ -529,13 +531,16 @@ class OpenStackComputeShell(object):
|
||||
if (not args.os_project_domain_id and
|
||||
not args.os_project_domain_name):
|
||||
setattr(args, "os_project_domain_id", "default")
|
||||
if not args.os_user_domain_id and not args.os_user_domain_name:
|
||||
|
||||
# os_user_domain_id is redundant in case of Token auth type
|
||||
if not auth_token and (not args.os_user_domain_id and
|
||||
not args.os_user_domain_name):
|
||||
setattr(args, "os_user_domain_id", "default")
|
||||
|
||||
os_project_domain_id = args.os_project_domain_id
|
||||
os_project_domain_name = args.os_project_domain_name
|
||||
os_user_domain_id = args.os_project_domain_id
|
||||
os_user_domain_name = args.os_project_domain_name
|
||||
os_user_domain_id = getattr(args, "os_user_domain_id", None)
|
||||
os_user_domain_name = getattr(args, "os_user_domain_name", None)
|
||||
|
||||
endpoint_type = args.endpoint_type
|
||||
insecure = args.insecure
|
||||
@ -550,13 +555,6 @@ class OpenStackComputeShell(object):
|
||||
keystone_session = None
|
||||
keystone_auth = None
|
||||
|
||||
# We may have either, both or none of these.
|
||||
# If we have both, we don't need USERNAME, PASSWORD etc.
|
||||
# Finally, authenticate unless we have both.
|
||||
# Note if we don't auth we probably don't have a tenant ID so we can't
|
||||
# cache the token.
|
||||
auth_token = getattr(args, 'os_token', None)
|
||||
|
||||
if not endpoint_type:
|
||||
endpoint_type = DEFAULT_NOVA_ENDPOINT_TYPE
|
||||
|
||||
@ -579,11 +577,11 @@ class OpenStackComputeShell(object):
|
||||
# for os_username or os_password but for compatibility it is not.
|
||||
if must_auth and not skip_auth:
|
||||
|
||||
if not os_username and not os_user_id:
|
||||
if not any([auth_token, os_username, os_user_id]):
|
||||
raise exc.CommandError(
|
||||
_("You must provide a username "
|
||||
"or user ID via --os-username, --os-user-id, "
|
||||
"env[OS_USERNAME] or env[OS_USER_ID]"))
|
||||
_("You must provide a user name/id (via --os-username, "
|
||||
"--os-user-id, env[OS_USERNAME] or env[OS_USER_ID]) or "
|
||||
"an auth token (via --os-token)."))
|
||||
|
||||
if not any([os_project_name, os_project_id]):
|
||||
raise exc.CommandError(_("You must provide a project name or"
|
||||
|
@ -51,17 +51,15 @@ class TestAuthentication(base.ClientTestBase):
|
||||
project_name=self.project_name, **kw)
|
||||
nova.servers.list()
|
||||
|
||||
# NOTE(andreykurilin): token auth is completely broken in CLI
|
||||
# flags = ('--os-username %s --os-tenant-name %s --os-auth-token %s '
|
||||
# '--os-auth-url %s --os-endpoint-type publicURL' % (
|
||||
# self.cli_clients.username,
|
||||
# self.cli_clients.tenant_name,
|
||||
# token, auth_url))
|
||||
# if self.cli_clients.insecure:
|
||||
# flags += ' --insecure '
|
||||
#
|
||||
# return tempest.lib.cli.base.execute(
|
||||
# "nova", action, flags, cli_dir=self.cli_clients.cli_dir)
|
||||
flags = ('--os-tenant-name %(project_name)s --os-token %(token)s '
|
||||
'--os-auth-url %(auth_url)s --os-endpoint-type publicURL'
|
||||
% {"project_name": self.project_name,
|
||||
"token": token, "auth_url": auth_url})
|
||||
if self.cli_clients.insecure:
|
||||
flags += ' --insecure '
|
||||
|
||||
tempest.lib.cli.base.execute(
|
||||
"nova", "list", flags, cli_dir=self.cli_clients.cli_dir)
|
||||
|
||||
def test_auth_via_keystone_v2(self):
|
||||
session = self.keystone.session
|
||||
|
@ -467,9 +467,9 @@ class ShellTest(utils.TestCase):
|
||||
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
|
||||
|
||||
def test_no_username(self):
|
||||
required = ('You must provide a username or user ID'
|
||||
' via --os-username, --os-user-id,'
|
||||
' env[OS_USERNAME] or env[OS_USER_ID]')
|
||||
required = ('You must provide a user name/id (via --os-username, '
|
||||
'--os-user-id, env[OS_USERNAME] or env[OS_USER_ID]) or '
|
||||
'an auth token (via --os-token).')
|
||||
self.make_env(exclude='OS_USERNAME')
|
||||
try:
|
||||
self.shell('list')
|
||||
@ -479,9 +479,9 @@ class ShellTest(utils.TestCase):
|
||||
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]')
|
||||
required = ('You must provide a user name/id (via --os-username, '
|
||||
'--os-user-id, env[OS_USERNAME] or env[OS_USER_ID]) or '
|
||||
'an auth token (via --os-token).')
|
||||
self.make_env(exclude='OS_USER_ID', fake_env=FAKE_ENV2)
|
||||
try:
|
||||
self.shell('list')
|
||||
|
Loading…
Reference in New Issue
Block a user