0

I have a function, the job of which is to read the private key and certificate from a shared drive.

def get_private_key():
    with open(config.CERTIFICATE_PATH + config.PRIVATE_KEY, 'rb') as key_file, \
             open(config.CERTIFICATE_PATH + config.PUBLIC_KEY, 'rb') as cert_file_string:
        private_key = serialization.load_pem_private_key(key_file.read(), password=None, backend=default_backend())
        cert = load_certificate(FILETYPE_PEM, cert_file_string.read())
    sha1_fingerprint = cert.digest("sha1")
    strkid = sha1_fingerprint.decode()
    kid = strkid.replace(':', '')

I'm trying to write a unit test for this where I won't have access to the shared drive, hence I'm trying to mock the certificate and the private key. Here's what I've tried so far.

@patch('OpenSSL.crypto.load_certificate')
@patch('cryptography.hazmat.primitives.serialization.load_pem_private_key')
@patch('builtins.open')
def test_get_private_key(self, mock_open, mock_load_pem_private_key, mock_load_certificate)
    mock_open.return_value = io.BytesIO('dummy'.encode('utf-8'))
    mock_load_pem_private_key.return_value = MagicMock(cryptography.hazmat.backends.openssl.rsa.RSAPrivateKey)
    mock_load_certificate.return_value = MagicMock(crypto.X509)
    self.assertEqual(get_private_key(), "dummyPvtKey")

But when I try to run this test I get an error on the line where I'm invoking the load_certificate function.

OpenSSL.crypto.Error: [('PEM routines', 'get_name', 'no start line')]

It would be great if someone could advise me on how to go about this, thanks in advance.

1 Answers1

0

Explanation

You've patched the wrong target for the following line

@patch('OpenSSL.crypto.load_certificate')

Since you've imported load_certificate() and used it in your module where get_private_key() is, let's call it foo.py since you didn't provide it your post. We want to patch the load_certificate() in foo.py not where it's defined which is OpenSSL.crypto.

Solution

Change the patch target to

@patch('foo.load_certificate')

Resources

annonymous
  • 741
  • 3
  • 6
  • This worked, thank you so much. Although I do have a doubt here, the load_certificate mock wasn't mocking because of the reason you mentioned above. Then why was the mock for load_pem_private_key working, ideally this shouldn't have been working as well right? – Ahmad Shaikh Jul 31 '22 at 09:25
  • It's because of the way it's imported. If you imported part of a module (e.g. a function or class), then you have to patch where it is used. If you import the whole module, you can patch it by referring to the module where the original function or class resides. – annonymous Jul 31 '22 at 12:02