예제 #1
0
 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()
예제 #2
0
 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')
예제 #3
0
 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')
예제 #4
0
 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()
예제 #5
0
    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
예제 #6
0
 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}")
예제 #8
0
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)
예제 #9
0
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()
예제 #10
0
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")