Browse Source

Fix exception handling and add tests

Per [0], fernet decrypt can never throw an InvalidSignature exception as that
is re-raised as InvalidToken. This patch set corrects the handling of the
exception, and added additional unit tests for coverage.

[0] https://cryptography.io/en/latest/fernet/#cryptography.fernet.Fernet.decrypt

Co-Authored-By: Drew Walters <drewwalters96@gmail.com>
Change-Id: Ic5ee7ef451a5657519c5397fc4b903b5adcb1d18
Signed-off-by: Tin Lam <tin@irrational.io>
changes/93/634593/6
Tin Lam 3 months ago
parent
commit
aa241081c9

+ 7
- 8
pegleg/engine/util/encryption.py View File

@@ -15,8 +15,7 @@
15 15
 import base64
16 16
 import logging
17 17
 
18
-from cryptography.exceptions import InvalidSignature
19
-from cryptography.fernet import Fernet
18
+from cryptography import fernet
20 19
 from cryptography.hazmat.backends import default_backend
21 20
 from cryptography.hazmat.primitives import hashes
22 21
 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
@@ -57,8 +56,8 @@ def encrypt(unencrypted_data,
57 56
     :rtype: bytes
58 57
     """
59 58
 
60
-    return Fernet(_generate_key(passphrase, salt, key_length,
61
-                                iterations)).encrypt(unencrypted_data)
59
+    return fernet.Fernet(_generate_key(
60
+        passphrase, salt, key_length, iterations)).encrypt(unencrypted_data)
62 61
 
63 62
 
64 63
 def decrypt(encrypted_data,
@@ -88,14 +87,14 @@ def decrypt(encrypted_data,
88 87
     :type iterations: positive integer.
89 88
     :return: Decrypted secret data
90 89
     :rtype: bytes
91
-    :raises InvalidSignature: If the provided passphrase, and/or
90
+    :raises InvalidToken: If the provided passphrase, and/or
92 91
     salt does not match the values used to encrypt the data.
93 92
     """
94 93
 
95 94
     try:
96
-        return Fernet(_generate_key(passphrase, salt, key_length,
97
-                                    iterations)).decrypt(encrypted_data)
98
-    except InvalidSignature:
95
+        return fernet.Fernet(_generate_key(
96
+            passphrase, salt, key_length, iterations)).decrypt(encrypted_data)
97
+    except fernet.InvalidToken:
99 98
         LOG.error('Signature verification to decrypt secrets failed. Please '
100 99
                   'check your provided passphrase and salt and try again.')
101 100
         raise

+ 1
- 0
test-requirements.txt View File

@@ -1,6 +1,7 @@
1 1
 # Testing
2 2
 pytest==3.2.1
3 3
 pytest-cov==2.5.1
4
+testfixtures
4 5
 mock==2.0.0
5 6
 
6 7
 # Formatting

+ 24
- 0
tests/unit/engine/test_generate_cryptostring.py View File

@@ -14,9 +14,13 @@
14 14
 
15 15
 import os
16 16
 import tempfile
17
+import uuid
17 18
 
19
+from cryptography import fernet
18 20
 import mock
21
+import pytest
19 22
 import string
23
+from testfixtures import log_capture
20 24
 import yaml
21 25
 
22 26
 from pegleg.engine.util.cryptostring import CryptoString
@@ -176,3 +180,23 @@ def test_generate_passphrases(*_):
176 180
                 assert len(decrypted_passphrase) == 25
177 181
             else:
178 182
                 assert len(decrypted_passphrase) == 24
183
+
184
+
185
+@log_capture()
186
+def test_generate_passphrases_exception(capture):
187
+    unenc_data = uuid.uuid4().bytes
188
+    passphrase1 = uuid.uuid4().bytes
189
+    passphrase2 = uuid.uuid4().bytes
190
+    salt1 = uuid.uuid4().bytes
191
+    salt2 = uuid.uuid4().bytes
192
+
193
+    # Generate random data and encrypt it
194
+    enc_data = encryption.encrypt(unenc_data, passphrase1, salt1)
195
+
196
+    # Decrypt using the wrong key to see to see the InvalidToken error
197
+    with pytest.raises(fernet.InvalidToken):
198
+        encryption.decrypt(enc_data, passphrase2, salt2)
199
+    capture.check(('pegleg.engine.util.encryption', 'ERROR',
200
+                   ('Signature verification to decrypt secrets failed. '
201
+                    'Please check your provided passphrase and salt and '
202
+                    'try again.')))

+ 26
- 0
tests/unit/test_exceptions.py View File

@@ -0,0 +1,26 @@
1
+# Licensed under the Apache License, Version 2.0 (the "License");
2
+# you may not use this file except in compliance with the License.
3
+# You may obtain a copy of the License at
4
+#
5
+#     http://www.apache.org/licenses/LICENSE-2.0
6
+#
7
+# Unless required by applicable law or agreed to in writing, software
8
+# distributed under the License is distributed on an "AS IS" BASIS,
9
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+# See the License for the specific language governing permissions and
11
+# limitations under the License.
12
+
13
+import logging
14
+
15
+import pytest
16
+from testfixtures import log_capture
17
+
18
+from pegleg.engine import exceptions as exc
19
+
20
+
21
+@log_capture()
22
+def test_exception_with_missing_kwargs(capture):
23
+    message = 'Testing missing kwargs exception with {text}'
24
+    with pytest.raises(exc.PeglegBaseException):
25
+        raise exc.PeglegBaseException(message=message, key="value")
26
+    capture.check(('pegleg.engine.exceptions', 'WARNING', 'Missing kwargs'))

+ 1
- 1
tox.ini View File

@@ -60,7 +60,7 @@ commands =
60 60
   {toxinidir}/tools/install-cfssl.sh
61 61
   bash -c 'PATH=$PATH:~/.local/bin; pytest --cov=pegleg --cov-report \
62 62
       html:cover --cov-report xml:cover/coverage.xml --cov-report term \
63
-      --cov-fail-under 84 tests/'
63
+      --cov-fail-under 86 tests/'
64 64
 whitelist_externals =
65 65
   bash
66 66
 

Loading…
Cancel
Save