# -*- coding: utf-8 -*- # Import Python libs from __future__ import absolute_import # Import Salt Libs from salt.states import mac_keychain as keychain # Import Salt Testing Libs from salttesting import TestCase from salttesting.helpers import ensure_in_syspath from salttesting.mock import ( MagicMock, patch, call ) ensure_in_syspath('../../') keychain.__salt__ = {} class KeychainTestCase(TestCase): def test_install_cert(self): ''' Test installing a certificate into the macOS keychain ''' expected = { 'changes': {'installed': 'Friendly Name'}, 'comment': '', 'name': '/path/to/cert.p12', 'result': True } list_mock = MagicMock(return_value=['Cert1']) friendly_mock = MagicMock(return_value='Friendly Name') install_mock = MagicMock(return_value='1 identity imported.') with patch.dict(keychain.__salt__, {'keychain.list_certs': list_mock, 'keychain.get_friendly_name': friendly_mock, 'keychain.install': install_mock}): out = keychain.installed('/path/to/cert.p12', 'passw0rd') list_mock.assert_called_once_with('/Library/Keychains/System.keychain') friendly_mock.assert_called_once_with('/path/to/cert.p12', 'passw0rd') install_mock.assert_called_once_with('/path/to/cert.p12', 'passw0rd', '/Library/Keychains/System.keychain') self.assertEqual(out, expected) def test_installed_cert(self): ''' Test installing a certificate into the macOS keychain when it's already installed ''' expected = { 'changes': {}, 'comment': 'Friendly Name already installed.', 'name': '/path/to/cert.p12', 'result': True } list_mock = MagicMock(return_value=['Friendly Name']) friendly_mock = MagicMock(return_value='Friendly Name') install_mock = MagicMock(return_value='1 identity imported.') hash_mock = MagicMock(return_value='ABCD') with patch.dict(keychain.__salt__, {'keychain.list_certs': list_mock, 'keychain.get_friendly_name': friendly_mock, 'keychain.install': install_mock, 'keychain.get_hash': hash_mock}): out = keychain.installed('/path/to/cert.p12', 'passw0rd') list_mock.assert_called_once_with('/Library/Keychains/System.keychain') friendly_mock.assert_called_once_with('/path/to/cert.p12', 'passw0rd') assert not install_mock.called self.assertEqual(out, expected) def test_uninstall_cert(self): ''' Test uninstalling a certificate into the macOS keychain when it's already installed ''' expected = { 'changes': {'uninstalled': 'Friendly Name'}, 'comment': '', 'name': '/path/to/cert.p12', 'result': True } list_mock = MagicMock(return_value=['Friendly Name']) friendly_mock = MagicMock(return_value='Friendly Name') uninstall_mock = MagicMock(return_value='1 identity imported.') with patch.dict(keychain.__salt__, {'keychain.list_certs': list_mock, 'keychain.get_friendly_name': friendly_mock, 'keychain.uninstall': uninstall_mock}): out = keychain.uninstalled('/path/to/cert.p12', 'passw0rd') list_mock.assert_called_once_with('/Library/Keychains/System.keychain') friendly_mock.assert_called_once_with('/path/to/cert.p12', 'passw0rd') uninstall_mock.assert_called_once_with('Friendly Name', '/Library/Keychains/System.keychain', None) self.assertEqual(out, expected) def test_uninstalled_cert(self): ''' Test uninstalling a certificate into the macOS keychain when it's not installed ''' expected = { 'changes': {}, 'comment': 'Friendly Name already uninstalled.', 'name': '/path/to/cert.p12', 'result': True } list_mock = MagicMock(return_value=['Cert2']) friendly_mock = MagicMock(return_value='Friendly Name') uninstall_mock = MagicMock(return_value='1 identity imported.') with patch.dict(keychain.__salt__, {'keychain.list_certs': list_mock, 'keychain.get_friendly_name': friendly_mock, 'keychain.uninstall': uninstall_mock}): out = keychain.uninstalled('/path/to/cert.p12', 'passw0rd') list_mock.assert_called_once_with('/Library/Keychains/System.keychain') friendly_mock.assert_called_once_with('/path/to/cert.p12', 'passw0rd') assert not uninstall_mock.called self.assertEqual(out, expected) @patch('os.path.exists') def test_default_keychain(self, exists_mock): ''' Test setting the default keychain ''' expected = { 'changes': {'default': '/path/to/chain.keychain'}, 'comment': '', 'name': '/path/to/chain.keychain', 'result': True } exists_mock.return_value = True get_default_mock = MagicMock(return_value='/path/to/other.keychain') set_mock = MagicMock(return_value='') with patch.dict(keychain.__salt__, {'keychain.get_default_keychain': get_default_mock, 'keychain.set_default_keychain': set_mock}): out = keychain.default_keychain('/path/to/chain.keychain', 'system', 'frank') get_default_mock.assert_called_once_with('frank', 'system') set_mock.assert_called_once_with('/path/to/chain.keychain', 'system', 'frank') self.assertEqual(out, expected) @patch('os.path.exists') def test_default_keychain_set_already(self, exists_mock): ''' Test setting the default keychain when it's already set ''' expected = { 'changes': {}, 'comment': '/path/to/chain.keychain was already the default keychain.', 'name': '/path/to/chain.keychain', 'result': True } exists_mock.return_value = True get_default_mock = MagicMock(return_value='/path/to/chain.keychain') set_mock = MagicMock(return_value='') with patch.dict(keychain.__salt__, {'keychain.get_default_keychain': get_default_mock, 'keychain.set_default_keychain': set_mock}): out = keychain.default_keychain('/path/to/chain.keychain', 'system', 'frank') get_default_mock.assert_called_once_with('frank', 'system') assert not set_mock.called self.assertEqual(out, expected) @patch('os.path.exists') def test_default_keychain_missing(self, exists_mock): ''' Test setting the default keychain when the keychain is missing ''' expected = { 'changes': {}, 'comment': 'Keychain not found at /path/to/cert.p12', 'name': '/path/to/cert.p12', 'result': False } exists_mock.return_value = False out = keychain.default_keychain('/path/to/cert.p12', 'system', 'frank') self.assertEqual(out, expected) def test_install_cert_salt_fileserver(self): ''' Test installing a certificate into the macOS keychain from the salt fileserver ''' expected = { 'changes': {'installed': 'Friendly Name'}, 'comment': '', 'name': 'salt://path/to/cert.p12', 'result': True } list_mock = MagicMock(return_value=['Cert1']) friendly_mock = MagicMock(return_value='Friendly Name') install_mock = MagicMock(return_value='1 identity imported.') cp_cache_mock = MagicMock(return_value='/tmp/path/to/cert.p12') with patch.dict(keychain.__salt__, {'keychain.list_certs': list_mock, 'keychain.get_friendly_name': friendly_mock, 'keychain.install': install_mock, 'cp.cache_file': cp_cache_mock}): out = keychain.installed('salt://path/to/cert.p12', 'passw0rd') list_mock.assert_called_once_with('/Library/Keychains/System.keychain') friendly_mock.assert_called_once_with('/tmp/path/to/cert.p12', 'passw0rd') install_mock.assert_called_once_with('/tmp/path/to/cert.p12', 'passw0rd', '/Library/Keychains/System.keychain') self.assertEqual(out, expected) def test_installed_cert_hash_different(self): ''' Test installing a certificate into the macOS keychain when it's already installed but the certificate has changed ''' expected = { 'changes': {'installed': 'Friendly Name', 'uninstalled': 'Friendly Name'}, 'comment': 'Found a certificate with the same name but different hash, removing it.\n', 'name': '/path/to/cert.p12', 'result': True } list_mock = MagicMock(side_effect=[['Friendly Name'], []]) friendly_mock = MagicMock(return_value='Friendly Name') install_mock = MagicMock(return_value='1 identity imported.') uninstall_mock = MagicMock(return_value='removed.') hash_mock = MagicMock(side_effect=['ABCD', 'XYZ']) with patch.dict(keychain.__salt__, {'keychain.list_certs': list_mock, 'keychain.get_friendly_name': friendly_mock, 'keychain.install': install_mock, 'keychain.uninstall': uninstall_mock, 'keychain.get_hash': hash_mock}): out = keychain.installed('/path/to/cert.p12', 'passw0rd') list_mock.assert_has_calls(calls=[call('/Library/Keychains/System.keychain'), call('/Library/Keychains/System.keychain')]) friendly_mock.assert_called_once_with('/path/to/cert.p12', 'passw0rd') install_mock.assert_called_once_with('/path/to/cert.p12', 'passw0rd', '/Library/Keychains/System.keychain') uninstall_mock.assert_called_once_with('Friendly Name', '/Library/Keychains/System.keychain', keychain_password=None) self.assertEqual(out, expected) if __name__ == '__main__': from integration import run_tests run_tests(KeychainTestCase, needs_daemon=False)