From 635e449b9e958472b58b95573d58dbf5189f5890 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Thu, 15 May 2025 21:30:36 +0200 Subject: [PATCH 01/22] feat: implement kms re-encrypt operation test: first re-encrypt integration test --- .../localstack/services/kms/provider.py | 27 ++++++++++++- tests/aws/services/kms/test_kms.py | 40 +++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/localstack-core/localstack/services/kms/provider.py b/localstack-core/localstack/services/kms/provider.py index 9f29780fa2103..4f11986462e19 100644 --- a/localstack-core/localstack/services/kms/provider.py +++ b/localstack-core/localstack/services/kms/provider.py @@ -954,8 +954,31 @@ def re_encrypt( dry_run: NullableBooleanType = None, **kwargs, ) -> ReEncryptResponse: - # TODO: when implementing, ensure cross-account support for source_key_id and destination_key_id - raise NotImplementedError + decrypt_response = self.decrypt( + context=context, + ciphertext_blob=ciphertext_blob, + encryption_context=source_encryption_context, + encryption_algorithm=source_encryption_algorithm, + key_id=source_key_id, + grant_tokens=grant_tokens + ) + + encrypt_response = self.encrypt( + context=context, + encryption_context=destination_encryption_context, + key_id=destination_key_id, + plaintext=decrypt_response["Plaintext"], + grant_tokens=grant_tokens, + dry_run=dry_run + ) + + return ReEncryptResponse( + CiphertextBlob=encrypt_response["CiphertextBlob"], + Source_key_id=source_key_id, + KeyId=source_key_id, + SourceEncryptionAlgorithm=source_encryption_algorithm, + DestinationEncryptionAlgorithm=destination_encryption_algorithm + ) def encrypt( self, diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 4b68dd9c38dce..5c067fabc3c81 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -871,6 +871,46 @@ def test_encrypt_decrypt(self, kms_create_key, key_spec, algo, aws_client): )["Plaintext"] assert base64.b64decode(plaintext) == message + @pytest.mark.parametrize( + "key_spec,algo", + [ + ("SYMMETRIC_DEFAULT", "SYMMETRIC_DEFAULT"), + ("RSA_2048", "RSAES_OAEP_SHA_256"), + ], + ) + + @markers.aws.only_localstack + def test_re_encript(self, kms_create_key, key_spec, algo, aws_client, snapshot): + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] + destination_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] + message = b"test message 123 !%$@ 1234567890" + ciphertext = aws_client.kms.encrypt( + KeyId=source_key_id, + Plaintext=base64.b64encode(message), + EncryptionAlgorithm=algo + )["CiphertextBlob"] + result = aws_client.kms.re_encrypt( + SourceKeyId=source_key_id, + DestinationKeyId=destination_key_id, + CiphertextBlob=ciphertext, + SourceEncryptionAlgorithm=algo, + DestinationEncryptionAlgorithm=algo + ) + plaintext = aws_client.kms.decrypt( + KeyId=source_key_id, + CiphertextBlob=ciphertext, + EncryptionAlgorithm=algo + )["Plaintext"] + re_plaintext = aws_client.kms.decrypt( + KeyId=destination_key_id, + CiphertextBlob=result["CiphertextBlob"], + EncryptionAlgorithm=algo + )["Plaintext"] + assert base64.b64decode(plaintext) == message + assert base64.b64decode(re_plaintext) == message + + #snapshot.match("invoke", result) + @pytest.mark.parametrize( "key_spec,algo", [ From b5e699c0985ccf35e947b8aaa6710cd183c8195e Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 19 May 2025 10:08:02 +0200 Subject: [PATCH 02/22] test: record snapshot and set the test as aws validated --- tests/aws/services/kms/test_kms.py | 26 +++++++++------ tests/aws/services/kms/test_kms.snapshot.json | 32 +++++++++++++++++++ .../aws/services/kms/test_kms.validation.json | 18 +++++++---- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 5c067fabc3c81..43c6119cd0805 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -879,16 +879,20 @@ def test_encrypt_decrypt(self, kms_create_key, key_spec, algo, aws_client): ], ) - @markers.aws.only_localstack - def test_re_encript(self, kms_create_key, key_spec, algo, aws_client, snapshot): + @markers.aws.validated + def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): + message = b"test message 123 !%$@ 1234567890" source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] destination_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] - message = b"test message 123 !%$@ 1234567890" + + # Encrypt the message using the source key ciphertext = aws_client.kms.encrypt( KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] + + # Re-encrypt the previously encryted message using the destination key result = aws_client.kms.re_encrypt( SourceKeyId=source_key_id, DestinationKeyId=destination_key_id, @@ -896,20 +900,24 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client, snapshot): SourceEncryptionAlgorithm=algo, DestinationEncryptionAlgorithm=algo ) - plaintext = aws_client.kms.decrypt( + + # Decrypt using the source key + source_key_plaintext = aws_client.kms.decrypt( KeyId=source_key_id, CiphertextBlob=ciphertext, EncryptionAlgorithm=algo )["Plaintext"] - re_plaintext = aws_client.kms.decrypt( + + # Decrypt using the destination key + destination_key_plaintext = aws_client.kms.decrypt( KeyId=destination_key_id, CiphertextBlob=result["CiphertextBlob"], EncryptionAlgorithm=algo )["Plaintext"] - assert base64.b64decode(plaintext) == message - assert base64.b64decode(re_plaintext) == message - - #snapshot.match("invoke", result) + + # Both source and destination plain texts should match the original + assert base64.b64decode(source_key_plaintext) == message + assert base64.b64decode(destination_key_plaintext) == message @pytest.mark.parametrize( "key_spec,algo", diff --git a/tests/aws/services/kms/test_kms.snapshot.json b/tests/aws/services/kms/test_kms.snapshot.json index 17ebf79f26bb7..399e8b546d641 100644 --- a/tests/aws/services/kms/test_kms.snapshot.json +++ b/tests/aws/services/kms/test_kms.snapshot.json @@ -2238,5 +2238,37 @@ } } } + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { + "recorded-date": "19-05-2025, 07:54:39", + "recorded-content": { + "test_re_encript": { + "CiphertextBlob": "ciphertext-blob", + "DestinationEncryptionAlgorithm": "SYMMETRIC_DEFAULT", + "KeyId": "", + "SourceEncryptionAlgorithm": "SYMMETRIC_DEFAULT", + "SourceKeyId": "", + "ResponseMetadata": { + "HTTPHeaders": {}, + "HTTPStatusCode": 200 + } + } + } + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[RSA_2048-RSAES_OAEP_SHA_256]": { + "recorded-date": "19-05-2025, 07:54:41", + "recorded-content": { + "test_re_encript": { + "CiphertextBlob": "ciphertext-blob", + "DestinationEncryptionAlgorithm": "RSAES_OAEP_SHA_256", + "KeyId": "", + "SourceEncryptionAlgorithm": "RSAES_OAEP_SHA_256", + "SourceKeyId": "", + "ResponseMetadata": { + "HTTPHeaders": {}, + "HTTPStatusCode": 200 + } + } + } } } diff --git a/tests/aws/services/kms/test_kms.validation.json b/tests/aws/services/kms/test_kms.validation.json index fb082e9a3265d..79ffcf512cbeb 100644 --- a/tests/aws/services/kms/test_kms.validation.json +++ b/tests/aws/services/kms/test_kms.validation.json @@ -200,6 +200,12 @@ "tests/aws/services/kms/test_kms.py::TestKMS::test_plaintext_size_for_encrypt": { "last_validated_date": "2024-04-11T15:54:20+00:00" }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[RSA_2048-RSAES_OAEP_SHA_256]": { + "last_validated_date": "2025-05-19T07:54:40+00:00" + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { + "last_validated_date": "2025-05-19T07:54:39+00:00" + }, "tests/aws/services/kms/test_kms.py::TestKMS::test_replicate_key": { "last_validated_date": "2024-04-11T15:53:44+00:00" }, @@ -323,16 +329,16 @@ "tests/aws/services/kms/test_kms.py::TestKMSGenerateKeys::test_generate_data_key_pair": { "last_validated_date": "2024-04-11T15:54:29+00:00" }, - "tests/aws/services/kms/test_kms.py::TestKMSGenerateKeys::test_generate_data_key_pair_without_plaintext": { - "last_validated_date": "2024-04-11T15:54:28+00:00" - }, - "tests/aws/services/kms/test_kms.py::TestKMSGenerateKeys::test_generate_data_key_without_plaintext": { - "last_validated_date": "2024-04-11T15:54:31+00:00" - }, "tests/aws/services/kms/test_kms.py::TestKMSGenerateKeys::test_generate_data_key_pair_dry_run": { "last_validated_date": "2025-04-06T11:54:20+00:00" }, + "tests/aws/services/kms/test_kms.py::TestKMSGenerateKeys::test_generate_data_key_pair_without_plaintext": { + "last_validated_date": "2024-04-11T15:54:28+00:00" + }, "tests/aws/services/kms/test_kms.py::TestKMSGenerateKeys::test_generate_data_key_pair_without_plaintext_dry_run": { "last_validated_date": "2025-04-13T15:44:57+00:00" + }, + "tests/aws/services/kms/test_kms.py::TestKMSGenerateKeys::test_generate_data_key_without_plaintext": { + "last_validated_date": "2024-04-11T15:54:31+00:00" } } From 3275f2908ef5ca182a2a00638a8e67d64943413c Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 19 May 2025 10:27:01 +0200 Subject: [PATCH 03/22] fix: remove whitelines --- tests/aws/services/kms/test_kms.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 43c6119cd0805..e1c1a6577daba 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -884,14 +884,12 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): message = b"test message 123 !%$@ 1234567890" source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] destination_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] - # Encrypt the message using the source key ciphertext = aws_client.kms.encrypt( KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] - # Re-encrypt the previously encryted message using the destination key result = aws_client.kms.re_encrypt( SourceKeyId=source_key_id, @@ -900,21 +898,18 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): SourceEncryptionAlgorithm=algo, DestinationEncryptionAlgorithm=algo ) - # Decrypt using the source key source_key_plaintext = aws_client.kms.decrypt( KeyId=source_key_id, CiphertextBlob=ciphertext, EncryptionAlgorithm=algo )["Plaintext"] - # Decrypt using the destination key destination_key_plaintext = aws_client.kms.decrypt( KeyId=destination_key_id, CiphertextBlob=result["CiphertextBlob"], EncryptionAlgorithm=algo )["Plaintext"] - # Both source and destination plain texts should match the original assert base64.b64decode(source_key_plaintext) == message assert base64.b64decode(destination_key_plaintext) == message From 6b0d3f96483ce7671404c012ad4ff3bc9daeb6be Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 19 May 2025 10:33:19 +0200 Subject: [PATCH 04/22] fix: remove white space --- localstack-core/localstack/services/kms/provider.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/localstack-core/localstack/services/kms/provider.py b/localstack-core/localstack/services/kms/provider.py index 4f11986462e19..9aac24c7fe47f 100644 --- a/localstack-core/localstack/services/kms/provider.py +++ b/localstack-core/localstack/services/kms/provider.py @@ -957,12 +957,11 @@ def re_encrypt( decrypt_response = self.decrypt( context=context, ciphertext_blob=ciphertext_blob, - encryption_context=source_encryption_context, + encryption_context=source_encryption_context, encryption_algorithm=source_encryption_algorithm, key_id=source_key_id, grant_tokens=grant_tokens ) - encrypt_response = self.encrypt( context=context, encryption_context=destination_encryption_context, @@ -971,7 +970,6 @@ def re_encrypt( grant_tokens=grant_tokens, dry_run=dry_run ) - return ReEncryptResponse( CiphertextBlob=encrypt_response["CiphertextBlob"], Source_key_id=source_key_id, From d69f6ec5a03a1bcb250c8e4c9d0ff7b3ebdea5b0 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 19 May 2025 10:44:18 +0200 Subject: [PATCH 05/22] fix: remove whitespace --- tests/aws/services/kms/test_kms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index e1c1a6577daba..27e1fd69a6c6b 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -913,7 +913,7 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): # Both source and destination plain texts should match the original assert base64.b64decode(source_key_plaintext) == message assert base64.b64decode(destination_key_plaintext) == message - + @pytest.mark.parametrize( "key_spec,algo", [ From cb32a212754f974001a539a21c392cc61c9faae1 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 19 May 2025 10:51:40 +0200 Subject: [PATCH 06/22] fix: linting --- .../localstack/services/kms/provider.py | 6 +++--- tests/aws/services/kms/test_kms.py | 14 ++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/localstack-core/localstack/services/kms/provider.py b/localstack-core/localstack/services/kms/provider.py index 9aac24c7fe47f..0a707f574563c 100644 --- a/localstack-core/localstack/services/kms/provider.py +++ b/localstack-core/localstack/services/kms/provider.py @@ -960,7 +960,7 @@ def re_encrypt( encryption_context=source_encryption_context, encryption_algorithm=source_encryption_algorithm, key_id=source_key_id, - grant_tokens=grant_tokens + grant_tokens=grant_tokens, ) encrypt_response = self.encrypt( context=context, @@ -968,14 +968,14 @@ def re_encrypt( key_id=destination_key_id, plaintext=decrypt_response["Plaintext"], grant_tokens=grant_tokens, - dry_run=dry_run + dry_run=dry_run, ) return ReEncryptResponse( CiphertextBlob=encrypt_response["CiphertextBlob"], Source_key_id=source_key_id, KeyId=source_key_id, SourceEncryptionAlgorithm=source_encryption_algorithm, - DestinationEncryptionAlgorithm=destination_encryption_algorithm + DestinationEncryptionAlgorithm=destination_encryption_algorithm, ) def encrypt( diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 27e1fd69a6c6b..6f55e22b17965 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -885,10 +885,7 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] destination_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] # Encrypt the message using the source key - ciphertext = aws_client.kms.encrypt( - KeyId=source_key_id, - Plaintext=base64.b64encode(message), - EncryptionAlgorithm=algo + ciphertext = aws_client.kms.encrypt(KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] # Re-encrypt the previously encryted message using the destination key result = aws_client.kms.re_encrypt( @@ -896,19 +893,16 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): DestinationKeyId=destination_key_id, CiphertextBlob=ciphertext, SourceEncryptionAlgorithm=algo, - DestinationEncryptionAlgorithm=algo + DestinationEncryptionAlgorithm=algo, ) # Decrypt using the source key - source_key_plaintext = aws_client.kms.decrypt( - KeyId=source_key_id, - CiphertextBlob=ciphertext, - EncryptionAlgorithm=algo + source_key_plaintext = aws_client.kms.decrypt(KeyId=source_key_id, CiphertextBlob=ciphertext, EncryptionAlgorithm=algo )["Plaintext"] # Decrypt using the destination key destination_key_plaintext = aws_client.kms.decrypt( KeyId=destination_key_id, CiphertextBlob=result["CiphertextBlob"], - EncryptionAlgorithm=algo + EncryptionAlgorithm=algo, )["Plaintext"] # Both source and destination plain texts should match the original assert base64.b64decode(source_key_plaintext) == message From 0ff104ace77f57c519592fd73f879435c4e0e828 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 19 May 2025 10:59:22 +0200 Subject: [PATCH 07/22] fix: lint tests --- tests/aws/services/kms/test_kms.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 6f55e22b17965..ff14a408886d1 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -885,7 +885,8 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] destination_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] # Encrypt the message using the source key - ciphertext = aws_client.kms.encrypt(KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo + ciphertext = aws_client.kms.encrypt( + KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] # Re-encrypt the previously encryted message using the destination key result = aws_client.kms.re_encrypt( @@ -896,7 +897,8 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): DestinationEncryptionAlgorithm=algo, ) # Decrypt using the source key - source_key_plaintext = aws_client.kms.decrypt(KeyId=source_key_id, CiphertextBlob=ciphertext, EncryptionAlgorithm=algo + source_key_plaintext = aws_client.kms.decrypt( + KeyId=source_key_id, CiphertextBlob=ciphertext, EncryptionAlgorithm=algo )["Plaintext"] # Decrypt using the destination key destination_key_plaintext = aws_client.kms.decrypt( From 19bd2c12177328f36234af0187e90ee69f432448 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 19 May 2025 11:05:45 +0200 Subject: [PATCH 08/22] fix: lint, remove extra blank line --- tests/aws/services/kms/test_kms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index ff14a408886d1..66a52bad245ba 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -878,7 +878,6 @@ def test_encrypt_decrypt(self, kms_create_key, key_spec, algo, aws_client): ("RSA_2048", "RSAES_OAEP_SHA_256"), ], ) - @markers.aws.validated def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): message = b"test message 123 !%$@ 1234567890" From baa383804ccb5561f851ee98d9f2df69331fbbf0 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Tue, 20 May 2025 15:02:41 +0200 Subject: [PATCH 09/22] fix: parse source and destination keys to retrieve arn --- localstack-core/localstack/services/kms/provider.py | 13 +++++++++++-- tests/aws/services/kms/test_kms.py | 3 ++- tests/aws/services/kms/test_kms.snapshot.json | 12 ++++++------ tests/aws/services/kms/test_kms.validation.json | 6 ++++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/localstack-core/localstack/services/kms/provider.py b/localstack-core/localstack/services/kms/provider.py index 0a707f574563c..9300e1410342e 100644 --- a/localstack-core/localstack/services/kms/provider.py +++ b/localstack-core/localstack/services/kms/provider.py @@ -954,6 +954,11 @@ def re_encrypt( dry_run: NullableBooleanType = None, **kwargs, ) -> ReEncryptResponse: + # TODO: when implementing, ensure cross-account support for source_key_id and destination_key_id + # Parse Source Key to extract metadata + account_id, region_name, source_key_id = self._parse_key_id(source_key_id, context) + source_key = self._get_kms_key(account_id, region_name, source_key_id) + # Decrypt using source key decrypt_response = self.decrypt( context=context, ciphertext_blob=ciphertext_blob, @@ -962,6 +967,10 @@ def re_encrypt( key_id=source_key_id, grant_tokens=grant_tokens, ) + # Parse Destination Key to extract metadata + account_id, region_name, destination_key_id = self._parse_key_id(destination_key_id, context) + destination_key = self._get_kms_key(account_id, region_name, destination_key_id) + # Encrypt using destination key encrypt_response = self.encrypt( context=context, encryption_context=destination_encryption_context, @@ -972,8 +981,8 @@ def re_encrypt( ) return ReEncryptResponse( CiphertextBlob=encrypt_response["CiphertextBlob"], - Source_key_id=source_key_id, - KeyId=source_key_id, + SourceKeyId=source_key.metadata.get("Arn"), + KeyId=destination_key.metadata.get("Arn"), SourceEncryptionAlgorithm=source_encryption_algorithm, DestinationEncryptionAlgorithm=destination_encryption_algorithm, ) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 66a52bad245ba..cd1e52de73625 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -879,7 +879,7 @@ def test_encrypt_decrypt(self, kms_create_key, key_spec, algo, aws_client): ], ) @markers.aws.validated - def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): + def test_re_encrypt(self, kms_create_key, key_spec, algo, aws_client, snapshot): message = b"test message 123 !%$@ 1234567890" source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] destination_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=key_spec)["KeyId"] @@ -895,6 +895,7 @@ def test_re_encript(self, kms_create_key, key_spec, algo, aws_client): SourceEncryptionAlgorithm=algo, DestinationEncryptionAlgorithm=algo, ) + snapshot.match("test_re_encrypt", result) # Decrypt using the source key source_key_plaintext = aws_client.kms.decrypt( KeyId=source_key_id, CiphertextBlob=ciphertext, EncryptionAlgorithm=algo diff --git a/tests/aws/services/kms/test_kms.snapshot.json b/tests/aws/services/kms/test_kms.snapshot.json index 399e8b546d641..f4b7af999806e 100644 --- a/tests/aws/services/kms/test_kms.snapshot.json +++ b/tests/aws/services/kms/test_kms.snapshot.json @@ -2239,10 +2239,10 @@ } } }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { - "recorded-date": "19-05-2025, 07:54:39", + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { + "recorded-date": "20-05-2025, 12:20:30", "recorded-content": { - "test_re_encript": { + "test_re_encrypt": { "CiphertextBlob": "ciphertext-blob", "DestinationEncryptionAlgorithm": "SYMMETRIC_DEFAULT", "KeyId": "", @@ -2255,10 +2255,10 @@ } } }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[RSA_2048-RSAES_OAEP_SHA_256]": { - "recorded-date": "19-05-2025, 07:54:41", + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[RSA_2048-RSAES_OAEP_SHA_256]": { + "recorded-date": "20-05-2025, 12:20:31", "recorded-content": { - "test_re_encript": { + "test_re_encrypt": { "CiphertextBlob": "ciphertext-blob", "DestinationEncryptionAlgorithm": "RSAES_OAEP_SHA_256", "KeyId": "", diff --git a/tests/aws/services/kms/test_kms.validation.json b/tests/aws/services/kms/test_kms.validation.json index 79ffcf512cbeb..45dd46d76a023 100644 --- a/tests/aws/services/kms/test_kms.validation.json +++ b/tests/aws/services/kms/test_kms.validation.json @@ -206,6 +206,12 @@ "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { "last_validated_date": "2025-05-19T07:54:39+00:00" }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[RSA_2048-RSAES_OAEP_SHA_256]": { + "last_validated_date": "2025-05-20T12:20:30+00:00" + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { + "last_validated_date": "2025-05-20T12:20:29+00:00" + }, "tests/aws/services/kms/test_kms.py::TestKMS::test_replicate_key": { "last_validated_date": "2024-04-11T15:53:44+00:00" }, From 12e2edf553c398d088a5b66d2b829142d4991633 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Tue, 20 May 2025 16:26:02 +0200 Subject: [PATCH 10/22] fix: linter --- localstack-core/localstack/services/kms/provider.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/localstack-core/localstack/services/kms/provider.py b/localstack-core/localstack/services/kms/provider.py index 9300e1410342e..7effd20053393 100644 --- a/localstack-core/localstack/services/kms/provider.py +++ b/localstack-core/localstack/services/kms/provider.py @@ -968,7 +968,8 @@ def re_encrypt( grant_tokens=grant_tokens, ) # Parse Destination Key to extract metadata - account_id, region_name, destination_key_id = self._parse_key_id(destination_key_id, context) + account_id, region_name, destination_key_id = self._parse_key_id( + destination_key_id, context) destination_key = self._get_kms_key(account_id, region_name, destination_key_id) # Encrypt using destination key encrypt_response = self.encrypt( From 475fc867ce5d1341e190a429347ae29e7e00b3c2 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Tue, 20 May 2025 16:35:06 +0200 Subject: [PATCH 11/22] fix: lint --- localstack-core/localstack/services/kms/provider.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/localstack-core/localstack/services/kms/provider.py b/localstack-core/localstack/services/kms/provider.py index 7effd20053393..20accf9657c92 100644 --- a/localstack-core/localstack/services/kms/provider.py +++ b/localstack-core/localstack/services/kms/provider.py @@ -969,7 +969,8 @@ def re_encrypt( ) # Parse Destination Key to extract metadata account_id, region_name, destination_key_id = self._parse_key_id( - destination_key_id, context) + destination_key_id, context + ) destination_key = self._get_kms_key(account_id, region_name, destination_key_id) # Encrypt using destination key encrypt_response = self.encrypt( From 3571777a09bc9c0baae0df0d0cd6e8d47335b27d Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Tue, 20 May 2025 16:58:17 +0200 Subject: [PATCH 12/22] chore: update comments --- localstack-core/localstack/services/kms/provider.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/localstack-core/localstack/services/kms/provider.py b/localstack-core/localstack/services/kms/provider.py index 20accf9657c92..cb9838b3352e7 100644 --- a/localstack-core/localstack/services/kms/provider.py +++ b/localstack-core/localstack/services/kms/provider.py @@ -955,7 +955,7 @@ def re_encrypt( **kwargs, ) -> ReEncryptResponse: # TODO: when implementing, ensure cross-account support for source_key_id and destination_key_id - # Parse Source Key to extract metadata + # Parse and fetch source Key account_id, region_name, source_key_id = self._parse_key_id(source_key_id, context) source_key = self._get_kms_key(account_id, region_name, source_key_id) # Decrypt using source key @@ -967,7 +967,7 @@ def re_encrypt( key_id=source_key_id, grant_tokens=grant_tokens, ) - # Parse Destination Key to extract metadata + # Parse and fetch destination key account_id, region_name, destination_key_id = self._parse_key_id( destination_key_id, context ) From 3285936611b8e473f47a89faf512e4b47b4210ed Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Wed, 21 May 2025 14:49:11 +0200 Subject: [PATCH 13/22] test: add tests to verify that an exception is raised when an invalid source/destination keys are provided --- tests/aws/services/kms/test_kms.py | 59 ++++++++++++++++++- tests/aws/services/kms/test_kms.snapshot.json | 36 ++++++++++- .../aws/services/kms/test_kms.validation.json | 16 ++--- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index cd1e52de73625..ccc953c1ae1c4 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -910,6 +910,63 @@ def test_re_encrypt(self, kms_create_key, key_spec, algo, aws_client, snapshot): assert base64.b64decode(source_key_plaintext) == message assert base64.b64decode(destination_key_plaintext) == message + @pytest.mark.parametrize( + "algo", + [ + ("SYMMETRIC_DEFAULT"), + ], + ) + @markers.aws.validated + def test_re_encrypt_incorrect_source_key(self, kms_create_key, algo, aws_client, snapshot): + message = b"test message 123 !%$@ 1234567890" + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")["KeyId"] + ciphertext = aws_client.kms.encrypt( + KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo + )["CiphertextBlob"] + invalid_key_id = kms_create_key( + Description="test hmac key", + KeySpec="HMAC_224", + KeyUsage="GENERATE_VERIFY_MAC", + )["KeyId"] + + with pytest.raises(ClientError) as exc: + aws_client.kms.re_encrypt( + SourceKeyId=invalid_key_id, + DestinationKeyId=invalid_key_id, + CiphertextBlob=ciphertext, + SourceEncryptionAlgorithm=algo, + DestinationEncryptionAlgorithm=algo, + ) + snapshot.match("incorrect-source-key", exc.value.response) + assert exc.match("IncorrectKeyException") + + @pytest.mark.parametrize( + "algo", + [ + ("SYMMETRIC_DEFAULT"), + ], + ) + @markers.aws.validated + def test_re_encrypt_invalid_destination_key(self, kms_create_key, algo, aws_client, snapshot): + message = b"test message 123 !%$@ 1234567890" + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")["KeyId"] + ciphertext = aws_client.kms.encrypt( + KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo + )["CiphertextBlob"] + invalid_key_id = kms_create_key(KeyUsage="SIGN_VERIFY", KeySpec="ECC_NIST_P256")["KeyId"] + with pytest.raises(ClientError) as exc: + aws_client.kms.re_encrypt( + SourceKeyId=source_key_id, + DestinationKeyId=invalid_key_id, + CiphertextBlob=ciphertext, + SourceEncryptionAlgorithm=algo, + DestinationEncryptionAlgorithm=algo, + ) + # TODO: Determine where 'context.operation.name' is being set to 'ReEncryptTo' as the expected AWS operation name is 'ReEncrypt' + # Then enable the snapshot check + #snapshot.match("invalid-destination-key-usage", exc.value.response) + assert exc.match("InvalidKeyUsageException") + @pytest.mark.parametrize( "key_spec,algo", [ @@ -1920,7 +1977,7 @@ def test_cross_accounts_access( # - GenerateDataKeyPairWithoutPlaintext # - GenerateDataKeyWithoutPlaintext # - GenerateMac - # - ReEncrypt (NOT IMPLEMENTED IN LOCALSTACK) + # - ReEncrypt # - Sign # - Verify # - VerifyMac diff --git a/tests/aws/services/kms/test_kms.snapshot.json b/tests/aws/services/kms/test_kms.snapshot.json index f4b7af999806e..26277bc6dea33 100644 --- a/tests/aws/services/kms/test_kms.snapshot.json +++ b/tests/aws/services/kms/test_kms.snapshot.json @@ -2240,7 +2240,7 @@ } }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { - "recorded-date": "20-05-2025, 12:20:30", + "recorded-date": "21-05-2025, 10:28:51", "recorded-content": { "test_re_encrypt": { "CiphertextBlob": "ciphertext-blob", @@ -2256,7 +2256,7 @@ } }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[RSA_2048-RSAES_OAEP_SHA_256]": { - "recorded-date": "20-05-2025, 12:20:31", + "recorded-date": "21-05-2025, 10:28:52", "recorded-content": { "test_re_encrypt": { "CiphertextBlob": "ciphertext-blob", @@ -2270,5 +2270,37 @@ } } } + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key[SYMMETRIC_DEFAULT]": { + "recorded-date": "21-05-2025, 10:29:13", + "recorded-content": { + "invalid-destination-key-usage": { + "Error": { + "Code": "InvalidKeyUsageException", + "Message": " key usage is SIGN_VERIFY which is not valid for ReEncryptTo." + }, + "message": " key usage is SIGN_VERIFY which is not valid for ReEncryptTo.", + "ResponseMetadata": { + "HTTPHeaders": {}, + "HTTPStatusCode": 400 + } + } + } + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key[SYMMETRIC_DEFAULT]": { + "recorded-date": "21-05-2025, 12:31:52", + "recorded-content": { + "incorrect-source-key": { + "Error": { + "Code": "IncorrectKeyException", + "Message": "The key ID in the request does not identify a CMK that can perform this operation." + }, + "message": "The key ID in the request does not identify a CMK that can perform this operation.", + "ResponseMetadata": { + "HTTPHeaders": {}, + "HTTPStatusCode": 400 + } + } + } } } diff --git a/tests/aws/services/kms/test_kms.validation.json b/tests/aws/services/kms/test_kms.validation.json index 45dd46d76a023..3ad1ce4944a53 100644 --- a/tests/aws/services/kms/test_kms.validation.json +++ b/tests/aws/services/kms/test_kms.validation.json @@ -200,17 +200,17 @@ "tests/aws/services/kms/test_kms.py::TestKMS::test_plaintext_size_for_encrypt": { "last_validated_date": "2024-04-11T15:54:20+00:00" }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[RSA_2048-RSAES_OAEP_SHA_256]": { - "last_validated_date": "2025-05-19T07:54:40+00:00" - }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encript[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { - "last_validated_date": "2025-05-19T07:54:39+00:00" - }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[RSA_2048-RSAES_OAEP_SHA_256]": { - "last_validated_date": "2025-05-20T12:20:30+00:00" + "last_validated_date": "2025-05-21T10:28:52+00:00" }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { - "last_validated_date": "2025-05-20T12:20:29+00:00" + "last_validated_date": "2025-05-21T10:28:50+00:00" + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key[SYMMETRIC_DEFAULT]": { + "last_validated_date": "2025-05-21T12:31:51+00:00" + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key[SYMMETRIC_DEFAULT]": { + "last_validated_date": "2025-05-21T10:29:13+00:00" }, "tests/aws/services/kms/test_kms.py::TestKMS::test_replicate_key": { "last_validated_date": "2024-04-11T15:53:44+00:00" From 4f8742b0a6260cc2cf52a49ffbbba851329b2e7a Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Wed, 21 May 2025 14:56:58 +0200 Subject: [PATCH 14/22] fix: lint --- tests/aws/services/kms/test_kms.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index ccc953c1ae1c4..16dca97a9ed0f 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -949,7 +949,9 @@ def test_re_encrypt_incorrect_source_key(self, kms_create_key, algo, aws_client, @markers.aws.validated def test_re_encrypt_invalid_destination_key(self, kms_create_key, algo, aws_client, snapshot): message = b"test message 123 !%$@ 1234567890" - source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")["KeyId"] + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")[ + "KeyId" + ] ciphertext = aws_client.kms.encrypt( KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] @@ -964,7 +966,7 @@ def test_re_encrypt_invalid_destination_key(self, kms_create_key, algo, aws_clie ) # TODO: Determine where 'context.operation.name' is being set to 'ReEncryptTo' as the expected AWS operation name is 'ReEncrypt' # Then enable the snapshot check - #snapshot.match("invalid-destination-key-usage", exc.value.response) + # snapshot.match("invalid-destination-key-usage", exc.value.response) assert exc.match("InvalidKeyUsageException") @pytest.mark.parametrize( From 66436324b8ac33ad7555e42406f4ee856d94b034 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Wed, 21 May 2025 15:01:55 +0200 Subject: [PATCH 15/22] fix: lint --- tests/aws/services/kms/test_kms.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 16dca97a9ed0f..99b67f8a56dd5 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -919,7 +919,9 @@ def test_re_encrypt(self, kms_create_key, key_spec, algo, aws_client, snapshot): @markers.aws.validated def test_re_encrypt_incorrect_source_key(self, kms_create_key, algo, aws_client, snapshot): message = b"test message 123 !%$@ 1234567890" - source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")["KeyId"] + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")[ + "KeyId" + ] ciphertext = aws_client.kms.encrypt( KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] From 701f2fd2cf2ab092209e03370bc5c2df0d34d5c7 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 9 Jun 2025 15:00:22 +0200 Subject: [PATCH 16/22] test: remove test params and update snapshots --- tests/aws/services/kms/test_kms.py | 22 ++++--------------- tests/aws/services/kms/test_kms.snapshot.json | 12 +++++----- .../aws/services/kms/test_kms.validation.json | 11 ++++++---- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 99b67f8a56dd5..baf1c0bd8763f 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -910,16 +910,10 @@ def test_re_encrypt(self, kms_create_key, key_spec, algo, aws_client, snapshot): assert base64.b64decode(source_key_plaintext) == message assert base64.b64decode(destination_key_plaintext) == message - @pytest.mark.parametrize( - "algo", - [ - ("SYMMETRIC_DEFAULT"), - ], - ) @markers.aws.validated - def test_re_encrypt_incorrect_source_key(self, kms_create_key, algo, aws_client, snapshot): + def test_re_encrypt_incorrect_source_key(self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT"): message = b"test message 123 !%$@ 1234567890" - source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")[ + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)[ "KeyId" ] ciphertext = aws_client.kms.encrypt( @@ -940,18 +934,11 @@ def test_re_encrypt_incorrect_source_key(self, kms_create_key, algo, aws_client, DestinationEncryptionAlgorithm=algo, ) snapshot.match("incorrect-source-key", exc.value.response) - assert exc.match("IncorrectKeyException") - @pytest.mark.parametrize( - "algo", - [ - ("SYMMETRIC_DEFAULT"), - ], - ) @markers.aws.validated - def test_re_encrypt_invalid_destination_key(self, kms_create_key, algo, aws_client, snapshot): + def test_re_encrypt_invalid_destination_key(self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT"): message = b"test message 123 !%$@ 1234567890" - source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec="SYMMETRIC_DEFAULT")[ + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)[ "KeyId" ] ciphertext = aws_client.kms.encrypt( @@ -969,7 +956,6 @@ def test_re_encrypt_invalid_destination_key(self, kms_create_key, algo, aws_clie # TODO: Determine where 'context.operation.name' is being set to 'ReEncryptTo' as the expected AWS operation name is 'ReEncrypt' # Then enable the snapshot check # snapshot.match("invalid-destination-key-usage", exc.value.response) - assert exc.match("InvalidKeyUsageException") @pytest.mark.parametrize( "key_spec,algo", diff --git a/tests/aws/services/kms/test_kms.snapshot.json b/tests/aws/services/kms/test_kms.snapshot.json index 26277bc6dea33..ca81b2ad11684 100644 --- a/tests/aws/services/kms/test_kms.snapshot.json +++ b/tests/aws/services/kms/test_kms.snapshot.json @@ -2240,7 +2240,7 @@ } }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { - "recorded-date": "21-05-2025, 10:28:51", + "recorded-date": "09-06-2025, 12:52:58", "recorded-content": { "test_re_encrypt": { "CiphertextBlob": "ciphertext-blob", @@ -2256,7 +2256,7 @@ } }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[RSA_2048-RSAES_OAEP_SHA_256]": { - "recorded-date": "21-05-2025, 10:28:52", + "recorded-date": "09-06-2025, 12:53:00", "recorded-content": { "test_re_encrypt": { "CiphertextBlob": "ciphertext-blob", @@ -2271,8 +2271,8 @@ } } }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key[SYMMETRIC_DEFAULT]": { - "recorded-date": "21-05-2025, 10:29:13", + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key": { + "recorded-date": "09-06-2025, 12:55:22", "recorded-content": { "invalid-destination-key-usage": { "Error": { @@ -2287,8 +2287,8 @@ } } }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key[SYMMETRIC_DEFAULT]": { - "recorded-date": "21-05-2025, 12:31:52", + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key": { + "recorded-date": "09-06-2025, 12:53:24", "recorded-content": { "incorrect-source-key": { "Error": { diff --git a/tests/aws/services/kms/test_kms.validation.json b/tests/aws/services/kms/test_kms.validation.json index 3ad1ce4944a53..f4d913d41e610 100644 --- a/tests/aws/services/kms/test_kms.validation.json +++ b/tests/aws/services/kms/test_kms.validation.json @@ -201,13 +201,16 @@ "last_validated_date": "2024-04-11T15:54:20+00:00" }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[RSA_2048-RSAES_OAEP_SHA_256]": { - "last_validated_date": "2025-05-21T10:28:52+00:00" + "last_validated_date": "2025-06-09T12:53:00+00:00" }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt[SYMMETRIC_DEFAULT-SYMMETRIC_DEFAULT]": { - "last_validated_date": "2025-05-21T10:28:50+00:00" + "last_validated_date": "2025-06-09T12:52:58+00:00" }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key[SYMMETRIC_DEFAULT]": { - "last_validated_date": "2025-05-21T12:31:51+00:00" + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key": { + "last_validated_date": "2025-06-09T12:53:24+00:00" + }, + "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key": { + "last_validated_date": "2025-06-09T12:55:21+00:00" }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key[SYMMETRIC_DEFAULT]": { "last_validated_date": "2025-05-21T10:29:13+00:00" From 0aefa7bcaedb11be7be397bb2bffb7de4f3235d4 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 9 Jun 2025 15:06:42 +0200 Subject: [PATCH 17/22] lint: fix linter --- tests/aws/services/kms/test_kms.py | 2 +- tests/aws/services/kms/test_kms.validation.json | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index baf1c0bd8763f..e046b0a50d569 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -945,7 +945,7 @@ def test_re_encrypt_invalid_destination_key(self, kms_create_key, aws_client, sn KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] invalid_key_id = kms_create_key(KeyUsage="SIGN_VERIFY", KeySpec="ECC_NIST_P256")["KeyId"] - with pytest.raises(ClientError) as exc: + with pytest.raises(ClientError): aws_client.kms.re_encrypt( SourceKeyId=source_key_id, DestinationKeyId=invalid_key_id, diff --git a/tests/aws/services/kms/test_kms.validation.json b/tests/aws/services/kms/test_kms.validation.json index f4d913d41e610..1a450a63f7781 100644 --- a/tests/aws/services/kms/test_kms.validation.json +++ b/tests/aws/services/kms/test_kms.validation.json @@ -212,9 +212,6 @@ "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key": { "last_validated_date": "2025-06-09T12:55:21+00:00" }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key[SYMMETRIC_DEFAULT]": { - "last_validated_date": "2025-05-21T10:29:13+00:00" - }, "tests/aws/services/kms/test_kms.py::TestKMS::test_replicate_key": { "last_validated_date": "2024-04-11T15:53:44+00:00" }, From ade9aa1f1c15c53c349b33197a05787ba8df5c3b Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 9 Jun 2025 15:11:05 +0200 Subject: [PATCH 18/22] lint: fix lint errors --- tests/aws/services/kms/test_kms.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index e046b0a50d569..4d53f97a531f7 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -936,11 +936,11 @@ def test_re_encrypt_incorrect_source_key(self, kms_create_key, aws_client, snaps snapshot.match("incorrect-source-key", exc.value.response) @markers.aws.validated - def test_re_encrypt_invalid_destination_key(self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT"): + def test_re_encrypt_invalid_destination_key( + self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT" + ): message = b"test message 123 !%$@ 1234567890" - source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)[ - "KeyId" - ] + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)["KeyId"] ciphertext = aws_client.kms.encrypt( KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] From 76dede227c22d4693ae0577d133ded6344cd6fb6 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Mon, 9 Jun 2025 15:20:24 +0200 Subject: [PATCH 19/22] lint: fix linter errors --- tests/aws/services/kms/test_kms.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 4d53f97a531f7..a4a39a52b8cda 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -911,11 +911,11 @@ def test_re_encrypt(self, kms_create_key, key_spec, algo, aws_client, snapshot): assert base64.b64decode(destination_key_plaintext) == message @markers.aws.validated - def test_re_encrypt_incorrect_source_key(self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT"): + def test_re_encrypt_incorrect_source_key( + self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT" + ): message = b"test message 123 !%$@ 1234567890" - source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)[ - "KeyId" - ] + source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)["KeyId"] ciphertext = aws_client.kms.encrypt( KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] From 197b60c81687b891989c0e35347a32a6b5b8e68e Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Tue, 10 Jun 2025 08:45:43 +0200 Subject: [PATCH 20/22] chore: remove snapshot --- tests/aws/services/kms/test_kms.py | 13 ++++++------- tests/aws/services/kms/test_kms.snapshot.json | 16 ---------------- tests/aws/services/kms/test_kms.validation.json | 3 --- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index a4a39a52b8cda..5d1363306ad93 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -911,9 +911,8 @@ def test_re_encrypt(self, kms_create_key, key_spec, algo, aws_client, snapshot): assert base64.b64decode(destination_key_plaintext) == message @markers.aws.validated - def test_re_encrypt_incorrect_source_key( - self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT" - ): + def test_re_encrypt_incorrect_source_key(self, kms_create_key, aws_client, snapshot): + algo="SYMMETRIC_DEFAULT" message = b"test message 123 !%$@ 1234567890" source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)["KeyId"] ciphertext = aws_client.kms.encrypt( @@ -936,16 +935,15 @@ def test_re_encrypt_incorrect_source_key( snapshot.match("incorrect-source-key", exc.value.response) @markers.aws.validated - def test_re_encrypt_invalid_destination_key( - self, kms_create_key, aws_client, snapshot, algo="SYMMETRIC_DEFAULT" - ): + def test_re_encrypt_invalid_destination_key(self, kms_create_key, aws_client): + algo="SYMMETRIC_DEFAULT" message = b"test message 123 !%$@ 1234567890" source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)["KeyId"] ciphertext = aws_client.kms.encrypt( KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] invalid_key_id = kms_create_key(KeyUsage="SIGN_VERIFY", KeySpec="ECC_NIST_P256")["KeyId"] - with pytest.raises(ClientError): + with pytest.raises(ClientError) as exec: aws_client.kms.re_encrypt( SourceKeyId=source_key_id, DestinationKeyId=invalid_key_id, @@ -956,6 +954,7 @@ def test_re_encrypt_invalid_destination_key( # TODO: Determine where 'context.operation.name' is being set to 'ReEncryptTo' as the expected AWS operation name is 'ReEncrypt' # Then enable the snapshot check # snapshot.match("invalid-destination-key-usage", exc.value.response) + assert exc.match("InvalidKeyUsageException") @pytest.mark.parametrize( "key_spec,algo", diff --git a/tests/aws/services/kms/test_kms.snapshot.json b/tests/aws/services/kms/test_kms.snapshot.json index ca81b2ad11684..0d4f5ff03be92 100644 --- a/tests/aws/services/kms/test_kms.snapshot.json +++ b/tests/aws/services/kms/test_kms.snapshot.json @@ -2271,22 +2271,6 @@ } } }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key": { - "recorded-date": "09-06-2025, 12:55:22", - "recorded-content": { - "invalid-destination-key-usage": { - "Error": { - "Code": "InvalidKeyUsageException", - "Message": " key usage is SIGN_VERIFY which is not valid for ReEncryptTo." - }, - "message": " key usage is SIGN_VERIFY which is not valid for ReEncryptTo.", - "ResponseMetadata": { - "HTTPHeaders": {}, - "HTTPStatusCode": 400 - } - } - } - }, "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key": { "recorded-date": "09-06-2025, 12:53:24", "recorded-content": { diff --git a/tests/aws/services/kms/test_kms.validation.json b/tests/aws/services/kms/test_kms.validation.json index 1a450a63f7781..df19dfe77dbba 100644 --- a/tests/aws/services/kms/test_kms.validation.json +++ b/tests/aws/services/kms/test_kms.validation.json @@ -209,9 +209,6 @@ "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_incorrect_source_key": { "last_validated_date": "2025-06-09T12:53:24+00:00" }, - "tests/aws/services/kms/test_kms.py::TestKMS::test_re_encrypt_invalid_destination_key": { - "last_validated_date": "2025-06-09T12:55:21+00:00" - }, "tests/aws/services/kms/test_kms.py::TestKMS::test_replicate_key": { "last_validated_date": "2024-04-11T15:53:44+00:00" }, From 2a2a1d09b315096c1c967865219c38bf31410ae9 Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Tue, 10 Jun 2025 08:53:40 +0200 Subject: [PATCH 21/22] fix: typo in exception name --- tests/aws/services/kms/test_kms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 5d1363306ad93..5570f4dd30cdf 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -943,7 +943,7 @@ def test_re_encrypt_invalid_destination_key(self, kms_create_key, aws_client): KeyId=source_key_id, Plaintext=base64.b64encode(message), EncryptionAlgorithm=algo )["CiphertextBlob"] invalid_key_id = kms_create_key(KeyUsage="SIGN_VERIFY", KeySpec="ECC_NIST_P256")["KeyId"] - with pytest.raises(ClientError) as exec: + with pytest.raises(ClientError) as exc: aws_client.kms.re_encrypt( SourceKeyId=source_key_id, DestinationKeyId=invalid_key_id, From 7b68fc00f7656917c5b0f2477f3b367bf2f9cd9b Mon Sep 17 00:00:00 2001 From: Victor Martin Date: Tue, 10 Jun 2025 08:58:47 +0200 Subject: [PATCH 22/22] fix: lint errors --- tests/aws/services/kms/test_kms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/aws/services/kms/test_kms.py b/tests/aws/services/kms/test_kms.py index 5570f4dd30cdf..92fcf1f085139 100644 --- a/tests/aws/services/kms/test_kms.py +++ b/tests/aws/services/kms/test_kms.py @@ -912,7 +912,7 @@ def test_re_encrypt(self, kms_create_key, key_spec, algo, aws_client, snapshot): @markers.aws.validated def test_re_encrypt_incorrect_source_key(self, kms_create_key, aws_client, snapshot): - algo="SYMMETRIC_DEFAULT" + algo = "SYMMETRIC_DEFAULT" message = b"test message 123 !%$@ 1234567890" source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)["KeyId"] ciphertext = aws_client.kms.encrypt( @@ -936,7 +936,7 @@ def test_re_encrypt_incorrect_source_key(self, kms_create_key, aws_client, snaps @markers.aws.validated def test_re_encrypt_invalid_destination_key(self, kms_create_key, aws_client): - algo="SYMMETRIC_DEFAULT" + algo = "SYMMETRIC_DEFAULT" message = b"test message 123 !%$@ 1234567890" source_key_id = kms_create_key(KeyUsage="ENCRYPT_DECRYPT", KeySpec=algo)["KeyId"] ciphertext = aws_client.kms.encrypt(