def test_init_without_host_raises_error(self, mock_init_logic, mock_input): mock_init_logic.fetch_account_from_server = MagicMock( side_effect=HttpStatusError(status=401)) mock_conjurrc_data = ConjurrcData() with self.assertRaises(MissingRequiredParameterException): mock_conjurrc_data.conjur_url = 'https://someurl' mock_init_controller = InitController( mock_conjurrc_data, mock_init_logic, False, self.ssl_verification_metadata) mock_init_controller._get_account_info_if_not_exist()
def test_init_host_is_added_to_conjurrc_object(self, mock_init_logic, mock_input): mock_init_logic.fetch_account_from_server = MagicMock( side_effect=HttpStatusError(status=401)) mock_conjurrc_data = ConjurrcData() mock_conjurrc_data.conjur_url = "https://someaccount" mock_init_controller = InitController(mock_conjurrc_data, mock_init_logic, False, self.ssl_verification_metadata) mock_init_controller._get_account_info_if_not_exist() self.assertEquals(mock_conjurrc_data.conjur_account, 'someaccount')
def test_user_does_not_input_https_will_raises_error(self, mock_input): mock_conjurrc_data = ConjurrcData(conjur_url='somehost') with self.assertRaises(InvalidURLFormatException) as context: init_controller = InitController(mock_conjurrc_data, self.init_logic, self.force_overwrite, self.ssl_verification_metadata) init_controller._validate_conjur_url(MOCK_FORMATTED_URL) self.assertRegex(str(context.exception), 'Error: undefined behavior')
def test_user_raises_certificate_hostname_mismatch_error( self, mock_init_logic): mock_init_logic.fetch_account_from_server = MagicMock( side_effect=CertificateHostnameMismatchException) init_controller = InitController(ConjurrcData(account=None), mock_init_logic, False, self.ssl_verification_metadata) with self.assertRaises(CertificateHostnameMismatchException): init_controller._get_account_info_if_not_exist()
def load_conjurrc_data(self) -> ConjurrcData: """ Method to load the conjurrc data because it is needed to fill in netrc properties and to send a login request to Conjur """ conjurrc = ConjurrcData.load_from_file() self.credential_data.machine = conjurrc.conjur_url return conjurrc
def test_user_does_not_input_url_raises_error(self, mock_input): mock_conjurrc_data = ConjurrcData(conjur_url=None) with self.assertRaises(InvalidURLFormatException) as context: init_controller = InitController(mock_conjurrc_data, self.init_logic, self.force_overwrite, self.ssl_verification_metadata) init_controller._prompt_for_conjur_url() self.assertRegex(str(context.exception), 'Error: URL is required')
def remove_credentials(self): """ Method for removing credentials from user machine """ try: loaded_conjurrc = ConjurrcData.load_from_file(DEFAULT_CONFIG_FILE) if not self.credentials_provider.is_exists(loaded_conjurrc.conjur_url): # Cleans up credentials leftover to make sure the environment is # not left in a partial state. For example, if user deleted # their username or password manually. self.logout_logic.cleanup_credentials(loaded_conjurrc) raise NotLoggedInException("You are already logged out.") self.logout_logic.remove_credentials(loaded_conjurrc) except Exception as error: # pylint: disable=raise-missing-from raise LoggedOutFailedException(f"Failed to log out. {error}")
def get_ssl_verification_meta_data_from_conjurrc( ssl_verify: bool, conjur_data: ConjurrcData = None) -> SslVerificationMetadata: """ Determine SslVerificationMetaData from conjurrc file """ if not conjur_data: conjur_data = ConjurrcData.load_from_file() cert_path = conjur_data.cert_file if not ssl_verify: return SslVerificationMetadata(SslVerificationMode.INSECURE) if not cert_path: return SslVerificationMetadata(SslVerificationMode.TRUST_STORE) if cert_path and cert_path != DEFAULT_CERTIFICATE_FILE: return SslVerificationMetadata(SslVerificationMode.CA_BUNDLE, cert_path) return SslVerificationMetadata(SslVerificationMode.SELF_SIGN, cert_path)
class InitControllerTest(unittest.TestCase): capture_stream = io.StringIO() conjurrc_data = ConjurrcData() ssl_service = SSLClient init_logic = InitLogic(ssl_service) force_overwrite = False ssl_verification_metadata = SslVerificationMetadata( SslVerificationMode.TRUST_STORE) def test_init_constructor(self): mock_conjurrc_data = None mock_init_logic = None mock_force = False mock_ssl_verification_data = SslVerificationMetadata( SslVerificationMode.INSECURE) InitController(mock_conjurrc_data, mock_init_logic, mock_force, mock_ssl_verification_data) assert InitController.conjurrc_data == mock_conjurrc_data assert InitController.init_logic == mock_init_logic assert InitController.force_overwrite == mock_force ''' When user does not supply an account a Runtime error should be raised ''' @patch('builtins.input', return_value='') @patch('conjur.logic.init_logic') def test_init_without_host_raises_error(self, mock_init_logic, mock_input): mock_init_logic.fetch_account_from_server = MagicMock( side_effect=HttpStatusError(status=401)) mock_conjurrc_data = ConjurrcData() with self.assertRaises(MissingRequiredParameterException): mock_conjurrc_data.conjur_url = 'https://someurl' mock_init_controller = InitController( mock_conjurrc_data, mock_init_logic, False, self.ssl_verification_metadata) mock_init_controller._get_account_info_if_not_exist() @patch('builtins.input', return_value='someaccount') @patch('conjur.logic.init_logic') def test_init_host_is_added_to_conjurrc_object(self, mock_init_logic, mock_input): mock_init_logic.fetch_account_from_server = MagicMock( side_effect=HttpStatusError(status=401)) mock_conjurrc_data = ConjurrcData() mock_conjurrc_data.conjur_url = "https://someaccount" mock_init_controller = InitController(mock_conjurrc_data, mock_init_logic, False, self.ssl_verification_metadata) mock_init_controller._get_account_info_if_not_exist() self.assertEquals(mock_conjurrc_data.conjur_account, 'someaccount') ''' When user does not trust the certificate, an exception will be raised ''' @patch('builtins.input', side_effect=['no']) def test_init_not_trusting_cert_raises_error(self, mock_input): self.conjurrc_data.conjur_url = 'https://someurl' ctx = SSL.Context(method=SSL.TLSv1_2_METHOD) sock = OpenSSL.SSL.Connection(ctx) self.init_logic.connect = MagicMock(return_value=sock) self.init_logic.get_certificate = MagicMock( return_value=["12:AB", "somecertchain"]) with self.assertRaises(CertificateNotTrustedException): init_controller = InitController(self.conjurrc_data, self.init_logic, self.force_overwrite, self.ssl_verification_metadata) init_controller._get_server_certificate(MOCK_FORMATTED_URL) ''' When user trusts the certificate, the certificate should be returned ''' @patch('builtins.input', side_effect=['yes']) def test_init_user_trusts_cert_returns_cert(self, mock_input): mock_certificate = "cert" self.conjurrc_data.conjur_url = "https://someurl" self.init_logic.get_certificate = MagicMock( return_value=["12:AB", mock_certificate]) init_controller = InitController(self.conjurrc_data, self.init_logic, self.force_overwrite, self.ssl_verification_metadata) fetched_certificate = init_controller._get_server_certificate( MOCK_FORMATTED_URL) self.assertEquals(fetched_certificate, mock_certificate) @patch('builtins.input', side_effect=['http://someurl']) def test_user_supplied_certificate_returns_none(self, mock_input): cert_file = "/some/path/somepem.pem" self.conjurrc_data.cert_file = cert_file ssl_verification_data = SslVerificationMetadata( SslVerificationMode.CA_BUNDLE, cert_file) init_controller = InitController(self.conjurrc_data, self.init_logic, self.force_overwrite, ssl_verification_data) fetched_certificate = init_controller._get_server_certificate( MOCK_FORMATTED_URL) assert self.conjurrc_data.cert_file == "/some/path/somepem.pem" self.assertEquals(fetched_certificate, None) @patch('conjur.logic.init_logic') def test_user_supplies_cert_writes_to_file_not_called( self, mock_init_logic): InitController._write_certificate(self, "https://some/cert/path") mock_init_logic.write_certificate_to_file.assert_not_called() ''' Validates that when the user wants to overwrite the certificate file, We attempt to write the certificate twice (initial attempt and user after confirmation) ''' # The certificate file exists and the CLI prompts # if the user wants to overwrite @patch('conjur.logic.init_logic') @patch('builtins.input', return_value='yes') def test_user_confirms_force_overwrites_writes_cert_to_file( self, mock_input, mock_init_logic): with redirect_stdout(self.capture_stream): self.conjurrc_data.conjur_url = "https://someurl" init_controller = InitController(self.conjurrc_data, mock_init_logic, False, self.ssl_verification_metadata) # Mock that a certificate file already exists mock_init_logic.write_certificate_to_file.return_value = False init_controller._write_certificate('some_cert') self.assertRegex(self.capture_stream.getvalue(), "Certificate written to") mock_init_logic.write_certificate_to_file.assert_called_with( 'some_cert', '/root/conjur-server.pem', True) self.assertEquals(mock_init_logic.write_certificate_to_file.call_count, 2) ''' Validates that when the user wants to overwrite the conjurrc file, We attempt to write the conjurrc twice (initial attempt and user after confirmation) ''' # The conjurrc file exists and the CLI prompts # if the user wants to overwrite @patch('conjur.logic.init_logic') @patch('builtins.input', return_value='yes') def test_user_confirms_force_overwrites_writes_conjurrc_to_file( self, mock_input, mock_init_logic): with redirect_stdout(self.capture_stream): self.conjurrc_data.conjur_url = "https://someurl" init_controller = InitController(self.conjurrc_data, mock_init_logic, False, self.ssl_verification_metadata) # Mock that a conjurrc file already exists mock_init_logic.write_conjurrc.return_value = False init_controller.write_conjurrc() self.assertRegex(self.capture_stream.getvalue(), "Configuration written to") mock_init_logic.write_conjurrc.assert_called_with( '/root/.conjurrc', self.conjurrc_data, True) self.assertEquals(mock_init_logic.write_conjurrc.call_count, 2) @patch('builtins.input', return_value='') def test_user_does_not_input_url_raises_error(self, mock_input): mock_conjurrc_data = ConjurrcData(conjur_url=None) with self.assertRaises(InvalidURLFormatException) as context: init_controller = InitController(mock_conjurrc_data, self.init_logic, self.force_overwrite, self.ssl_verification_metadata) init_controller._prompt_for_conjur_url() self.assertRegex(str(context.exception), 'Error: URL is required') @patch('builtins.input', return_value=MockConjurrcData.conjur_url) def test_user_does_not_input_https_will_raises_error(self, mock_input): mock_conjurrc_data = ConjurrcData(conjur_url='somehost') with self.assertRaises(InvalidURLFormatException) as context: init_controller = InitController(mock_conjurrc_data, self.init_logic, self.force_overwrite, self.ssl_verification_metadata) init_controller._validate_conjur_url(MOCK_FORMATTED_URL) self.assertRegex(str(context.exception), 'Error: undefined behavior') @patch('builtins.input', return_value='no') def test_user_does_not_overwrite_raises_error(self, mock_input): init_controller = InitController(ConjurrcData, InitLogic, False, self.ssl_verification_metadata) with self.assertRaises(Exception): init_controller.ensure_overwrite_file('someconfig') @patch('conjur.logic.init_logic') def test_user_raises_certificate_hostname_mismatch_error( self, mock_init_logic): mock_init_logic.fetch_account_from_server = MagicMock( side_effect=CertificateHostnameMismatchException) init_controller = InitController(ConjurrcData(account=None), mock_init_logic, False, self.ssl_verification_metadata) with self.assertRaises(CertificateHostnameMismatchException): init_controller._get_account_info_if_not_exist()
from contextlib import redirect_stdout from unittest.mock import patch, MagicMock import OpenSSL from OpenSSL import SSL from conjur_api.models import SslVerificationMetadata, SslVerificationMode from conjur.constants import TEST_HOSTNAME from conjur_api.errors.errors import CertificateHostnameMismatchException, HttpStatusError from conjur.errors import InvalidURLFormatException, CertificateNotTrustedException, MissingRequiredParameterException from conjur.logic.init_logic import InitLogic as InitLogic from conjur.controller.init_controller import InitController as InitController from conjur.data_object.conjurrc_data import ConjurrcData from conjur.util.ssl_utils import SSLClient MockConjurrcData = ConjurrcData(conjur_url=TEST_HOSTNAME, account="admin") class MOCK_FORMATTED_URL: hostname = MockConjurrcData.conjur_url port = 443 scheme = "somescheme" class InitControllerTest(unittest.TestCase): capture_stream = io.StringIO() conjurrc_data = ConjurrcData() ssl_service = SSLClient init_logic = InitLogic(ssl_service) force_overwrite = False ssl_verification_metadata = SslVerificationMetadata(
class UserLogicTest(unittest.TestCase): conjurrc_data = ConjurrcData('someurl', 'someacc', 'some/path/to/pem') credential_provider = FileCredentialsProvider() client = Client user_logic = UserLogic(conjurrc_data, credential_provider, client) def test_user_logic_constructor(self): mock_conjurrc_data = None mock_credential_provider = None mock_client = None user_logic = UserLogic(mock_conjurrc_data, mock_credential_provider, mock_client) self.assertEquals(user_logic.conjurrc_data, mock_conjurrc_data) self.assertEquals(user_logic.credential_provider, mock_credential_provider) self.assertEquals(user_logic.client, mock_client) ''' Validate that if user doesn't provide username, rotate_other_api_key will be called once with proper params ''' def test_user_does_not_provide_username_can_rotate_own_key(self): self.user_logic.extract_credentials_from_credential_store = MagicMock( return_value=MockCredentials) self.user_logic.rotate_other_api_key = MagicMock( return_value='someAPIKey') self.user_logic.rotate_api_key('someUserToRotate') self.user_logic.rotate_other_api_key.assert_called_once_with( 'someUserToRotate') ''' Validate that if user doesn't provide username, rotate_personal_api_key will be called once with proper params ''' def test_user_provides_username_can_rotate_anothers_key(self): self.user_logic.extract_credentials_from_credential_store = MagicMock( return_value=MockCredentials) self.user_logic.rotate_personal_api_key = MagicMock( return_value='someAPIKey') self.user_logic.rotate_api_key(None) self.user_logic.rotate_personal_api_key.assert_called_once_with( 'someuser', MockCredentials, 'someAPIKey') def test_change_password_returns_user(self): with patch.object(UserLogic, 'extract_credentials_from_credential_store', return_value=MockCredentials): client = MagicMock(return_value=None) mock_user_logic = UserLogic(ConjurrcData, FileCredentialsProvider, client) mock_user_logic.client.change_personal_password = MagicMock( return_value='success!') resource_to_update = mock_user_logic.change_personal_password( 'someNewPassword') self.assertEquals(resource_to_update, 'someuser') @patch('conjur.data_object.conjurrc_data.ConjurrcData.load_from_file', return_value=MockConjurrc) def test_extract_credential_provider_returns_netrc_store( self, mock_conjurrc): mock_user_logic = UserLogic(self.conjurrc_data, self.credential_provider, self.client) mock_user_logic.credential_provider.load = MagicMock( return_value=CONJURRC_DICT) mock_user_logic.extract_credentials_from_credential_store() self.assertEquals( mock_user_logic.extract_credentials_from_credential_store(), CONJURRC_DICT) ''' Validates that a rotated API key for another user can be returned ''' def test_rotate_other_api_key_returns_new_key(self): new_api_key = 'someAPIKey' client = MagicMock(return_value=None) mock_user_logic = UserLogic(ConjurrcData, FileCredentialsProvider, client) mock_user_logic.client.rotate_other_api_key = MagicMock( return_value=new_api_key) self.assertEquals(mock_user_logic.rotate_other_api_key('someuser'), new_api_key) ''' Validates that a new personal API key can be returned ''' def test_rotate_personal_api_key_returns_api_key(self): new_api_key = 'someAPIKey' client = MagicMock(return_value=None) mock_user_logic = UserLogic(ConjurrcData, FileCredentialsProvider, client) mock_user_logic.client.rotate_personal_api_key = MagicMock( return_value=new_api_key) mock_user_logic.update_api_key_in_credential_store = MagicMock( return_value='someupdatedstore!') self.assertEquals( mock_user_logic.rotate_personal_api_key('someuser', 'somecreds', 'somepass'), new_api_key) ''' Raises exception when HTTPError was raised ''' def test_rotate_personal_api_key_raises_exception_when_unauthorized(self): with self.assertRaises(HttpError): client = MagicMock(return_value=None) mock_user_logic = UserLogic(ConjurrcData, FileCredentialsProvider, client) mock_user_logic.client.rotate_personal_api_key = MagicMock( side_effect=HttpError) mock_user_logic.rotate_personal_api_key('someuser', 'somecreds', 'somepass') ''' Raises exception when operation was not able to be completed successfully ''' def test_rotate_personal_api_key_raises_exception_when_incomplete_operation( self): client = MagicMock(return_value=None) mock_user_logic = UserLogic(ConjurrcData, FileCredentialsProvider, client) mock_user_logic.client.rotate_personal_api_key = MagicMock( side_effect=OperationNotCompletedException) with self.assertRaises(OperationNotCompletedException): mock_user_logic.rotate_personal_api_key('someuser', 'somecreds', 'somepass') ''' Validates that update_api_key_entry was called ''' def test_update_entry_was_called(self): FileCredentialsProvider.update_api_key_entry = MagicMock() mock_user_logic = UserLogic(self.conjurrc_data, self.credential_provider, self.client) mock_user_logic.update_api_key_in_credential_store( 'some_user_to_update', 'loaded_creds', 'someapikey') FileCredentialsProvider.update_api_key_entry.assert_called_once_with( 'some_user_to_update', 'loaded_creds', 'someapikey')
def test_conjurrc_throws_error_when_key_is_missing(self, mock_open): mock_conjurrc = ConjurrcData("https://someurl", "someaccount", "/some/cert/path") with self.assertRaises(InvalidConfigurationException): mock_conjurrc.load_from_file()
def test_conjurrc_object_is_filled_correctly(self, mock_yaml_load): with patch("builtins.open", mock_open(read_data=EXPECTED_CONJURRC)): mock_conjurrc_data = ConjurrcData.load_from_file() self.assertEquals(mock_conjurrc_data.__dict__, CONJURRC_DICT)
def test_conjurrc_object_representation(self): conjurrc_data = ConjurrcData("https://someurl", "someaccount", "/some/cert/path") rep_obj = conjurrc_data.__repr__() self.assertEquals(str(EXPECTED_REP_OBJECT), rep_obj)
class InitLogicTest(unittest.TestCase): conjurrc_data = ConjurrcData("my_url", "myorg", None) ssl_service = SSLClient capture_stream = io.StringIO() init_logic = InitLogic(ssl_service) ''' Validates that certificate was written to the file ''' @patch('builtins.input', return_value='yes') def test_certificate_is_written_to_file(self, mock_input): with patch("builtins.open", mock_open(read_data=MOCK_CERT)): is_written = self.init_logic.write_certificate_to_file( MOCK_CERT, "path/to/cert.pem", False) assert is_written is True assert open("path/to/cert").read() == MOCK_CERT ''' Validates that when the user did not force the overwrite and the certificate already exists that the certificate is not overwritten ''' @patch('os.path.exists') def test_cert_exists_returns_not_written(self, mock_path_exists): mock_path_exists.return_value = True written = self.init_logic.write_certificate_to_file( MOCK_CERT, "/some/path/cert", False) self.assertEquals(written, False) ''' Validates that when the user did not force the overwrite and the conjurrc already exists that the conjurrc is not written ''' @patch('os.path.exists') def test_conjurrc_exists_returns_not_written(self, mock_path_exists): mock_path_exists.return_value = True written = self.init_logic.write_conjurrc(MOCK_CERT, "/some/path/cert", False) self.assertEquals(written, False) ''' Validates that conjurrc was written to the file ''' def test_conjurrc_is_written(self): with patch("builtins.open", mock_open(read_data=EXPECTED_CONFIG)): is_written = self.init_logic.write_conjurrc( "path/to/conjurrc", self.conjurrc_data, False) # assert that the file was written assert is_written is True assert open("path/to/conjurrc").read() == EXPECTED_CONFIG ''' Validates that the conjurrc was written in the proper format ''' def test_conjurrc_is_written_formatted_correctly(self): with mock.patch.object(self.init_logic, '_InitLogic__overwrite_file_if_exists', create=True, return_value=None): with patch("builtins.open", mock_open(read_data=EXPECTED_CONFIG)): self.init_logic.write_conjurrc("path/to/conjurrc", self.conjurrc_data, False) with open('path/to/conjurrc', 'r') as conjurrc: lines = conjurrc.readlines() self.assertEquals(lines[0].strip(), "---") self.assertEquals(lines[1].strip(), "conjur_account: someaccount") self.assertEquals( lines[3].strip(), "cert_file: /path/to/conjur-someaccount.pem") ''' Validates that Conjur can connect to server ''' def test_dns_error_will_raise_exception(self): with patch.object(SSLClient, 'get_certificate', side_effect=TLSSocketConnectionException( "err")) as mock_get_cert: with self.assertRaises( ConnectionToConjurFailedException) as context: init_logic = InitLogic(self.ssl_service()) init_logic.get_certificate('https://url', None) self.assertRegex(str(context.exception), 'Unable to resolve server DNS ') def test_timeout_error_will_raise_exception(self): with patch.object(SSLClient, 'get_certificate', side_effect=TimeoutError) as mock_get_cert: with self.assertRaises( ConnectionToConjurFailedException) as context: init_logic = InitLogic(self.ssl_service) init_logic.get_certificate('https://url', None) self.assertRegex(str(context.exception), 'Unable to connect to server ') def test_cert_error_will_raise_exception(self): with patch.object(SSLClient, 'get_certificate', side_effect=Exception) as mock_get_cert: with self.assertRaises(Exception) as context: init_logic = InitLogic(self.ssl_service) init_logic.get_certificate('https://url', None) self.assertRegex(str(context.exception), 'Unable to retrieve certificate from ') ''' Validates that the fingerprint and certificate that were returned from the inner called service are also returned by the caller ''' def test_fingerprint_and_certificate_are_properly_returned(self): with patch.object(SSLClient, 'get_certificate', return_value=["12:AB", "cert"]) as mock_ssl: mock_init_command = InitLogic(self.ssl_service) fingerprint, readable_certificate = mock_init_command.get_certificate( "https://someurl", 443) self.assertEquals(fingerprint, "12:AB") self.assertEquals(readable_certificate, "cert")