Merge "Prompt for password on CLI if not provided"
This commit is contained in:
@@ -82,3 +82,11 @@ class Password(base.BaseGenericPlugin):
|
|||||||
options = super(Password, cls).get_options()
|
options = super(Password, cls).get_options()
|
||||||
options.extend(get_options())
|
options.extend(get_options())
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_from_argparse_arguments(cls, namespace, **kwargs):
|
||||||
|
if not (kwargs.get('password') or namespace.os_password):
|
||||||
|
kwargs['password'] = utils.prompt_user_password()
|
||||||
|
|
||||||
|
return super(Password, cls).load_from_argparse_arguments(namespace,
|
||||||
|
**kwargs)
|
||||||
|
@@ -144,6 +144,14 @@ class Password(Auth):
|
|||||||
|
|
||||||
return {'passwordCredentials': auth}
|
return {'passwordCredentials': auth}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_from_argparse_arguments(cls, namespace, **kwargs):
|
||||||
|
if not (kwargs.get('password') or namespace.os_password):
|
||||||
|
kwargs['password'] = utils.prompt_user_password()
|
||||||
|
|
||||||
|
return super(Password, cls).load_from_argparse_arguments(namespace,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_options(cls):
|
def get_options(cls):
|
||||||
options = super(Password, cls).get_options()
|
options = super(Password, cls).get_options()
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from keystoneclient.auth.identity.v3 import base
|
from keystoneclient.auth.identity.v3 import base
|
||||||
|
from keystoneclient import utils
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['PasswordMethod', 'Password']
|
__all__ = ['PasswordMethod', 'Password']
|
||||||
@@ -86,3 +87,11 @@ class Password(base.AuthConstructor):
|
|||||||
])
|
])
|
||||||
|
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_from_argparse_arguments(cls, namespace, **kwargs):
|
||||||
|
if not (kwargs.get('password') or namespace.os_password):
|
||||||
|
kwargs['password'] = utils.prompt_user_password()
|
||||||
|
|
||||||
|
return super(Password, cls).load_from_argparse_arguments(namespace,
|
||||||
|
**kwargs)
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import getpass
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@@ -296,13 +295,8 @@ class OpenStackIdentityShell(object):
|
|||||||
'--os-username or env[OS_USERNAME]')
|
'--os-username or env[OS_USERNAME]')
|
||||||
|
|
||||||
if not args.os_password:
|
if not args.os_password:
|
||||||
# No password, If we've got a tty, try prompting for it
|
args.os_password = utils.prompt_user_password()
|
||||||
if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty():
|
|
||||||
# Check for Ctl-D
|
|
||||||
try:
|
|
||||||
args.os_password = getpass.getpass('OS Password: ')
|
|
||||||
except EOFError:
|
|
||||||
pass
|
|
||||||
# No password because we didn't have a tty or the
|
# No password because we didn't have a tty or the
|
||||||
# user Ctl-D when prompted?
|
# user Ctl-D when prompted?
|
||||||
if not args.os_password:
|
if not args.os_password:
|
||||||
|
@@ -10,9 +10,12 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
from keystoneclient.auth.identity import v2
|
from keystoneclient.auth.identity import v2
|
||||||
from keystoneclient import exceptions
|
from keystoneclient import exceptions
|
||||||
from keystoneclient import session
|
from keystoneclient import session
|
||||||
@@ -294,3 +297,28 @@ class V2IdentityPlugin(utils.TestCase):
|
|||||||
def test_password_with_no_user_id_or_name(self):
|
def test_password_with_no_user_id_or_name(self):
|
||||||
self.assertRaises(TypeError,
|
self.assertRaises(TypeError,
|
||||||
v2.Password, self.TEST_URL, password=self.TEST_PASS)
|
v2.Password, self.TEST_URL, password=self.TEST_PASS)
|
||||||
|
|
||||||
|
@mock.patch('sys.stdin', autospec=True)
|
||||||
|
def test_prompt_password(self, mock_stdin):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
v2.Password.register_argparse_arguments(parser)
|
||||||
|
|
||||||
|
username = uuid.uuid4().hex
|
||||||
|
auth_url = uuid.uuid4().hex
|
||||||
|
tenant_id = uuid.uuid4().hex
|
||||||
|
password = uuid.uuid4().hex
|
||||||
|
|
||||||
|
opts = parser.parse_args(['--os-username', username,
|
||||||
|
'--os-auth-url', auth_url,
|
||||||
|
'--os-tenant-id', tenant_id])
|
||||||
|
|
||||||
|
with mock.patch('getpass.getpass') as mock_getpass:
|
||||||
|
mock_getpass.return_value = password
|
||||||
|
mock_stdin.isatty = lambda: True
|
||||||
|
|
||||||
|
plugin = v2.Password.load_from_argparse_arguments(opts)
|
||||||
|
|
||||||
|
self.assertEqual(auth_url, plugin.auth_url)
|
||||||
|
self.assertEqual(username, plugin.username)
|
||||||
|
self.assertEqual(tenant_id, plugin.tenant_id)
|
||||||
|
self.assertEqual(password, plugin.password)
|
||||||
|
@@ -10,9 +10,12 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
from keystoneclient import access
|
from keystoneclient import access
|
||||||
from keystoneclient.auth.identity import v3
|
from keystoneclient.auth.identity import v3
|
||||||
from keystoneclient.auth.identity.v3 import base as v3_base
|
from keystoneclient.auth.identity.v3 import base as v3_base
|
||||||
@@ -531,3 +534,32 @@ class V3IdentityPlugin(utils.TestCase):
|
|||||||
s = session.Session()
|
s = session.Session()
|
||||||
|
|
||||||
self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s)
|
self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s)
|
||||||
|
|
||||||
|
@mock.patch('sys.stdin', autospec=True)
|
||||||
|
def test_prompt_password(self, mock_stdin):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
v3.Password.register_argparse_arguments(parser)
|
||||||
|
|
||||||
|
username = uuid.uuid4().hex
|
||||||
|
user_domain_id = uuid.uuid4().hex
|
||||||
|
auth_url = uuid.uuid4().hex
|
||||||
|
project_id = uuid.uuid4().hex
|
||||||
|
password = uuid.uuid4().hex
|
||||||
|
|
||||||
|
opts = parser.parse_args(['--os-username', username,
|
||||||
|
'--os-auth-url', auth_url,
|
||||||
|
'--os-user-domain-id', user_domain_id,
|
||||||
|
'--os-project-id', project_id])
|
||||||
|
|
||||||
|
with mock.patch('getpass.getpass') as mock_getpass:
|
||||||
|
mock_getpass.return_value = password
|
||||||
|
mock_stdin.isatty = lambda: True
|
||||||
|
|
||||||
|
plugin = v3.Password.load_from_argparse_arguments(opts)
|
||||||
|
|
||||||
|
self.assertEqual(auth_url, plugin.auth_url)
|
||||||
|
self.assertEqual(username, plugin.auth_methods[0].username)
|
||||||
|
self.assertEqual(project_id, plugin.project_id)
|
||||||
|
self.assertEqual(user_domain_id,
|
||||||
|
plugin.auth_methods[0].user_domain_id)
|
||||||
|
self.assertEqual(password, plugin.auth_methods[0].password)
|
||||||
|
@@ -10,8 +10,11 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import argparse
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
from keystoneclient.auth.identity.generic import password
|
from keystoneclient.auth.identity.generic import password
|
||||||
from keystoneclient.auth.identity import v2
|
from keystoneclient.auth.identity import v2
|
||||||
from keystoneclient.auth.identity import v3
|
from keystoneclient.auth.identity import v3
|
||||||
@@ -66,3 +69,31 @@ class PasswordTests(utils.GenericPluginTestCase):
|
|||||||
def test_symbols(self):
|
def test_symbols(self):
|
||||||
self.assertIs(v3.Password, v3_password.Password)
|
self.assertIs(v3.Password, v3_password.Password)
|
||||||
self.assertIs(v3.PasswordMethod, v3_password.PasswordMethod)
|
self.assertIs(v3.PasswordMethod, v3_password.PasswordMethod)
|
||||||
|
|
||||||
|
@mock.patch('sys.stdin', autospec=True)
|
||||||
|
def test_prompt_password(self, mock_stdin):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
self.PLUGIN_CLASS.register_argparse_arguments(parser)
|
||||||
|
|
||||||
|
username = uuid.uuid4().hex
|
||||||
|
user_domain_id = uuid.uuid4().hex
|
||||||
|
auth_url = uuid.uuid4().hex
|
||||||
|
project_id = uuid.uuid4().hex
|
||||||
|
password = uuid.uuid4().hex
|
||||||
|
|
||||||
|
opts = parser.parse_args(['--os-username', username,
|
||||||
|
'--os-auth-url', auth_url,
|
||||||
|
'--os-user-domain-id', user_domain_id,
|
||||||
|
'--os-project-id', project_id])
|
||||||
|
|
||||||
|
with mock.patch('getpass.getpass') as mock_getpass:
|
||||||
|
mock_getpass.return_value = password
|
||||||
|
mock_stdin.isatty = lambda: True
|
||||||
|
|
||||||
|
plugin = self.PLUGIN_CLASS.load_from_argparse_arguments(opts)
|
||||||
|
|
||||||
|
self.assertEqual(auth_url, plugin.auth_url)
|
||||||
|
self.assertEqual(username, plugin._username)
|
||||||
|
self.assertEqual(project_id, plugin._project_id)
|
||||||
|
self.assertEqual(user_domain_id, plugin._user_domain_id)
|
||||||
|
self.assertEqual(password, plugin._password)
|
||||||
|
@@ -147,6 +147,24 @@ def hash_signed_token(signed_text, mode='md5'):
|
|||||||
return hash_.hexdigest()
|
return hash_.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_user_password():
|
||||||
|
"""Prompt user for a password
|
||||||
|
|
||||||
|
Prompt for a password if stdin is a tty.
|
||||||
|
"""
|
||||||
|
password = None
|
||||||
|
|
||||||
|
# If stdin is a tty, try prompting for the password
|
||||||
|
if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty():
|
||||||
|
# Check for Ctl-D
|
||||||
|
try:
|
||||||
|
password = getpass.getpass('Password: ')
|
||||||
|
except EOFError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return password
|
||||||
|
|
||||||
|
|
||||||
def prompt_for_password():
|
def prompt_for_password():
|
||||||
"""Prompt user for password if not provided so the password
|
"""Prompt user for password if not provided so the password
|
||||||
doesn't show up in the bash history.
|
doesn't show up in the bash history.
|
||||||
|
Reference in New Issue
Block a user