From 1de4c66009485b6e42791ac84684da7b5a1f0736 Mon Sep 17 00:00:00 2001 From: Alvaro Lopez Garcia Date: Mon, 20 Jun 2016 12:37:22 +0200 Subject: [PATCH] Improve masking of secrets in configuration show The command "configuration show" tries to redact some of the secrets that are shown on the screen. However, this failed redacting options that were marked as secrete by the auth plugins (if any) and it redacted other options that were not redacted at all. For example, when using the OpenID Connect plugins, it redacted the "access_token_endpoint" as the word "token" appears there, but it failed to redact "client_secret" even when this option is marked as secret in the corresponding plugin. Change-Id: Idfad4fbbe5ddcff5e729e1dcd756d0379ad31dee --- openstackclient/common/configuration.py | 10 ++++++---- .../tests/common/test_configuration.py | 17 ++++++++++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/openstackclient/common/configuration.py b/openstackclient/common/configuration.py index d6e2ab45bb..016e91917f 100644 --- a/openstackclient/common/configuration.py +++ b/openstackclient/common/configuration.py @@ -13,6 +13,7 @@ """Configuration action implementations""" +from keystoneauth1.loading import base from osc_lib.command import command import six @@ -44,12 +45,13 @@ class ShowConfiguration(command.ShowOne): def take_action(self, parsed_args): + auth_plg_name = self.app.client_manager.auth_plugin_name + secret_opts = [o.dest for o in base.get_plugin_options(auth_plg_name) + if o.secret] + info = self.app.client_manager.get_configuration() for key, value in six.iteritems(info.pop('auth', {})): - if parsed_args.mask: - if 'password' in key.lower(): - value = REDACTED - if 'token' in key.lower(): + if parsed_args.mask and key.lower() in secret_opts: value = REDACTED info['auth.' + key] = value return zip(*sorted(six.iteritems(info))) diff --git a/openstackclient/tests/common/test_configuration.py b/openstackclient/tests/common/test_configuration.py index e81550ed0a..915e5bd394 100644 --- a/openstackclient/tests/common/test_configuration.py +++ b/openstackclient/tests/common/test_configuration.py @@ -11,6 +11,8 @@ # under the License. # +import mock + from openstackclient.common import configuration from openstackclient.tests import fakes from openstackclient.tests import utils @@ -33,7 +35,12 @@ class TestConfiguration(utils.TestCommand): fakes.REGION_NAME, ) - def test_show(self): + opts = [mock.Mock(secret=True, dest="password"), + mock.Mock(secret=True, dest="token")] + + @mock.patch("keystoneauth1.loading.base.get_plugin_options", + return_value=opts) + def test_show(self, m_get_plugin_opts): arglist = [] verifylist = [('mask', True)] cmd = configuration.ShowConfiguration(self.app, None) @@ -44,7 +51,9 @@ class TestConfiguration(utils.TestCommand): self.assertEqual(self.columns, columns) self.assertEqual(self.datalist, data) - def test_show_unmask(self): + @mock.patch("keystoneauth1.loading.base.get_plugin_options", + return_value=opts) + def test_show_unmask(self, m_get_plugin_opts): arglist = ['--unmask'] verifylist = [('mask', False)] cmd = configuration.ShowConfiguration(self.app, None) @@ -62,7 +71,9 @@ class TestConfiguration(utils.TestCommand): ) self.assertEqual(datalist, data) - def test_show_mask(self): + @mock.patch("keystoneauth1.loading.base.get_plugin_options", + return_value=opts) + def test_show_mask(self, m_get_plugin_opts): arglist = ['--mask'] verifylist = [('mask', True)] cmd = configuration.ShowConfiguration(self.app, None)