Skip to content

Commit bec206f

Browse files
author
Dean Troyer
committed
Fix auth prompt brokenness
We start by fixing this in the already-present OSC_Config class so OSC can move forward. This change needs to get ported down into os-client-config in the near future, maybe even soon enough to make the client library freeze this week. * Add the pw-func argument to the OSC_Config (or OpenStackConfig) __init__() * When looping through the auth options from the KSA plugin look for any that have a prompt defined and do not have a value already, so ask for one. Closes-bug: #1617384 Change-Id: Ic86d56b8a6844516292fb74513712b486fec4442
1 parent a08b625 commit bec206f

4 files changed

Lines changed: 102 additions & 3 deletions

File tree

openstackclient/common/client_config.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,40 @@
2525
# before auth plugins are loaded
2626
class OSC_Config(OpenStackConfig):
2727

28+
# TODO(dtroyer): Once os-client-config with pw_func argument is in
29+
# global-requirements we can remove __init()__
30+
def __init__(
31+
self,
32+
config_files=None,
33+
vendor_files=None,
34+
override_defaults=None,
35+
force_ipv4=None,
36+
envvar_prefix=None,
37+
secure_files=None,
38+
pw_func=None,
39+
):
40+
ret = super(OSC_Config, self).__init__(
41+
config_files=config_files,
42+
vendor_files=vendor_files,
43+
override_defaults=override_defaults,
44+
force_ipv4=force_ipv4,
45+
envvar_prefix=envvar_prefix,
46+
secure_files=secure_files,
47+
)
48+
49+
# NOTE(dtroyer): This will be pushed down into os-client-config
50+
# The default is there is no callback, the calling
51+
# application must specify what to use, typically
52+
# it will be osc_lib.shell.prompt_for_password()
53+
if '_pw_callback' not in vars(self):
54+
# Set the default if it doesn't already exist
55+
self._pw_callback = None
56+
if pw_func is not None:
57+
# Set the passed in value
58+
self._pw_callback = pw_func
59+
60+
return ret
61+
2862
def _auth_select_default_plugin(self, config):
2963
"""Select a default plugin based on supplied arguments
3064
@@ -183,4 +217,13 @@ def _validate_auth(self, config, loader, fixed_argparse=None):
183217
else:
184218
config['auth'][p_opt.dest] = winning_value
185219

220+
# See if this needs a prompting
221+
if (
222+
'prompt' in vars(p_opt) and
223+
p_opt.prompt is not None and
224+
p_opt.dest not in config['auth'] and
225+
self._pw_callback is not None
226+
):
227+
config['auth'][p_opt.dest] = self._pw_callback(p_opt.prompt)
228+
186229
return config

openstackclient/common/clientmanager.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,10 @@ def __init__(
4444
self,
4545
cli_options=None,
4646
api_version=None,
47-
pw_func=None,
4847
):
4948
super(ClientManager, self).__init__(
5049
cli_options=cli_options,
5150
api_version=api_version,
52-
pw_func=pw_func,
5351
)
5452

5553
# TODO(dtroyer): For compatibility; mark this for removal when plugin

openstackclient/shell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ def initialize_app(self, argv):
145145
'interface': None,
146146
'auth_type': self._auth_type,
147147
},
148+
pw_func=shell.prompt_for_password,
148149
)
149150
except (IOError, OSError) as e:
150151
self.log.critical("Could not read clouds.yaml configuration file")
@@ -162,7 +163,6 @@ def initialize_app(self, argv):
162163
self.client_manager = clientmanager.ClientManager(
163164
cli_options=self.cloud,
164165
api_version=self.api_version,
165-
pw_func=shell.prompt_for_password,
166166
)
167167

168168

openstackclient/tests/test_shell_integ.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,64 @@ def test_shell_args_cacert_insecure(self):
354354
self.assertFalse(self.requests_mock.request_history[0].verify)
355355

356356

357+
class TestShellCliV3Prompt(TestShellInteg):
358+
359+
def setUp(self):
360+
super(TestShellCliV3Prompt, self).setUp()
361+
env = {
362+
"OS_AUTH_URL": V3_AUTH_URL,
363+
"OS_PROJECT_DOMAIN_ID": test_shell.DEFAULT_PROJECT_DOMAIN_ID,
364+
"OS_USER_DOMAIN_ID": test_shell.DEFAULT_USER_DOMAIN_ID,
365+
"OS_USERNAME": test_shell.DEFAULT_USERNAME,
366+
"OS_IDENTITY_API_VERSION": "3",
367+
}
368+
self.useFixture(osc_lib_utils.EnvFixture(copy.deepcopy(env)))
369+
370+
self.token = ksa_fixture.V3Token(
371+
project_domain_id=test_shell.DEFAULT_PROJECT_DOMAIN_ID,
372+
user_domain_id=test_shell.DEFAULT_USER_DOMAIN_ID,
373+
user_name=test_shell.DEFAULT_USERNAME,
374+
)
375+
376+
# Set up the v3 auth routes
377+
self.requests_mock.register_uri(
378+
'GET',
379+
V3_AUTH_URL,
380+
json=V3_VERSION_RESP,
381+
status_code=200,
382+
)
383+
self.requests_mock.register_uri(
384+
'POST',
385+
V3_AUTH_URL + 'auth/tokens',
386+
json=self.token,
387+
status_code=200,
388+
)
389+
390+
@mock.patch("osc_lib.shell.prompt_for_password")
391+
def test_shell_callback(self, mock_prompt):
392+
mock_prompt.return_value = "qaz"
393+
_shell = shell.OpenStackShell()
394+
_shell.run("configuration show".split())
395+
396+
# Check general calls
397+
self.assertEqual(len(self.requests_mock.request_history), 2)
398+
399+
# Check password callback set correctly
400+
self.assertEqual(
401+
mock_prompt,
402+
_shell.cloud._openstack_config._pw_callback
403+
)
404+
405+
# Check auth request
406+
auth_req = self.requests_mock.request_history[1].json()
407+
408+
# Check returned password from prompt function
409+
self.assertEqual(
410+
"qaz",
411+
auth_req['auth']['identity']['password']['user']['password'],
412+
)
413+
414+
357415
class TestShellCliPrecedence(TestShellInteg):
358416
"""Validate option precedence rules without clouds.yaml
359417

0 commit comments

Comments
 (0)