Skip to content

Commit

Permalink
Use CRT for cloudtrail verify query results
Browse files Browse the repository at this point in the history
This commit makes two changes that were difficult to make
separately due to a change in the interface of signing and verifying
with public and private keys.

First, it migrates all remaining use of cryptography to CRT for the
CloudTrail verify query results.

Second, the existing test cases relied on utilities from the
cryptography package to create a temporary public key from a given
private key file. This has been refactored to move the public key to a
DER-encoded PKCS1 file that is similarly read in and used directly
through the utility module  `PublicPrivateKeyLoader`. A DER-encoded file
was chosen because it is the format used in the API, and it could easily
be read in directly without other cryptographic file manipulation. The
`PublicPrivateKeyLoader` class is now used in the CloudTrail log
validation tests to keep them as similar as possible.

I left the data files separately for each test suite (unit and
functional), even though they are identical since there was no
preexisting structure for sharing data files across the test suites.
This entailed duplicating the helper file loading functions as well,
since they relied on the test module directory at import time.
  • Loading branch information
kdaily committed Nov 27, 2024
1 parent 09010c4 commit 71472d3
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 129 deletions.
28 changes: 11 additions & 17 deletions awscli/customizations/cloudtrail/verifyqueryresults.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@
from abc import ABC, abstractmethod
from os import path

import cryptography
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
from cryptography.hazmat.primitives.serialization import load_der_public_key
from awscli.customizations.exceptions import ParamValidationError

from awscrt.crypto import RSA, RSASignatureAlgorithm

from awscli.customizations.commands import BasicCommand
from awscli.customizations.cloudtrail.utils import parse_date, PublicKeyProvider

