From 5cbecc130ef2aacd5d9bd265b814e6f8140374f9 Mon Sep 17 00:00:00 2001 From: Guang Yee Date: Thu, 7 Jan 2016 18:56:44 -0800 Subject: [PATCH] Support non-interactive user password update Currently user password update require interactive prompting of user's original password. This is problematic because we can't support non-interactive applications and therefore hinders automation. This patch make it possible by optionally accepting an '--original-password' argument. If specified, we would use it instead of prompting. DocImpact Change-Id: I2d994e8c2be949f7ae616ac1d1594fb94e1a27cd Closes-Bug: 1531360 --- openstackclient/identity/v3/user.py | 31 +++++++++++++++++-- .../tests/identity/v3/test_user.py | 19 ++++++++++++ .../notes/bug-1531360-0f5c62d18088e5b5.yaml | 5 +++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/bug-1531360-0f5c62d18088e5b5.yaml diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py index eaef8f0523..43a116cb36 100644 --- a/openstackclient/identity/v3/user.py +++ b/openstackclient/identity/v3/user.py @@ -392,14 +392,41 @@ class SetPasswordUser(command.Command): metavar='', help='New user password' ) + parser.add_argument( + '--original-password', + metavar='', + help='Original user password' + ) return parser @utils.log_method(log) def take_action(self, parsed_args): identity_client = self.app.client_manager.identity - current_password = utils.get_password( - self.app.stdin, prompt="Current Password:", confirm=False) + # FIXME(gyee): there are two scenarios: + # + # 1. user update password for himself + # 2. admin update password on behalf of the user. This is an unlikely + # scenario because that will require admin knowing the user's + # original password which is forbidden under most security + # policies. + # + # Of the two scenarios above, user either authenticate using its + # original password or an authentication token. For scenario #1, + # if user is authenticating with its original password (i.e. passing + # --os-password argument), we can just make use of it instead of using + # --original-password or prompting. For scenario #2, admin will need + # to specify --original-password option or this won't work because + # --os-password is the admin's own password. In the future if we stop + # supporting scenario #2 then we can just do this. + # + # current_password = (parsed_args.original_password or + # self.app.cloud.password) + # + current_password = parsed_args.original_password + if current_password is None: + current_password = utils.get_password( + self.app.stdin, prompt="Current Password:", confirm=False) password = parsed_args.password if password is None: diff --git a/openstackclient/tests/identity/v3/test_user.py b/openstackclient/tests/identity/v3/test_user.py index 76d5f83487..41fab60ee7 100644 --- a/openstackclient/tests/identity/v3/test_user.py +++ b/openstackclient/tests/identity/v3/test_user.py @@ -1095,6 +1095,25 @@ class TestUserSetPassword(TestUser): current_pass, new_pass ) + def test_user_password_change_no_prompt(self): + current_pass = 'old_pass' + new_pass = 'new_pass' + arglist = [ + '--password', new_pass, + '--original-password', current_pass, + ] + verifylist = [ + ('password', new_pass), + ('original_password', current_pass), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + + self.users_mock.update_password.assert_called_with( + current_pass, new_pass + ) + class TestUserShow(TestUser): diff --git a/releasenotes/notes/bug-1531360-0f5c62d18088e5b5.yaml b/releasenotes/notes/bug-1531360-0f5c62d18088e5b5.yaml new file mode 100644 index 0000000000..992f2656e2 --- /dev/null +++ b/releasenotes/notes/bug-1531360-0f5c62d18088e5b5.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Support non-interactive user password update + [Bug `1531360 `_]