Support unscoped token request
Make scope check optional for the "token issue" command as unscoped token is a valid Keystone V2/V3 API. Change-Id: Ie1cded4dbfdafd3a78c0ebdf89e3f66762509930 Closes-Bug: #1543214
This commit is contained in:
parent
fae6c4c7bd
commit
e7ac0db0a3
@ -135,8 +135,12 @@ def build_auth_params(auth_plugin_name, cmd_options):
|
||||
return (auth_plugin_class, auth_params)
|
||||
|
||||
|
||||
def check_valid_auth_options(options, auth_plugin_name):
|
||||
"""Perform basic option checking, provide helpful error messages"""
|
||||
def check_valid_auth_options(options, auth_plugin_name, required_scope=True):
|
||||
"""Perform basic option checking, provide helpful error messages.
|
||||
|
||||
:param required_scope: indicate whether a scoped token is required
|
||||
|
||||
"""
|
||||
|
||||
msg = ''
|
||||
if auth_plugin_name.endswith('password'):
|
||||
@ -146,7 +150,8 @@ def check_valid_auth_options(options, auth_plugin_name):
|
||||
if not options.auth.get('auth_url', None):
|
||||
msg += _('Set an authentication URL, with --os-auth-url,'
|
||||
' OS_AUTH_URL or auth.auth_url\n')
|
||||
if (not options.auth.get('project_id', None) and not
|
||||
if (required_scope and not
|
||||
options.auth.get('project_id', None) and not
|
||||
options.auth.get('domain_id', None) and not
|
||||
options.auth.get('domain_name', None) and not
|
||||
options.auth.get('project_name', None) and not
|
||||
|
@ -113,19 +113,35 @@ class ClientManager(object):
|
||||
root_logger = logging.getLogger('')
|
||||
LOG.setLevel(root_logger.getEffectiveLevel())
|
||||
|
||||
def setup_auth(self):
|
||||
# NOTE(gyee): use this flag to indicate whether auth setup has already
|
||||
# been completed. If so, do not perform auth setup again. The reason
|
||||
# we need this flag is that we want to be able to perform auth setup
|
||||
# outside of auth_ref as auth_ref itself is a property. We can not
|
||||
# retrofit auth_ref to optionally skip scope check. Some operations
|
||||
# do not require a scoped token. In those cases, we call setup_auth
|
||||
# prior to dereferrencing auth_ref.
|
||||
self._auth_setup_completed = False
|
||||
|
||||
def setup_auth(self, required_scope=True):
|
||||
"""Set up authentication
|
||||
|
||||
:param required_scope: indicate whether a scoped token is required
|
||||
|
||||
This is deferred until authentication is actually attempted because
|
||||
it gets in the way of things that do not require auth.
|
||||
"""
|
||||
|
||||
if self._auth_setup_completed:
|
||||
return
|
||||
|
||||
# If no auth type is named by the user, select one based on
|
||||
# the supplied options
|
||||
self.auth_plugin_name = auth.select_auth_plugin(self._cli_options)
|
||||
|
||||
# Basic option checking to avoid unhelpful error messages
|
||||
auth.check_valid_auth_options(self._cli_options, self.auth_plugin_name)
|
||||
auth.check_valid_auth_options(self._cli_options,
|
||||
self.auth_plugin_name,
|
||||
required_scope=required_scope)
|
||||
|
||||
# Horrible hack alert...must handle prompt for null password if
|
||||
# password auth is requested.
|
||||
@ -180,6 +196,8 @@ class ClientManager(object):
|
||||
user_agent=USER_AGENT,
|
||||
)
|
||||
|
||||
self._auth_setup_completed = True
|
||||
|
||||
return
|
||||
|
||||
@property
|
||||
|
@ -353,6 +353,9 @@ class OpenStackShell(app.App):
|
||||
cmd.__class__.__name__,
|
||||
)
|
||||
if cmd.auth_required:
|
||||
if hasattr(cmd, 'required_scope'):
|
||||
# let the command decide whether we need a scoped token
|
||||
self.client_manager.setup_auth(cmd.required_scope)
|
||||
# Trigger the Identity client to initialize
|
||||
self.client_manager.auth_ref
|
||||
return
|
||||
|
@ -325,3 +325,28 @@ class TestClientManager(utils.TestCase):
|
||||
exc.CommandError,
|
||||
client_manager.setup_auth,
|
||||
)
|
||||
|
||||
@mock.patch('openstackclient.api.auth.check_valid_auth_options')
|
||||
def test_client_manager_auth_setup_once(self, check_auth_options_func):
|
||||
client_manager = clientmanager.ClientManager(
|
||||
cli_options=FakeOptions(
|
||||
auth=dict(
|
||||
auth_url=fakes.AUTH_URL,
|
||||
username=fakes.USERNAME,
|
||||
password=fakes.PASSWORD,
|
||||
project_name=fakes.PROJECT_NAME,
|
||||
),
|
||||
),
|
||||
api_version=API_VERSION,
|
||||
verify=False,
|
||||
)
|
||||
self.assertFalse(client_manager._auth_setup_completed)
|
||||
client_manager.setup_auth()
|
||||
self.assertTrue(check_auth_options_func.called)
|
||||
self.assertTrue(client_manager._auth_setup_completed)
|
||||
|
||||
# now make sure we don't do auth setup the second time around
|
||||
# by checking whether check_valid_auth_options() gets called again
|
||||
check_auth_options_func.reset_mock()
|
||||
client_manager.auth_ref
|
||||
check_auth_options_func.assert_not_called()
|
||||
|
Loading…
x
Reference in New Issue
Block a user