2013-11-27 11:19:24 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2012-05-21 17:45:03 +00:00
|
|
|
'''
|
|
|
|
Test the ssh_known_hosts state
|
|
|
|
'''
|
2013-06-27 12:49:50 +00:00
|
|
|
|
|
|
|
# Import python libs
|
2014-11-21 19:05:13 +00:00
|
|
|
from __future__ import absolute_import
|
2012-05-21 17:45:03 +00:00
|
|
|
import os
|
|
|
|
import shutil
|
2013-06-27 12:49:50 +00:00
|
|
|
|
|
|
|
# Import Salt Testing libs
|
2017-04-03 16:04:09 +00:00
|
|
|
from tests.support.case import ModuleCase
|
|
|
|
from tests.support.mixins import SaltReturnAssertsMixin
|
|
|
|
from tests.support.runtests import RUNTIME_VARS
|
2017-02-27 13:58:07 +00:00
|
|
|
from tests.support.helpers import (
|
2013-09-27 21:57:19 +00:00
|
|
|
destructiveTest,
|
2014-05-20 09:53:47 +00:00
|
|
|
with_system_user,
|
2017-04-04 17:57:27 +00:00
|
|
|
skip_if_binaries_missing,
|
|
|
|
skip_if_not_root
|
2013-09-27 21:57:19 +00:00
|
|
|
)
|
2013-06-27 12:49:50 +00:00
|
|
|
|
|
|
|
# Import salt libs
|
2017-07-18 16:31:01 +00:00
|
|
|
import salt.utils.files
|
2012-05-21 17:45:03 +00:00
|
|
|
|
2017-04-03 16:04:09 +00:00
|
|
|
KNOWN_HOSTS = os.path.join(RUNTIME_VARS.TMP, 'known_hosts')
|
2017-05-11 15:33:45 +00:00
|
|
|
GITHUB_FINGERPRINT = '9d:38:5b:83:a9:17:52:92:56:1a:5e:c4:d4:81:8e:0a:ca:51:a2:64:f1:74:20:11:2e:f8:8a:c3:a1:39:49:8f'
|
2016-07-12 19:17:41 +00:00
|
|
|
GITHUB_IP = '192.30.253.113'
|
2012-05-21 17:45:03 +00:00
|
|
|
|
|
|
|
|
2014-02-05 21:56:08 +00:00
|
|
|
@skip_if_binaries_missing(['ssh', 'ssh-keygen'], check_all=True)
|
2017-04-03 16:04:09 +00:00
|
|
|
class SSHKnownHostsStateTest(ModuleCase, SaltReturnAssertsMixin):
|
2012-05-21 17:45:03 +00:00
|
|
|
'''
|
|
|
|
Validate the ssh state
|
|
|
|
'''
|
|
|
|
def tearDown(self):
|
|
|
|
if os.path.isfile(KNOWN_HOSTS):
|
|
|
|
os.remove(KNOWN_HOSTS)
|
|
|
|
super(SSHKnownHostsStateTest, self).tearDown()
|
|
|
|
|
|
|
|
def test_present(self):
|
|
|
|
'''
|
|
|
|
ssh_known_hosts.present
|
|
|
|
'''
|
2012-12-07 12:46:02 +00:00
|
|
|
kwargs = {
|
|
|
|
'name': 'github.com',
|
|
|
|
'user': 'root',
|
|
|
|
'fingerprint': GITHUB_FINGERPRINT,
|
|
|
|
'config': KNOWN_HOSTS
|
2012-05-22 18:13:52 +00:00
|
|
|
}
|
|
|
|
# test first
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.present', test=True, **kwargs)
|
|
|
|
self.assertSaltNoneReturn(ret)
|
|
|
|
|
2012-05-24 16:05:45 +00:00
|
|
|
# save once, new key appears
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.present', **kwargs)
|
|
|
|
try:
|
|
|
|
self.assertSaltTrueReturn(ret)
|
2013-05-04 02:53:53 +00:00
|
|
|
except AssertionError as err:
|
2012-12-07 12:46:02 +00:00
|
|
|
try:
|
|
|
|
self.assertInSaltComment(
|
2013-08-18 04:46:33 +00:00
|
|
|
'Unable to receive remote host key', ret
|
2012-12-07 12:46:02 +00:00
|
|
|
)
|
|
|
|
self.skipTest('Unable to receive remote host key')
|
|
|
|
except AssertionError:
|
|
|
|
# raise initial assertion error
|
|
|
|
raise err
|
|
|
|
|
|
|
|
self.assertSaltStateChangesEqual(
|
|
|
|
ret, GITHUB_FINGERPRINT, keys=('new', 'fingerprint')
|
|
|
|
)
|
|
|
|
|
2012-05-24 16:05:45 +00:00
|
|
|
# save twice, no changes
|
2015-01-13 01:53:56 +00:00
|
|
|
self.run_state('ssh_known_hosts.present', **kwargs)
|
2012-12-07 12:46:02 +00:00
|
|
|
|
2012-05-22 18:13:52 +00:00
|
|
|
# test again, nothing is about to be changed
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.present', test=True, **kwargs)
|
2013-07-02 10:25:11 +00:00
|
|
|
self.assertSaltTrueReturn(ret)
|
2012-12-07 12:46:02 +00:00
|
|
|
|
2012-05-23 17:45:16 +00:00
|
|
|
# then add a record for IP address
|
2017-02-28 12:07:21 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.present', # pylint: disable=repeated-keyword
|
2012-12-07 12:46:02 +00:00
|
|
|
**dict(kwargs, name=GITHUB_IP))
|
2016-10-05 07:32:57 +00:00
|
|
|
try:
|
|
|
|
self.assertSaltStateChangesEqual(
|
|
|
|
ret, GITHUB_FINGERPRINT, keys=('new', 'fingerprint')
|
|
|
|
)
|
|
|
|
except AssertionError as err:
|
|
|
|
try:
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Unable to receive remote host key', ret
|
|
|
|
)
|
|
|
|
self.skipTest('Unable to receive remote host key')
|
|
|
|
except AssertionError:
|
|
|
|
raise err
|
2012-12-07 12:46:02 +00:00
|
|
|
|
2012-05-23 17:45:16 +00:00
|
|
|
# record for every host must be available
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_function(
|
|
|
|
'ssh.get_known_host', ['root', 'github.com'], config=KNOWN_HOSTS
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
self.assertNotIn(ret, ('', None))
|
|
|
|
except AssertionError:
|
|
|
|
raise AssertionError(
|
2015-08-27 04:26:08 +00:00
|
|
|
'Salt return \'{0}\' is in (\'\', None).'.format(ret)
|
2012-12-07 12:46:02 +00:00
|
|
|
)
|
|
|
|
ret = self.run_function(
|
|
|
|
'ssh.get_known_host', ['root', GITHUB_IP], config=KNOWN_HOSTS
|
|
|
|
)
|
|
|
|
try:
|
|
|
|
self.assertNotIn(ret, ('', None, {}))
|
|
|
|
except AssertionError:
|
|
|
|
raise AssertionError(
|
2015-08-27 04:26:08 +00:00
|
|
|
'Salt return \'{0}\' is in (\'\', None,'.format(ret) + ' {})'
|
2012-12-07 12:46:02 +00:00
|
|
|
)
|
2012-05-21 17:45:03 +00:00
|
|
|
|
|
|
|
def test_present_fail(self):
|
|
|
|
# save something wrong
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state(
|
|
|
|
'ssh_known_hosts.present',
|
|
|
|
name='github.com',
|
|
|
|
user='root',
|
|
|
|
fingerprint='aa:bb:cc:dd',
|
|
|
|
config=KNOWN_HOSTS
|
|
|
|
)
|
|
|
|
self.assertSaltFalseReturn(ret)
|
2012-05-21 17:45:03 +00:00
|
|
|
|
|
|
|
def test_absent(self):
|
|
|
|
'''
|
|
|
|
ssh_known_hosts.absent
|
|
|
|
'''
|
2017-04-03 16:04:09 +00:00
|
|
|
known_hosts = os.path.join(RUNTIME_VARS.FILES, 'ssh', 'known_hosts')
|
2012-08-05 18:23:12 +00:00
|
|
|
shutil.copyfile(known_hosts, KNOWN_HOSTS)
|
|
|
|
if not os.path.isfile(KNOWN_HOSTS):
|
2012-12-07 12:46:02 +00:00
|
|
|
self.skipTest(
|
|
|
|
'Unable to copy {0} to {1}'.format(
|
|
|
|
known_hosts, KNOWN_HOSTS
|
|
|
|
)
|
|
|
|
)
|
2012-08-05 18:23:12 +00:00
|
|
|
|
|
|
|
kwargs = {'name': 'github.com', 'user': 'root', 'config': KNOWN_HOSTS}
|
2012-05-22 18:13:52 +00:00
|
|
|
# test first
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.absent', test=True, **kwargs)
|
|
|
|
self.assertSaltNoneReturn(ret)
|
|
|
|
|
2012-05-24 16:05:45 +00:00
|
|
|
# remove once, the key is gone
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.absent', **kwargs)
|
|
|
|
self.assertSaltStateChangesEqual(
|
|
|
|
ret, GITHUB_FINGERPRINT, keys=('old', 'fingerprint')
|
|
|
|
)
|
|
|
|
|
2012-05-24 16:05:45 +00:00
|
|
|
# remove twice, nothing has changed
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.absent', **kwargs)
|
|
|
|
self.assertSaltStateChangesEqual(ret, {})
|
|
|
|
|
2012-05-22 18:13:52 +00:00
|
|
|
# test again
|
2012-12-07 12:46:02 +00:00
|
|
|
ret = self.run_state('ssh_known_hosts.absent', test=True, **kwargs)
|
2015-03-06 10:47:29 +00:00
|
|
|
self.assertSaltTrueReturn(ret)
|
2012-05-23 17:45:16 +00:00
|
|
|
|
|
|
|
|
2017-04-03 16:04:09 +00:00
|
|
|
class SSHAuthStateTests(ModuleCase, SaltReturnAssertsMixin):
|
2013-09-27 21:57:19 +00:00
|
|
|
|
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2014-04-25 19:03:41 +00:00
|
|
|
@with_system_user('issue_7409', on_existing='delete', delete=True)
|
2013-09-27 21:57:19 +00:00
|
|
|
def test_issue_7409_no_linebreaks_between_keys(self, username):
|
|
|
|
|
|
|
|
userdetails = self.run_function('user.info', [username])
|
|
|
|
user_ssh_dir = os.path.join(userdetails['home'], '.ssh')
|
|
|
|
authorized_keys_file = os.path.join(user_ssh_dir, 'authorized_keys')
|
|
|
|
|
|
|
|
ret = self.run_state(
|
|
|
|
'file.managed',
|
|
|
|
name=authorized_keys_file,
|
|
|
|
user=username,
|
|
|
|
makedirs=True,
|
2014-06-10 01:32:22 +00:00
|
|
|
contents_newline=False,
|
2013-09-27 21:57:19 +00:00
|
|
|
# Explicit no ending line break
|
|
|
|
contents='ssh-rsa AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY== root'
|
|
|
|
)
|
|
|
|
|
|
|
|
ret = self.run_state(
|
|
|
|
'ssh_auth.present',
|
|
|
|
name='AAAAB3NzaC1kcQ9J5bYTEyZ==',
|
|
|
|
enc='ssh-rsa',
|
|
|
|
user=username,
|
|
|
|
comment=username
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn(ret)
|
|
|
|
self.assertSaltStateChangesEqual(
|
|
|
|
ret, {'AAAAB3NzaC1kcQ9J5bYTEyZ==': 'New'}
|
|
|
|
)
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen(authorized_keys_file, 'r') as fhr:
|
2014-11-26 18:01:35 +00:00
|
|
|
self.assertEqual(
|
|
|
|
fhr.read(),
|
|
|
|
'ssh-rsa AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY== root\n'
|
|
|
|
'ssh-rsa AAAAB3NzaC1kcQ9J5bYTEyZ== {0}\n'.format(username)
|
|
|
|
)
|
2013-09-27 21:57:19 +00:00
|
|
|
|
2014-02-05 21:56:08 +00:00
|
|
|
@destructiveTest
|
2017-04-04 17:57:27 +00:00
|
|
|
@skip_if_not_root
|
2014-04-25 19:03:41 +00:00
|
|
|
@with_system_user('issue_10198', on_existing='delete', delete=True)
|
2014-02-05 21:56:08 +00:00
|
|
|
def test_issue_10198_keyfile_from_another_env(self, username=None):
|
|
|
|
userdetails = self.run_function('user.info', [username])
|
|
|
|
user_ssh_dir = os.path.join(userdetails['home'], '.ssh')
|
|
|
|
authorized_keys_file = os.path.join(user_ssh_dir, 'authorized_keys')
|
|
|
|
|
|
|
|
key_fname = 'issue_10198.id_rsa.pub'
|
|
|
|
|
|
|
|
# Create the keyfile that we expect to get back on the state call
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.TMP_PRODENV_STATE_TREE, key_fname), 'w') as kfh:
|
2014-02-05 21:56:08 +00:00
|
|
|
kfh.write(
|
|
|
|
'ssh-rsa AAAAB3NzaC1kcQ9J5bYTEyZ== {0}\n'.format(username)
|
|
|
|
)
|
|
|
|
|
|
|
|
# Create a bogus key file on base environment
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.TMP_STATE_TREE, key_fname), 'w') as kfh:
|
2014-02-05 21:56:08 +00:00
|
|
|
kfh.write(
|
|
|
|
'ssh-rsa BAAAB3NzaC1kcQ9J5bYTEyZ== {0}\n'.format(username)
|
|
|
|
)
|
|
|
|
|
|
|
|
ret = self.run_state(
|
|
|
|
'ssh_auth.present',
|
|
|
|
name='Setup Keys',
|
|
|
|
source='salt://{0}?saltenv=prod'.format(key_fname),
|
|
|
|
enc='ssh-rsa',
|
|
|
|
user=username,
|
|
|
|
comment=username
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn(ret)
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen(authorized_keys_file, 'r') as fhr:
|
2014-11-26 18:01:35 +00:00
|
|
|
self.assertEqual(
|
|
|
|
fhr.read(),
|
|
|
|
'ssh-rsa AAAAB3NzaC1kcQ9J5bYTEyZ== {0}\n'.format(username)
|
|
|
|
)
|
2014-02-05 21:56:08 +00:00
|
|
|
|
|
|
|
os.unlink(authorized_keys_file)
|
|
|
|
|
|
|
|
ret = self.run_state(
|
|
|
|
'ssh_auth.present',
|
|
|
|
name='Setup Keys',
|
|
|
|
source='salt://{0}'.format(key_fname),
|
|
|
|
enc='ssh-rsa',
|
|
|
|
user=username,
|
|
|
|
comment=username,
|
|
|
|
saltenv='prod'
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn(ret)
|
2017-07-18 16:31:01 +00:00
|
|
|
with salt.utils.files.fopen(authorized_keys_file, 'r') as fhr:
|
2014-11-26 18:01:35 +00:00
|
|
|
self.assertEqual(
|
|
|
|
fhr.read(),
|
|
|
|
'ssh-rsa AAAAB3NzaC1kcQ9J5bYTEyZ== {0}\n'.format(username)
|
|
|
|
)
|