SSHPool in utils should allow customized host key missing policy

The cinder/utils SSHPool should allow  missing key policy and host key
file being customized so that any caller can determine by their own
scenario if the host key file can be customized, or if an 'AutoAdd' is
appropriate, or just reject the key when mismatch. This will give more
flexible customization and also prevent any security issue as a middle
man.

Closes-Bug: #1320056
Change-Id: I3c72b0d042de719ecd45429d376bd88d0aefb2cc
This commit is contained in:
Lynxzh 2014-05-19 18:47:16 +08:00
parent 721e657073
commit 3908178796
2 changed files with 50 additions and 2 deletions

View File

@ -767,7 +767,13 @@ class FakeSSHClient(object):
self.transport = FakeTransport()
def set_missing_host_key_policy(self, policy):
pass
self.policy = policy
def load_system_host_keys(self):
self.system_host_keys = 'system_host_keys'
def load_host_keys(self, hosts_key_file):
self.hosts_key_file = hosts_key_file
def connect(self, ip, port=22, username=None, password=None,
pkey=None, timeout=10):
@ -776,6 +782,9 @@ class FakeSSHClient(object):
def get_transport(self):
return self.transport
def get_policy(self):
return self.policy
def close(self):
pass
@ -803,6 +812,33 @@ class FakeTransport(object):
class SSHPoolTestCase(test.TestCase):
"""Unit test for SSH Connection Pool."""
@mock.patch('paramiko.SSHClient')
def test_ssh_key_policy(self, mock_sshclient):
mock_sshclient.return_value = FakeSSHClient()
# create with customized setting
sshpool = utils.SSHPool("127.0.0.1", 22, 10,
"test",
password="test",
min_size=1,
max_size=1,
missing_key_policy=paramiko.RejectPolicy(),
hosts_key_file='dummy_host_keyfile')
with sshpool.item() as ssh:
self.assertTrue(isinstance(ssh.get_policy(),
paramiko.RejectPolicy))
self.assertEqual(ssh.hosts_key_file, 'dummy_host_keyfile')
# create with default setting
sshpool = utils.SSHPool("127.0.0.1", 22, 10,
"test",
password="test",
min_size=1,
max_size=1)
with sshpool.item() as ssh:
self.assertTrue(isinstance(ssh.get_policy(),
paramiko.AutoAddPolicy))
self.assertEqual(ssh.system_host_keys, 'system_host_keys')
@mock.patch('paramiko.RSAKey.from_private_key_file')
@mock.patch('paramiko.SSHClient')

View File

@ -189,12 +189,24 @@ class SSHPool(pools.Pool):
self.password = password
self.conn_timeout = conn_timeout if conn_timeout else None
self.privatekey = privatekey
if 'missing_key_policy' in kwargs.keys():
self.missing_key_policy = kwargs.pop('missing_key_policy')
else:
self.missing_key_policy = paramiko.AutoAddPolicy()
if 'hosts_key_file' in kwargs.keys():
self.hosts_key_file = kwargs.pop('hosts_key_file')
else:
self.hosts_key_file = None
super(SSHPool, self).__init__(*args, **kwargs)
def create(self):
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.set_missing_host_key_policy(self.missing_key_policy)
if not self.hosts_key_file:
ssh.load_system_host_keys()
else:
ssh.load_host_keys(self.hosts_key_file)
if self.password:
ssh.connect(self.ip,
port=self.port,