Change user passwd in CLI using interacive prompt
`fuel user change-password` now asks for password in interactive prompt in unix `passwd` style, which is secure comparing with passing new password as an argument to CLI. Also tests added. Change-Id: I88fd38e8bd0bb96dd9b596aa44fa3f7721ee6431 Closes-Bug: 1462343
This commit is contained in:
committed by
Maciej Kwiek
parent
142dae5693
commit
62c569281c
@@ -12,6 +12,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from getpass import getpass
|
||||
|
||||
from fuelclient.cli.actions.base import Action
|
||||
import fuelclient.cli.arguments as Args
|
||||
from fuelclient.cli.error import ArgumentException
|
||||
@@ -27,19 +29,29 @@ class UserAction(Action):
|
||||
super(UserAction, self).__init__()
|
||||
self.args = (
|
||||
Args.get_new_password_arg(),
|
||||
Args.get_change_password_arg("Change user password")
|
||||
Args.get_change_password_arg(
|
||||
"Change user password. WARNING: This method of changing the "
|
||||
"password is dangerous - it may be saved in bash history.")
|
||||
)
|
||||
|
||||
self.flag_func_map = (
|
||||
("change-password", self.change_password),
|
||||
)
|
||||
|
||||
def _get_password_from_prompt(self):
|
||||
password1 = getpass("Changing password for Fuel User.\nNew Password:")
|
||||
password2 = getpass("Retype new Password:")
|
||||
if password1 != password2:
|
||||
raise ArgumentException("Passwords are not the same.")
|
||||
return password1
|
||||
|
||||
def change_password(self, params):
|
||||
"""To change user password:
|
||||
fuel user change-password
|
||||
"""
|
||||
if params.newpass:
|
||||
APIClient.update_own_password(params.newpass)
|
||||
password = params.newpass
|
||||
else:
|
||||
raise ArgumentException(
|
||||
"Expect password [--newpass NEWPASS]")
|
||||
password = self._get_password_from_prompt()
|
||||
|
||||
APIClient.update_own_password(password)
|
||||
|
||||
@@ -289,15 +289,6 @@ class TestHandlers(base.BaseTestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestUserActions(base.BaseTestCase):
|
||||
|
||||
def test_change_password_params(self):
|
||||
cmd = "user change-password"
|
||||
msg = "Expect password [--newpass NEWPASS]"
|
||||
result = self.run_cli_command(cmd, check_errors=False)
|
||||
self.assertTrue(msg, result)
|
||||
|
||||
|
||||
class TestCharset(base.BaseTestCase):
|
||||
|
||||
def test_charset_problem(self):
|
||||
|
||||
66
fuelclient/tests/v1/unit/test_user_action.py
Normal file
66
fuelclient/tests/v1/unit/test_user_action.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# Copyright 2015 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from fuelclient.cli.actions.user import UserAction
|
||||
from fuelclient.cli.error import ArgumentException
|
||||
from fuelclient.tests import base
|
||||
|
||||
|
||||
class TestChangePassword(base.UnitTestCase):
|
||||
|
||||
def test_get_password_from_prompt(self):
|
||||
user_action = UserAction()
|
||||
passwd = 'secret!'
|
||||
with mock.patch('fuelclient.cli.actions.user.getpass',
|
||||
return_value=passwd):
|
||||
user_passwd = user_action._get_password_from_prompt()
|
||||
|
||||
self.assertEqual(passwd, user_passwd)
|
||||
|
||||
@mock.patch('fuelclient.cli.actions.user.getpass',
|
||||
side_effect=['pwd', 'otherpwd'])
|
||||
def test_get_password_from_prompt_different_passwords(self, mgetpass):
|
||||
user_action = UserAction()
|
||||
with self.assertRaisesRegexp(
|
||||
ArgumentException, 'Passwords are not the same'):
|
||||
user_action._get_password_from_prompt()
|
||||
|
||||
@mock.patch('fuelclient.cli.actions.user.APIClient')
|
||||
def test_change_password(self, mapiclient):
|
||||
user_action = UserAction()
|
||||
params = mock.Mock()
|
||||
params.newpass = None
|
||||
password = 'secret'
|
||||
|
||||
with mock.patch('fuelclient.cli.actions.user.getpass',
|
||||
return_value=password) as mgetpass:
|
||||
user_action.change_password(params)
|
||||
|
||||
calls = [
|
||||
mock.call("Changing password for Fuel User.\nNew Password:"),
|
||||
mock.call("Retype new Password:"),
|
||||
]
|
||||
|
||||
mgetpass.assert_has_calls(calls)
|
||||
mapiclient.update_own_password.assert_called_once_with(password)
|
||||
|
||||
@mock.patch('fuelclient.cli.actions.user.APIClient')
|
||||
def test_change_password_w_newpass(self, mapiclient):
|
||||
user_action = UserAction()
|
||||
params = mock.Mock()
|
||||
params.newpass = 'secret'
|
||||
user_action.change_password(params)
|
||||
mapiclient.update_own_password.assert_called_once_with(params.newpass)
|
||||
Reference in New Issue
Block a user