From 4522fae4bb5ebe678fdc0e5f38f86efddee0d738 Mon Sep 17 00:00:00 2001 From: Jose Corella Date: Fri, 27 Mar 2026 11:21:27 -0700 Subject: [PATCH 1/6] test: add shared materials in clients test --- test/functional/test_f_commitment.py | 30 ++++++++++++++++++++++++++++ tox.ini | 14 ++++++------- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/test/functional/test_f_commitment.py b/test/functional/test_f_commitment.py index fdfe281ae..35f678894 100644 --- a/test/functional/test_f_commitment.py +++ b/test/functional/test_f_commitment.py @@ -225,3 +225,33 @@ def test_encrypt_with_uncommitting_algorithm_require_decrypt(): with pytest.raises(ActionNotAllowedError) as excinfo: decrypting_client.decrypt(source=ciphertext, key_provider=key_provider) excinfo.match("Configuration conflict. Cannot decrypt due to .* requiring only committed messages") + + +def test_encrypt_with_different_kc_clients_sharing_materials_yield_error(): + """Tests that when two different client configured with CommitmentPolicy REQUIRE_ENCRYPT_REQUIRE_DECRYPT + and FORBID_ENCRYPT_ALLOW_DECRYPT share encryption materials client errors out due to conflicting commitment policies.""" + forbid_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT + ) + required_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT + ) + + provider = StaticRawMasterKeyProvider( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + encryption_key_type=EncryptionKeyType.SYMMETRIC, + key_bytes=b"\00" * 32, + ) + provider.add_master_key("KeyId") + cache = aws_encryption_sdk.LocalCryptoMaterialsCache(capacity=10) + ccmm = aws_encryption_sdk.CachingCryptoMaterialsManager( + master_key_provider=provider, cache=cache, max_age=3600.0, max_messages_encrypted=5 + ) + plaintext = b"Yellow Submarine" + + ciphertext, _ = forbid_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) + ciphertext2, _ = required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) + with pytest.raises(ActionNotAllowedError) as excinfo: + required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) + excinfo.match("Configuration conflict. Cannot encrypt due to .* requiring only committed messages") + diff --git a/tox.ini b/tox.ini index 130737f86..928d0b23e 100644 --- a/tox.ini +++ b/tox.ini @@ -63,19 +63,19 @@ commands = pytest --basetemp={envtmpdir} -l {posargs} [testenv] passenv = # Identifies AWS KMS key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID, \ # Identifies a second AWS KMS key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2 \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2, \ # Identifies AWS KMS MRK key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1 \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1, \ # Identifies a related AWS KMS MRK key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2 \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2, \ # Pass through AWS credentials - AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \ + AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, \ # AWS Role access in CodeBuild is via the contaner URI - AWS_CONTAINER_CREDENTIALS_RELATIVE_URI \ + AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, \ # Pass through AWS profile name (useful for local testing) - AWS_PROFILE \ + AWS_PROFILE, \ # Pass through custom pip config file settings PIP_CONFIG_FILE sitepackages = False From 4734c5612dedf18ba9db40cf0dc56fc46fbbd8f6 Mon Sep 17 00:00:00 2001 From: Jose Corella Date: Fri, 27 Mar 2026 12:32:14 -0700 Subject: [PATCH 2/6] fix: validate encryption materials from cmm are compatible with commitment policy --- src/aws_encryption_sdk/streaming_client.py | 2 ++ test/functional/test_f_commitment.py | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/aws_encryption_sdk/streaming_client.py b/src/aws_encryption_sdk/streaming_client.py index 0eb5670b4..c2411a716 100644 --- a/src/aws_encryption_sdk/streaming_client.py +++ b/src/aws_encryption_sdk/streaming_client.py @@ -553,6 +553,8 @@ def _prep_message(self): request=encryption_materials_request ) + validate_commitment_policy_on_encrypt(self.config.commitment_policy, self._encryption_materials.algorithm) + if self.config.algorithm is not None and self._encryption_materials.algorithm != self.config.algorithm: raise ActionNotAllowedError( ( diff --git a/test/functional/test_f_commitment.py b/test/functional/test_f_commitment.py index 35f678894..e47201200 100644 --- a/test/functional/test_f_commitment.py +++ b/test/functional/test_f_commitment.py @@ -234,7 +234,7 @@ def test_encrypt_with_different_kc_clients_sharing_materials_yield_error(): commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT ) required_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( - commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) provider = StaticRawMasterKeyProvider( @@ -250,7 +250,6 @@ def test_encrypt_with_different_kc_clients_sharing_materials_yield_error(): plaintext = b"Yellow Submarine" ciphertext, _ = forbid_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) - ciphertext2, _ = required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) with pytest.raises(ActionNotAllowedError) as excinfo: required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) excinfo.match("Configuration conflict. Cannot encrypt due to .* requiring only committed messages") From 27d38e9397fc65143324bb3861aaa9da40b61c22 Mon Sep 17 00:00:00 2001 From: Jose Corella Date: Fri, 27 Mar 2026 14:52:53 -0700 Subject: [PATCH 3/6] remove commas on passenv variables --- tox.ini | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tox.ini b/tox.ini index 928d0b23e..130737f86 100644 --- a/tox.ini +++ b/tox.ini @@ -63,19 +63,19 @@ commands = pytest --basetemp={envtmpdir} -l {posargs} [testenv] passenv = # Identifies AWS KMS key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID, \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID \ # Identifies a second AWS KMS key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2, \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2 \ # Identifies AWS KMS MRK key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1, \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1 \ # Identifies a related AWS KMS MRK key id to use in integration tests - AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2, \ + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2 \ # Pass through AWS credentials - AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, \ + AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \ # AWS Role access in CodeBuild is via the contaner URI - AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, \ + AWS_CONTAINER_CREDENTIALS_RELATIVE_URI \ # Pass through AWS profile name (useful for local testing) - AWS_PROFILE, \ + AWS_PROFILE \ # Pass through custom pip config file settings PIP_CONFIG_FILE sitepackages = False From 2c6bd076976d7c87d100c0c5f17b9a971e356468 Mon Sep 17 00:00:00 2001 From: Jose Corella Date: Tue, 31 Mar 2026 13:19:46 -0700 Subject: [PATCH 4/6] add vice versa test --- test/functional/test_f_commitment.py | 33 +++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/test/functional/test_f_commitment.py b/test/functional/test_f_commitment.py index e47201200..d6defd242 100644 --- a/test/functional/test_f_commitment.py +++ b/test/functional/test_f_commitment.py @@ -227,9 +227,9 @@ def test_encrypt_with_uncommitting_algorithm_require_decrypt(): excinfo.match("Configuration conflict. Cannot decrypt due to .* requiring only committed messages") -def test_encrypt_with_different_kc_clients_sharing_materials_yield_error(): - """Tests that when two different client configured with CommitmentPolicy REQUIRE_ENCRYPT_REQUIRE_DECRYPT - and FORBID_ENCRYPT_ALLOW_DECRYPT share encryption materials client errors out due to conflicting commitment policies.""" +def test_encrypt_with_require_policy_fail_when_retrieving_invalid_cmm_materials(): + """Tests that when a client with a require policy shares a cache with a client with a forbid policy + an error gets thrown due to invalid materials retrieved from cmm""" forbid_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT ) @@ -254,3 +254,30 @@ def test_encrypt_with_different_kc_clients_sharing_materials_yield_error(): required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) excinfo.match("Configuration conflict. Cannot encrypt due to .* requiring only committed messages") + +def test_encrypt_with_forbid_policy_fail_when_retrieving_invalid_cmm_materials(): + """Tests that when a client with a forbid policy shares a cache with a client with a require policy + an error gets thrown due to invalid materials retrieved from cmm""" + forbid_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT + ) + required_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + provider = StaticRawMasterKeyProvider( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + encryption_key_type=EncryptionKeyType.SYMMETRIC, + key_bytes=b"\00" * 32, + ) + provider.add_master_key("KeyId") + cache = aws_encryption_sdk.LocalCryptoMaterialsCache(capacity=10) + ccmm = aws_encryption_sdk.CachingCryptoMaterialsManager( + master_key_provider=provider, cache=cache, max_age=3600.0, max_messages_encrypted=5 + ) + plaintext = b"Yellow Submarine" + + ciphertext, _ = required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) + with pytest.raises(ActionNotAllowedError) as excinfo: + forbid_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) + excinfo.match("Configuration conflict. Cannot encrypt due to .* requiring only non-committed messages.") From 12e9082f6df2dd1f5db4a4ca70688605d4bf550f Mon Sep 17 00:00:00 2001 From: Jose Corella Date: Fri, 17 Apr 2026 13:52:56 -0700 Subject: [PATCH 5/6] fix static analysis tests --- test/functional/test_f_commitment.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/test_f_commitment.py b/test/functional/test_f_commitment.py index d6defd242..387effacf 100644 --- a/test/functional/test_f_commitment.py +++ b/test/functional/test_f_commitment.py @@ -236,7 +236,7 @@ def test_encrypt_with_require_policy_fail_when_retrieving_invalid_cmm_materials( required_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) - + provider = StaticRawMasterKeyProvider( wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, encryption_key_type=EncryptionKeyType.SYMMETRIC, @@ -249,7 +249,7 @@ def test_encrypt_with_require_policy_fail_when_retrieving_invalid_cmm_materials( ) plaintext = b"Yellow Submarine" - ciphertext, _ = forbid_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) + _, _ = forbid_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) with pytest.raises(ActionNotAllowedError) as excinfo: required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) excinfo.match("Configuration conflict. Cannot encrypt due to .* requiring only committed messages") @@ -264,7 +264,7 @@ def test_encrypt_with_forbid_policy_fail_when_retrieving_invalid_cmm_materials() required_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) - + provider = StaticRawMasterKeyProvider( wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, encryption_key_type=EncryptionKeyType.SYMMETRIC, @@ -277,7 +277,7 @@ def test_encrypt_with_forbid_policy_fail_when_retrieving_invalid_cmm_materials() ) plaintext = b"Yellow Submarine" - ciphertext, _ = required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) + _, _ = required_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) with pytest.raises(ActionNotAllowedError) as excinfo: forbid_encrypting_client.encrypt(source=plaintext, materials_manager=ccmm) excinfo.match("Configuration conflict. Cannot encrypt due to .* requiring only non-committed messages.") From e95d8abceb5d39abf28c2e9f108d68fb60f2614e Mon Sep 17 00:00:00 2001 From: Jose Corella Date: Fri, 17 Apr 2026 13:57:05 -0700 Subject: [PATCH 6/6] fix static analysis --- test/functional/test_f_commitment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/test_f_commitment.py b/test/functional/test_f_commitment.py index 387effacf..f6078197c 100644 --- a/test/functional/test_f_commitment.py +++ b/test/functional/test_f_commitment.py @@ -236,7 +236,7 @@ def test_encrypt_with_require_policy_fail_when_retrieving_invalid_cmm_materials( required_encrypting_client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) - + provider = StaticRawMasterKeyProvider( wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, encryption_key_type=EncryptionKeyType.SYMMETRIC,