Expand Down Expand Up @@ -64,17 +61,14 @@ def validate(self, public_key_base64, sign_file):
:param sign_file: Dict of sign file data returned when JSON
decoding a manifest.
"""
try:
public_key = self._load_public_key(public_key_base64)
signature_bytes = binascii.unhexlify(sign_file["hashSignature"])
hashing = hashes.SHA256()
public_key.verify(
signature_bytes,
self._create_string_to_sign(sign_file),
PKCS1v15(),
hashing,
)
except cryptography.exceptions.InvalidSignature:
public_key = self._load_public_key(public_key_base64)
signature_bytes = binascii.unhexlify(sign_file["hashSignature"])
result = public_key.verify(
signature_algorithm=RSASignatureAlgorithm.PKCS1_5_SHA256,
digest=hashlib.sha256(self._create_string_to_sign(sign_file)).digest(),
signature=signature_bytes
)
if not result:
raise ValidationError("Invalid signature in sign file")

def _create_string_to_sign(self, sign_file):
Expand All @@ -88,7 +82,7 @@ def _create_string_to_sign(self, sign_file):
def _load_public_key(self, public_key_base64):
try:
decoded_key = base64.b64decode(public_key_base64)
return load_der_public_key(decoded_key, default_backend())
return RSA.new_public_key_from_der_data(decoded_key)
except ValueError:
raise ValidationError(
f"Sign file invalid, unable to load PKCS #1 key: {public_key_base64}"
Expand Down
17 changes: 8 additions & 9 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@
import botocore.validate
from botocore.exceptions import ClientError, WaiterError

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import Encoding, \
PublicFormat, load_pem_private_key
from awscrt.crypto import RSA

import prompt_toolkit
import prompt_toolkit.buffer
Expand Down Expand Up @@ -688,14 +686,15 @@ def _wait_for_key(self, bucket_name, key_name, extra_params=None,
waiter.wait(**params)

class PublicPrivateKeyLoader:
def load_private_key_and_generate_public_key(private_key_path):
def load_private_key_and_public_key(private_key_path, public_key_path):
with open(private_key_path, 'rb') as f:
private_key_byte_input = f.read()

private_key = load_pem_private_key(private_key_byte_input, None,
default_backend())
public_key = private_key.public_key()
pub_bytes = public_key.public_bytes(Encoding.DER, PublicFormat.PKCS1)
public_key_b64 = base64.b64encode(pub_bytes)
private_key = RSA.new_private_key_from_pem_data(private_key_byte_input)

with open(public_key_path, 'rb') as f:
public_key_byte_input = f.read()

public_key_b64 = base64.b64encode(public_key_byte_input)

return public_key_b64, private_key
17 changes: 17 additions & 0 deletions tests/functional/cloudtrail/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,20 @@
# distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

import os

def get_private_key_path():
return os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"test_resource",
"sample_private_key.pem",
)


def get_public_key_path():
return os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"test_resource",
"sample_public_key.der",
)
32 changes: 25 additions & 7 deletions tests/functional/cloudtrail/test_resource/sample_private_key.pem
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
Binary file not shown.
47 changes: 25 additions & 22 deletions tests/functional/cloudtrail/test_verifyqueryresults.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import json
import binascii
import copy
import hashlib
import os

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
from awscrt.crypto import RSASignatureAlgorithm

from awscli.testutils import BaseAWSCommandParamsTest
from tests import PublicPrivateKeyLoader
from . import get_private_key_path, get_public_key_path

SAMPLE_PUBLIC_KEY_FINGERPRINT = "67b9fa73676d86966b449dd677850753"
SAMPLE_PUBLIC_KEY = (
Expand Down Expand Up @@ -38,26 +39,20 @@
SAMPLE_S3_EXPORT_FILE_PREFIX = "lake-export-prefix/"


def get_private_key_path():
return os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"test_resource",
"sample_private_key.pem",
)


class TestVerifyQueryResults(BaseAWSCommandParamsTest):
def test_get_file_form_s3_happy_case(self):
(
public_key,
private_key,
) = PublicPrivateKeyLoader.load_private_key_and_generate_public_key(
get_private_key_path()
) = PublicPrivateKeyLoader.load_private_key_and_public_key(
get_private_key_path(),
get_public_key_path()
)

sign_file = copy.deepcopy(SAMPLE_SIGNING_FILE)
signature = private_key.sign(
SAMPLE_HASH_VALUE.encode(), PKCS1v15(), hashes.SHA256()
signature_algorithm=RSASignatureAlgorithm.PKCS1_5_SHA256,
digest=hashlib.sha256(SAMPLE_HASH_VALUE.encode()).digest()
)
sign_file["hashSignature"] = binascii.hexlify(signature).decode()

Expand Down Expand Up @@ -92,10 +87,15 @@ def test_get_file_form_s3_invalid_signature(self):
(
public_key,
private_key,
) = PublicPrivateKeyLoader.load_private_key_and_generate_public_key(
get_private_key_path()
) = PublicPrivateKeyLoader.load_private_key_and_public_key(
get_private_key_path(),
get_public_key_path()
)
signature = private_key.sign(
signature_algorithm=RSASignatureAlgorithm.PKCS1_5_SHA256,
digest=hashlib.sha256("123".encode()).digest()
)
signature = private_key.sign(b"123", PKCS1v15(), hashes.SHA256())

sign_file["hashSignature"] = binascii.hexlify(signature).decode()

self.parsed_responses = [
Expand All @@ -114,9 +114,10 @@ def test_get_file_form_s3_invalid_signature(self):
def test_get_file_form_s3_invalid_sign_file(self):
(
public_key,
private_key,
) = PublicPrivateKeyLoader.load_private_key_and_generate_public_key(
get_private_key_path()
_,
) = PublicPrivateKeyLoader.load_private_key_and_public_key(
get_private_key_path(),
get_public_key_path()
)
self.parsed_responses = [
{"Body": BytesIO(b"123")},
Expand Down Expand Up @@ -161,11 +162,13 @@ def test_get_file_form_s3_incorrect_hash_value(self):
(
public_key,
private_key,
) = PublicPrivateKeyLoader.load_private_key_and_generate_public_key(
get_private_key_path()
) = PublicPrivateKeyLoader.load_private_key_and_public_key(
get_private_key_path(),
get_public_key_path()
)
signature = private_key.sign(
SAMPLE_HASH_VALUE.encode(), PKCS1v15(), hashes.SHA256()
signature_algorithm=RSASignatureAlgorithm.PKCS1_5_SHA256,
digest=hashlib.sha256(SAMPLE_HASH_VALUE.encode()).digest()
)
sign_file["hashSignature"] = binascii.hexlify(signature).decode()

Expand Down
17 changes: 17 additions & 0 deletions tests/unit/customizations/cloudtrail/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,20 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

import os

def get_private_key_path():
return os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"test_resource",
"sample_private_key.pem",
)


def get_public_key_path():
return os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"test_resource",
"sample_public_key.der",
)
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
Binary file not shown.
61 changes: 11 additions & 50 deletions tests/unit/customizations/cloudtrail/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from dateutil import parser, tz
from argparse import Namespace

from awscrt.crypto import RSA, RSASignatureAlgorithm
from awscrt.crypto import RSASignatureAlgorithm

from awscli.testutils import mock, BaseAWSCommandParamsTest
from awscli.customizations.cloudtrail.validation import DigestError, \
Expand All @@ -32,6 +32,8 @@
from awscli.customizations.exceptions import ParamValidationError
from awscli.compat import BytesIO
from botocore.exceptions import ClientError
from tests import PublicPrivateKeyLoader
from . import get_private_key_path, get_public_key_path

START_DATE = parser.parse('20140810T000000Z')
END_DATE = parser.parse('20150810T000000Z')
Expand Down Expand Up @@ -346,50 +348,6 @@ def test_creates_traverser_organization_trail_missing_account_id(self):


class TestSha256RSADigestValidator(unittest.TestCase):
private_key_bytes = (
b"-----BEGIN RSA PRIVATE KEY-----\n"
b"MIIEowIBAAKCAQEAsVYkrQG55kbh2HTOhdAYK8S/y3SPWiC0c3wqBxcOFXxP7lAc\n"
b"a7i6JhMbEa/PepPew+b6tDGQeOHapuaz47Ic2cDHclxjS+lO1zlfGTzr97K9Yggb\n"
b"qLOsPiqrBBioFKs9vOOXaoL5hcmtdScvgjXxm1DDid4w4KC9w7NLYBocAN03Ve5E\n"
b"AyfahDqI+l4HdoGdjIuDqeI2T2DRiM8/IBPgirkgH6oOsMgIqEZOYYUny4o8c/09\n"
b"KoqAIYfbWFLoaj/ISLnegveN75tIjg06DX4/NfUFnqQs4TeGr7YQPa4Y363YGCqG\n"
b"inO8Y05SexctpstsAnjaiGXPYee2qqr+SxyyoQIDAQABAoIBABMkOz05bHmAuSwG\n"
b"H6yt84315MXvRPHzicbVZivxvyFuk6ojl43BGMa3VTqpgXm3sFnw+qqslu2VY2aU\n"
b"jGJNfXO7rUuY0VcGTe5JUQyGWOoZrvt/6IxjKHplXKRKjQn+GeHjpxpmHMzmIgT9\n"
b"P9GMRRIAu7qL8zar4w/WsJIk/1TQXeo+5wSBi1amg9eqIFPKPAkHT5jNvLp057Oc\n"
b"aL4WhazFCVdm2ot8hS9h2j4YpcIaIwiIiGG0fKpO8W7UIFmr9vYAYJMqyrpSkHDW\n"
b"9KNKrWfNsetXDHtqH3WAfw9dg9YnNAvsarkJL1ADtT3Iy39U80ParA3cI3uspV33\n"
b"UEkqjKkCgYEAx5nX3OlkbJHhYBf7qPFRn2di5IQLTCTFb+NwiYHUey8hD7lZrujJ\n"
b"qJN7YYA64VS4DMjRWDp7TFfKr0reBNcS7Fa/M6BnMpX9ljwK7zXpaWHMgKXLYv9P\n"
b"wWCfJJFH43s6i2WaOmkTnTMQyUa2/reNfcTMo+Nd7Gu6q5zUKZpn/KMCgYEA43HM\n"
b"YxGjAof1VT7Pzfwn9xQsb1/WkdvNBt2aewvtLvSTI2tNC/SctqYEaCQii47IKDCB\n"
b"xgYaaE40UK8XjSnIKKq2CFdVAsqyFFdjAgVr2CCfKBLwrgAQoe4IWjMAQdp1+Gi4\n"
b"u68qschE339JDGfhHuwIbQ2umKLv2KgyPBnEo+sCgYBsgzG8stHayHA7Wq6BSThz\n"
b"rbQwwayWp8MCsiZjS0bl9VhHASBFm97OG+fOuPTJvdIVeTN+gMS5W10gcVZEUVzD\n"
b"SeHGwmR4NtzXSSs0ox2TIg0Yv4nT9zM30TyTl7v6ausID6OKL8fvBW0Rz7T6w3VT\n"
b"s6MBUkGkn2irlaYuO/heewKBgHvKtmm9cbGw+jC5jTUZ506tpjnAOfMNZRw1hR0v\n"
b"spp595OxlS/KpXksBv3/nOXEguCM9jUnoTvgRM0dX34vnYe00nrbvaNVW3OC1JqH\n"
b"BNmPd9DB7klmM6dO/TDKzXsKQmc/6DwO7Pfyfrn+d23PJFJGOZfReJQPKugLM7xO\n"
b"ch6dAoGBAJQe65Bvb271syTg9NDEqwMXeHM9j/q3g4ZVX0anwfD3gdDuJlmHyVB1\n"
b"d5tmx0P8ReLYPS79A1/tgrZ8wesL4d1o2wyOk6kGr5qpJvXRqk6gdIr2+OZbgpjv\n"
b"YE9cpgRbz4SuadWd4cqB790g/I720b46OO0BhImG+vbTFZaEo349\n"
b"-----END RSA PRIVATE KEY-----\n"
)

public_key_der_bytes = (
b"0\x82\x01\n\x02\x82\x01\x01\x00\xb1V$\xad\x01\xb9\xe6F\xe1\xd8t\xce"
b"\x85\xd0\x18+\xc4\xbf\xcbt\x8fZ \xb4s|*\x07\x17\x0e\x15|O\xeeP\x1ck"
b"\xb8\xba&\x13\x1b\x11\xaf\xcfz\x93\xde\xc3\xe6\xfa\xb41\x90x\xe1\xda"
b"\xa6\xe6\xb3\xe3\xb2\x1c\xd9\xc0\xc7r\\cK\xe9N\xd79_\x19<\xeb\xf7\xb2"
b"\xbdb\x08\x1b\xa8\xb3\xac>*\xab\x04\x18\xa8\x14\xab=\xbc\xe3\x97j\x82"
b"\xf9\x85\xc9\xadu'/\x825\xf1\x9bP\xc3\x89\xde0\xe0\xa0\xbd\xc3\xb3K`"
b"\x1a\x1c\x00\xdd7U\xeeD\x03'\xda\x84:\x88\xfa^\x07v\x81\x9d\x8c\x8b\x83"
b"\xa9\xe26O`\xd1\x88\xcf? \x13\xe0\x8a\xb9 \x1f\xaa\x0e\xb0\xc8\x08\xa8FNa"
b"\x85'\xcb\x8a<s\xfd=*\x8a\x80!\x87\xdbXR\xe8j?\xc8H\xb9\xde\x82\xf7\x8d"
b"\xef\x9bH\x8e\r:\r~?5\xf5\x05\x9e\xa4,\xe17\x86\xaf\xb6\x10=\xae\x18\xdf"
b"\xad\xd8\x18*\x86\x8as\xbccNR{\x17-\xa6\xcbl\x02x\xda\x88e\xcfa\xe7\xb6"
b"\xaa\xaa\xfeK\x1c\xb2\xa1\x02\x03\x01\x00\x01"
)
def setUp(self):
self._digest_data = {'digestStartTime': 'baz',
'digestEndTime': 'foo',
Expand All @@ -402,8 +360,13 @@ def setUp(self):
self._digest_data['_signature'] = 'aeff'

def test_validates_digests(self):
private_key = RSA.new_private_key_from_pem_data(self.private_key_bytes)

(
public_key,
private_key,
) = PublicPrivateKeyLoader.load_private_key_and_public_key(
get_private_key_path(),
get_public_key_path()
)
sha256_hash = hashlib.sha256(self._inflated_digest)
string_to_sign = "%s\n%s/%s\n%s\n%s" % (
self._digest_data['digestEndTime'],
Expand All @@ -412,16 +375,14 @@ def test_validates_digests(self):
sha256_hash.hexdigest(),
self._digest_data['previousDigestSignature'])
to_sign = string_to_sign.encode()

signature = private_key.sign(
signature_algorithm=RSASignatureAlgorithm.PKCS1_5_SHA256,
digest=hashlib.sha256(to_sign).digest()
)

self._digest_data['_signature'] = binascii.hexlify(signature)
validator = Sha256RSADigestValidator()
public_key_b64 = base64.b64encode(self.public_key_der_bytes)
validator.validate('b', 'k', public_key_b64, self._digest_data,
validator.validate('b', 'k', public_key, self._digest_data,
self._inflated_digest)

def test_does_not_expose_underlying_key_decoding_error(self):
Expand Down
Loading

0 comments on commit 71472d3

Please sign in to comment.