2023-11-30 15:55:51 +00:00
import base64
import itertools
2021-08-03 15:21:15 +00:00
import json
2023-11-30 15:55:51 +00:00
import os
2020-02-07 15:28:23 +00:00
from datetime import datetime
2022-12-17 21:35:07 +00:00
from unittest import mock
2023-08-24 07:52:11 +00:00
2020-02-07 15:28:23 +00:00
import boto3
import botocore . exceptions
2023-11-30 15:55:51 +00:00
import pytest
2021-09-22 20:37:03 +00:00
from botocore . exceptions import ClientError
2023-11-30 15:55:51 +00:00
from cryptography . hazmat . primitives import hashes , serialization
from cryptography . hazmat . primitives . asymmetric import ec , rsa
from dateutil . tz import tzutc
2020-02-07 15:28:23 +00:00
from freezegun import freeze_time
2024-01-07 12:03:33 +00:00
from moto import mock_aws
2022-08-13 09:49:43 +00:00
from moto . core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
2020-02-07 15:28:23 +00:00
2020-11-11 15:55:37 +00:00
PLAINTEXT_VECTORS = [
b " some encodeable plaintext " ,
b " some unencodeable plaintext \xec \x8a \xcf \xb6 r \xe9 \xb5 \xeb \xff \xa2 3 \x16 " ,
" some unicode characters ø˚∆øˆˆ∆ßçøˆˆçßøˆ¨¥ " ,
]
2020-02-07 15:28:23 +00:00
def _get_encoded_value ( plaintext ) :
2021-07-26 06:40:39 +00:00
if isinstance ( plaintext , bytes ) :
2020-02-07 15:28:23 +00:00
return plaintext
return plaintext . encode ( " utf-8 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-18 21:12:18 +00:00
def test_create_key_without_description ( ) :
conn = boto3 . client ( " kms " , region_name = " us-east-1 " )
metadata = conn . create_key ( Policy = " my policy " ) [ " KeyMetadata " ]
2023-08-02 09:41:44 +00:00
assert metadata [ " AWSAccountId " ] == ACCOUNT_ID
assert " KeyId " in metadata
assert " Arn " in metadata
assert metadata [ " Description " ] == " "
2021-09-18 21:12:18 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-19 10:53:54 +00:00
def test_create_key_with_invalid_key_spec ( ) :
conn = boto3 . client ( " kms " , region_name = " us-east-1 " )
unsupported_key_spec = " NotSupportedKeySpec "
with pytest . raises ( ClientError ) as ex :
conn . create_key ( Policy = " my policy " , KeySpec = unsupported_key_spec )
err = ex . value . response [ " Error " ]
assert err [ " Code " ] == " ValidationException "
assert err [ " Message " ] == (
" 1 validation error detected: Value ' {key_spec} ' at ' KeySpec ' failed "
" to satisfy constraint: Member must satisfy enum value set: "
" [ ' ECC_NIST_P256 ' , ' ECC_NIST_P384 ' , ' ECC_NIST_P521 ' , ' ECC_SECG_P256K1 ' , ' HMAC_224 ' , ' HMAC_256 ' , ' HMAC_384 ' , ' HMAC_512 ' , ' RSA_2048 ' , ' RSA_3072 ' , ' RSA_4096 ' , ' SM2 ' , ' SYMMETRIC_DEFAULT ' ] "
) . format ( key_spec = unsupported_key_spec )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_create_key ( ) :
conn = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = conn . create_key (
Policy = " my policy " ,
Description = " my key " ,
KeyUsage = " ENCRYPT_DECRYPT " ,
Tags = [ { " TagKey " : " project " , " TagValue " : " moto " } ] ,
)
2023-08-02 09:41:44 +00:00
assert (
key [ " KeyMetadata " ] [ " Arn " ]
== f " arn:aws:kms:us-east-1: { ACCOUNT_ID } :key/ { key [ ' KeyMetadata ' ] [ ' KeyId ' ] } "
2020-02-07 15:28:23 +00:00
)
2023-08-02 09:41:44 +00:00
assert key [ " KeyMetadata " ] [ " AWSAccountId " ] == ACCOUNT_ID
assert key [ " KeyMetadata " ] [ " CustomerMasterKeySpec " ] == " SYMMETRIC_DEFAULT "
assert key [ " KeyMetadata " ] [ " KeySpec " ] == " SYMMETRIC_DEFAULT "
assert key [ " KeyMetadata " ] [ " Description " ] == " my key "
assert key [ " KeyMetadata " ] [ " Enabled " ] is True
assert key [ " KeyMetadata " ] [ " EncryptionAlgorithms " ] == [ " SYMMETRIC_DEFAULT " ]
assert key [ " KeyMetadata " ] [ " KeyManager " ] == " CUSTOMER "
assert key [ " KeyMetadata " ] [ " KeyState " ] == " Enabled "
assert key [ " KeyMetadata " ] [ " KeyUsage " ] == " ENCRYPT_DECRYPT "
assert key [ " KeyMetadata " ] [ " Origin " ] == " AWS_KMS "
assert " SigningAlgorithms " not in key [ " KeyMetadata " ]
2020-02-07 15:28:23 +00:00
2022-06-21 17:18:51 +00:00
key = conn . create_key ( KeyUsage = " ENCRYPT_DECRYPT " , KeySpec = " RSA_2048 " )
2020-02-07 15:28:23 +00:00
2023-08-02 09:41:44 +00:00
assert sorted ( key [ " KeyMetadata " ] [ " EncryptionAlgorithms " ] ) == [
" RSAES_OAEP_SHA_1 " ,
" RSAES_OAEP_SHA_256 " ,
]
assert " SigningAlgorithms " not in key [ " KeyMetadata " ]
2020-02-07 15:28:23 +00:00
2022-06-21 17:18:51 +00:00
key = conn . create_key ( KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 " )
2020-02-07 15:28:23 +00:00
2023-08-02 09:41:44 +00:00
assert " EncryptionAlgorithms " not in key [ " KeyMetadata " ]
assert sorted ( key [ " KeyMetadata " ] [ " SigningAlgorithms " ] ) == [
" RSASSA_PKCS1_V1_5_SHA_256 " ,
" RSASSA_PKCS1_V1_5_SHA_384 " ,
" RSASSA_PKCS1_V1_5_SHA_512 " ,
" RSASSA_PSS_SHA_256 " ,
" RSASSA_PSS_SHA_384 " ,
" RSASSA_PSS_SHA_512 " ,
]
2020-02-07 15:28:23 +00:00
2022-06-21 17:18:51 +00:00
key = conn . create_key ( KeyUsage = " SIGN_VERIFY " , KeySpec = " ECC_SECG_P256K1 " )
2020-02-07 15:28:23 +00:00
2023-08-02 09:41:44 +00:00
assert " EncryptionAlgorithms " not in key [ " KeyMetadata " ]
assert key [ " KeyMetadata " ] [ " SigningAlgorithms " ] == [ " ECDSA_SHA_256 " ]
2020-02-07 15:28:23 +00:00
2022-06-21 17:18:51 +00:00
key = conn . create_key ( KeyUsage = " SIGN_VERIFY " , KeySpec = " ECC_NIST_P384 " )
2020-02-07 15:28:23 +00:00
2023-08-02 09:41:44 +00:00
assert " EncryptionAlgorithms " not in key [ " KeyMetadata " ]
assert key [ " KeyMetadata " ] [ " SigningAlgorithms " ] == [ " ECDSA_SHA_384 " ]
2020-02-07 15:28:23 +00:00
2022-06-21 17:18:51 +00:00
key = conn . create_key ( KeyUsage = " SIGN_VERIFY " , KeySpec = " ECC_NIST_P521 " )
2023-08-02 09:41:44 +00:00
assert " EncryptionAlgorithms " not in key [ " KeyMetadata " ]
assert key [ " KeyMetadata " ] [ " SigningAlgorithms " ] == [ " ECDSA_SHA_512 " ]
2022-06-21 17:18:51 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-07-27 09:30:41 +00:00
def test_create_multi_region_key ( ) :
conn = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = conn . create_key (
Policy = " my policy " ,
Description = " my key " ,
KeyUsage = " ENCRYPT_DECRYPT " ,
MultiRegion = True ,
Tags = [ { " TagKey " : " project " , " TagValue " : " moto " } ] ,
)
2023-08-02 09:41:44 +00:00
assert key [ " KeyMetadata " ] [ " KeyId " ] . startswith ( " mrk- " )
assert key [ " KeyMetadata " ] [ " MultiRegion " ] is True
2022-07-27 09:30:41 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-07-27 09:30:41 +00:00
def test_non_multi_region_keys_should_not_have_multi_region_properties ( ) :
conn = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = conn . create_key (
Policy = " my policy " ,
Description = " my key " ,
KeyUsage = " ENCRYPT_DECRYPT " ,
MultiRegion = False ,
Tags = [ { " TagKey " : " project " , " TagValue " : " moto " } ] ,
)
2023-08-02 09:41:44 +00:00
assert not key [ " KeyMetadata " ] [ " KeyId " ] . startswith ( " mrk- " )
assert key [ " KeyMetadata " ] [ " MultiRegion " ] is False
2022-07-27 09:30:41 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-07-27 09:30:41 +00:00
def test_replicate_key ( ) :
region_to_replicate_from = " us-east-1 "
region_to_replicate_to = " us-west-1 "
from_region_client = boto3 . client ( " kms " , region_name = region_to_replicate_from )
to_region_client = boto3 . client ( " kms " , region_name = region_to_replicate_to )
response = from_region_client . create_key (
Policy = " my policy " ,
Description = " my key " ,
KeyUsage = " ENCRYPT_DECRYPT " ,
MultiRegion = True ,
Tags = [ { " TagKey " : " project " , " TagValue " : " moto " } ] ,
)
key_id = response [ " KeyMetadata " ] [ " KeyId " ]
with pytest . raises ( to_region_client . exceptions . NotFoundException ) :
to_region_client . describe_key ( KeyId = key_id )
2022-12-17 21:35:07 +00:00
with mock . patch . object ( rsa , " generate_private_key " , return_value = " " ) :
2023-09-08 15:23:09 +00:00
replica_response = from_region_client . replicate_key (
2022-12-17 21:35:07 +00:00
KeyId = key_id , ReplicaRegion = region_to_replicate_to
)
2022-07-27 09:30:41 +00:00
to_region_client . describe_key ( KeyId = key_id )
from_region_client . describe_key ( KeyId = key_id )
2023-09-08 15:23:09 +00:00
assert " ReplicaKeyMetadata " in replica_response
assert region_to_replicate_to in replica_response [ " ReplicaKeyMetadata " ] [ " Arn " ]
assert " ReplicaPolicy " in replica_response
2022-07-27 09:30:41 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-21 17:18:51 +00:00
def test_create_key_deprecated_master_custom_key_spec ( ) :
conn = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-11-11 15:55:37 +00:00
key = conn . create_key ( KeyUsage = " SIGN_VERIFY " , CustomerMasterKeySpec = " ECC_NIST_P521 " )
2020-02-07 15:28:23 +00:00
2023-08-02 09:41:44 +00:00
assert " EncryptionAlgorithms " not in key [ " KeyMetadata " ]
assert key [ " KeyMetadata " ] [ " SigningAlgorithms " ] == [ " ECDSA_SHA_512 " ]
2020-02-07 15:28:23 +00:00
2023-08-02 09:41:44 +00:00
assert key [ " KeyMetadata " ] [ " CustomerMasterKeySpec " ] == " ECC_NIST_P521 "
assert key [ " KeyMetadata " ] [ " KeySpec " ] == " ECC_NIST_P521 "
2022-06-21 17:18:51 +00:00
2020-02-07 15:28:23 +00:00
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize ( " id_or_arn " , [ " KeyId " , " Arn " ] )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_describe_key ( id_or_arn ) :
2020-02-07 15:28:23 +00:00
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-11-11 15:55:37 +00:00
response = client . create_key ( Description = " my key " , KeyUsage = " ENCRYPT_DECRYPT " )
2021-09-22 20:37:03 +00:00
key_id = response [ " KeyMetadata " ] [ id_or_arn ]
2020-02-07 15:28:23 +00:00
response = client . describe_key ( KeyId = key_id )
2023-08-02 09:41:44 +00:00
assert response [ " KeyMetadata " ] [ " AWSAccountId " ] == " 123456789012 "
assert response [ " KeyMetadata " ] [ " CreationDate " ] is not None
assert response [ " KeyMetadata " ] [ " CustomerMasterKeySpec " ] == " SYMMETRIC_DEFAULT "
assert response [ " KeyMetadata " ] [ " KeySpec " ] == " SYMMETRIC_DEFAULT "
assert response [ " KeyMetadata " ] [ " Description " ] == " my key "
assert response [ " KeyMetadata " ] [ " Enabled " ] is True
assert response [ " KeyMetadata " ] [ " EncryptionAlgorithms " ] == [ " SYMMETRIC_DEFAULT " ]
assert response [ " KeyMetadata " ] [ " KeyManager " ] == " CUSTOMER "
assert response [ " KeyMetadata " ] [ " KeyState " ] == " Enabled "
assert response [ " KeyMetadata " ] [ " KeyUsage " ] == " ENCRYPT_DECRYPT "
assert response [ " KeyMetadata " ] [ " Origin " ] == " AWS_KMS "
assert " SigningAlgorithms " not in response [ " KeyMetadata " ]
2020-02-07 15:28:23 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-08-03 15:21:15 +00:00
def test_get_key_policy_default ( ) :
# given
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-08-03 15:21:15 +00:00
# when
policy = client . get_key_policy ( KeyId = key_id , PolicyName = " default " ) [ " Policy " ]
# then
2023-08-02 09:41:44 +00:00
assert json . loads ( policy ) == {
" Version " : " 2012-10-17 " ,
" Id " : " key-default-1 " ,
" Statement " : [
{
" Sid " : " Enable IAM User Permissions " ,
" Effect " : " Allow " ,
" Principal " : { " AWS " : f " arn:aws:iam:: { ACCOUNT_ID } :root " } ,
" Action " : " kms:* " ,
" Resource " : " * " ,
}
] ,
}
2021-08-03 15:21:15 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_describe_key_via_alias ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client , description = " my key " )
2021-09-22 20:37:03 +00:00
client . create_alias ( AliasName = " alias/my-alias " , TargetKeyId = key_id )
alias_key = client . describe_key ( KeyId = " alias/my-alias " )
2023-08-02 09:41:44 +00:00
assert alias_key [ " KeyMetadata " ] [ " Description " ] == " my key "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__can_create_multiple_aliases_for_same_key_id ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
alias_names = [ " alias/al1 " , " alias/al2 " , " alias/al3 " ]
for name in alias_names :
client . create_alias ( AliasName = name , TargetKeyId = key_id )
aliases = client . list_aliases ( KeyId = key_id ) [ " Aliases " ]
for name in alias_names :
2022-11-17 22:41:08 +00:00
alias_arn = f " arn:aws:kms:us-east-1: { ACCOUNT_ID } : { name } "
2023-08-02 09:41:44 +00:00
assert {
" AliasName " : name ,
" AliasArn " : alias_arn ,
" TargetKeyId " : key_id ,
} in aliases
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_list_aliases ( ) :
2021-10-26 09:57:58 +00:00
region = " us-west-1 "
client = boto3 . client ( " kms " , region_name = region )
2022-12-17 21:35:07 +00:00
create_simple_key ( client )
2021-09-22 20:37:03 +00:00
2023-01-11 20:43:48 +00:00
default_alias_target_keys = {
" aws/ebs " : " 7adeb491-68c9-4a5b-86ec-a86ce5364094 " ,
" aws/s3 " : " 8c3faf07-f43c-4d11-abdb-9183079214c7 " ,
" aws/redshift " : " dcdae9aa-593a-4e0b-9153-37325591901f " ,
" aws/rds " : " f5f30938-abed-41a2-a0f6-5482d02a2489 " ,
}
default_alias_names = list ( default_alias_target_keys . keys ( ) )
2021-09-22 20:37:03 +00:00
aliases = client . list_aliases ( ) [ " Aliases " ]
2023-08-02 09:41:44 +00:00
assert len ( aliases ) == 14
2021-09-22 20:37:03 +00:00
for name in default_alias_names :
2022-11-17 22:41:08 +00:00
full_name = f " alias/ { name } "
arn = f " arn:aws:kms: { region } : { ACCOUNT_ID } : { full_name } "
2023-01-11 20:43:48 +00:00
target_key_id = default_alias_target_keys [ name ]
2023-08-02 09:41:44 +00:00
assert {
" AliasName " : full_name ,
" AliasArn " : arn ,
" TargetKeyId " : target_key_id ,
} in aliases
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-02-27 15:43:43 +00:00
def test_list_aliases_for_key_id ( ) :
region = " us-west-1 "
client = boto3 . client ( " kms " , region_name = region )
my_alias = " alias/my-alias "
alias_arn = f " arn:aws:kms: { region } : { ACCOUNT_ID } : { my_alias } "
key_id = create_simple_key ( client , description = " my key " )
client . create_alias ( AliasName = my_alias , TargetKeyId = key_id )
aliases = client . list_aliases ( KeyId = key_id ) [ " Aliases " ]
2023-08-02 09:41:44 +00:00
assert len ( aliases ) == 1
assert {
" AliasName " : my_alias ,
" AliasArn " : alias_arn ,
" TargetKeyId " : key_id ,
} in aliases
2023-02-27 15:43:43 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-02-27 15:43:43 +00:00
def test_list_aliases_for_key_arn ( ) :
region = " us-west-1 "
client = boto3 . client ( " kms " , region_name = region )
key = client . create_key ( )
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
key_arn = key [ " KeyMetadata " ] [ " Arn " ]
id_alias = " alias/my-alias-1 "
client . create_alias ( AliasName = id_alias , TargetKeyId = key_id )
arn_alias = " alias/my-alias-2 "
client . create_alias ( AliasName = arn_alias , TargetKeyId = key_arn )
aliases = client . list_aliases ( KeyId = key_arn ) [ " Aliases " ]
2023-08-02 09:41:44 +00:00
assert len ( aliases ) == 2
2023-02-27 15:43:43 +00:00
for alias in [ id_alias , arn_alias ] :
alias_arn = f " arn:aws:kms: { region } : { ACCOUNT_ID } : { alias } "
2023-08-02 09:41:44 +00:00
assert {
" AliasName " : alias ,
" AliasArn " : alias_arn ,
" TargetKeyId " : key_id ,
} in aliases
2023-02-27 15:43:43 +00:00
2020-11-11 15:55:37 +00:00
@pytest.mark.parametrize (
" key_id " ,
[
" alias/does-not-exist " ,
" arn:aws:kms:us-east-1:012345678912:alias/does-not-exist " ,
" invalid " ,
] ,
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_describe_key_via_alias_invalid_alias ( key_id ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . describe_key ( KeyId = key_id )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_list_keys ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
with mock . patch . object ( rsa , " generate_private_key " , return_value = " " ) :
k1 = client . create_key ( Description = " key1 " ) [ " KeyMetadata " ]
k2 = client . create_key ( Description = " key2 " ) [ " KeyMetadata " ]
2021-09-22 20:37:03 +00:00
keys = client . list_keys ( ) [ " Keys " ]
2023-08-02 09:41:44 +00:00
assert len ( keys ) == 2
assert { " KeyId " : k1 [ " KeyId " ] , " KeyArn " : k1 [ " Arn " ] } in keys
assert { " KeyId " : k2 [ " KeyId " ] , " KeyArn " : k2 [ " Arn " ] } in keys
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize ( " id_or_arn " , [ " KeyId " , " Arn " ] )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_enable_key_rotation ( id_or_arn ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client , id_or_arn = id_or_arn )
2021-09-22 20:37:03 +00:00
2023-08-02 09:41:44 +00:00
assert client . get_key_rotation_status ( KeyId = key_id ) [ " KeyRotationEnabled " ] is False
2021-09-22 20:37:03 +00:00
client . enable_key_rotation ( KeyId = key_id )
2023-08-02 09:41:44 +00:00
assert client . get_key_rotation_status ( KeyId = key_id ) [ " KeyRotationEnabled " ] is True
2021-09-22 20:37:03 +00:00
client . disable_key_rotation ( KeyId = key_id )
2023-08-02 09:41:44 +00:00
assert client . get_key_rotation_status ( KeyId = key_id ) [ " KeyRotationEnabled " ] is False
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_enable_key_rotation_with_alias_name_should_fail ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
client . create_alias ( AliasName = " alias/my-alias " , TargetKeyId = key_id )
with pytest . raises ( ClientError ) as ex :
client . enable_key_rotation ( KeyId = " alias/my-alias " )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " NotFoundException "
assert err [ " Message " ] == " Invalid keyId alias/my-alias "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_data_key ( ) :
kms = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = kms . create_key ( )
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
key_arn = key [ " KeyMetadata " ] [ " Arn " ]
response = kms . generate_data_key ( KeyId = key_id , NumberOfBytes = 32 )
# CiphertextBlob must NOT be base64-encoded
2020-10-06 05:54:49 +00:00
with pytest . raises ( Exception ) :
2020-02-07 15:28:23 +00:00
base64 . b64decode ( response [ " CiphertextBlob " ] , validate = True )
# Plaintext must NOT be base64-encoded
2020-10-06 05:54:49 +00:00
with pytest . raises ( Exception ) :
2020-02-07 15:28:23 +00:00
base64 . b64decode ( response [ " Plaintext " ] , validate = True )
2023-08-02 09:41:44 +00:00
assert response [ " KeyId " ] == key_arn
2020-02-07 15:28:23 +00:00
2020-11-11 15:55:37 +00:00
@pytest.mark.parametrize (
" key_id " ,
[
" not-a-uuid " ,
" alias/DoesNotExist " ,
" arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist " ,
" d25652e4-d2d2-49f7-929a-671ccda580c6 " ,
" arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6 " ,
] ,
2020-02-07 15:28:23 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_invalid_key_ids ( key_id ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . generate_data_key ( KeyId = key_id , NumberOfBytes = 5 )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_disable_key ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
client . disable_key ( KeyId = key_id )
2020-02-07 15:28:23 +00:00
2022-12-17 21:35:07 +00:00
result = client . describe_key ( KeyId = key_id )
2022-03-11 21:28:45 +00:00
assert result [ " KeyMetadata " ] [ " Enabled " ] is False
2020-02-07 15:28:23 +00:00
assert result [ " KeyMetadata " ] [ " KeyState " ] == " Disabled "
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_enable_key ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
client . disable_key ( KeyId = key_id )
client . enable_key ( KeyId = key_id )
2020-02-07 15:28:23 +00:00
2022-12-17 21:35:07 +00:00
result = client . describe_key ( KeyId = key_id )
2022-03-11 21:28:45 +00:00
assert result [ " KeyMetadata " ] [ " Enabled " ] is True
2020-02-07 15:28:23 +00:00
assert result [ " KeyMetadata " ] [ " KeyState " ] == " Enabled "
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_schedule_key_deletion ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2020-02-07 15:28:23 +00:00
if os . environ . get ( " TEST_SERVER_MODE " , " false " ) . lower ( ) == " false " :
with freeze_time ( " 2015-01-01 12:00:00 " ) :
2022-12-17 21:35:07 +00:00
response = client . schedule_key_deletion ( KeyId = key_id )
assert response [ " KeyId " ] == key_id
2020-02-07 15:28:23 +00:00
assert response [ " DeletionDate " ] == datetime (
2015 , 1 , 31 , 12 , 0 , tzinfo = tzutc ( )
)
else :
# Can't manipulate time in server mode
2022-12-17 21:35:07 +00:00
response = client . schedule_key_deletion ( KeyId = key_id )
assert response [ " KeyId " ] == key_id
2020-02-07 15:28:23 +00:00
2022-12-17 21:35:07 +00:00
result = client . describe_key ( KeyId = key_id )
2022-03-11 21:28:45 +00:00
assert result [ " KeyMetadata " ] [ " Enabled " ] is False
2020-02-07 15:28:23 +00:00
assert result [ " KeyMetadata " ] [ " KeyState " ] == " PendingDeletion "
assert " DeletionDate " in result [ " KeyMetadata " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_schedule_key_deletion_custom ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " schedule-key-deletion " )
if os . environ . get ( " TEST_SERVER_MODE " , " false " ) . lower ( ) == " false " :
with freeze_time ( " 2015-01-01 12:00:00 " ) :
response = client . schedule_key_deletion (
KeyId = key [ " KeyMetadata " ] [ " KeyId " ] , PendingWindowInDays = 7
)
assert response [ " KeyId " ] == key [ " KeyMetadata " ] [ " KeyId " ]
assert response [ " DeletionDate " ] == datetime (
2015 , 1 , 8 , 12 , 0 , tzinfo = tzutc ( )
)
else :
# Can't manipulate time in server mode
response = client . schedule_key_deletion (
KeyId = key [ " KeyMetadata " ] [ " KeyId " ] , PendingWindowInDays = 7
)
assert response [ " KeyId " ] == key [ " KeyMetadata " ] [ " KeyId " ]
result = client . describe_key ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] )
2022-03-11 21:28:45 +00:00
assert result [ " KeyMetadata " ] [ " Enabled " ] is False
2020-02-07 15:28:23 +00:00
assert result [ " KeyMetadata " ] [ " KeyState " ] == " PendingDeletion "
assert " DeletionDate " in result [ " KeyMetadata " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_cancel_key_deletion ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " cancel-key-deletion " )
client . schedule_key_deletion ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] )
response = client . cancel_key_deletion ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] )
assert response [ " KeyId " ] == key [ " KeyMetadata " ] [ " KeyId " ]
result = client . describe_key ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] )
2022-03-11 21:28:45 +00:00
assert result [ " KeyMetadata " ] [ " Enabled " ] is False
2020-02-07 15:28:23 +00:00
assert result [ " KeyMetadata " ] [ " KeyState " ] == " Disabled "
assert " DeletionDate " not in result [ " KeyMetadata " ]
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_update_key_description ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2020-02-07 15:28:23 +00:00
result = client . update_key_description ( KeyId = key_id , Description = " new_description " )
assert " ResponseMetadata " in result
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_tag_resource ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " cancel-key-deletion " )
response = client . schedule_key_deletion ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] )
keyid = response [ " KeyId " ]
response = client . tag_resource (
KeyId = keyid , Tags = [ { " TagKey " : " string " , " TagValue " : " string " } ]
)
# Shouldn't have any data, just header
assert len ( response . keys ( ) ) == 1
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_list_resource_tags ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " cancel-key-deletion " )
response = client . schedule_key_deletion ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] )
keyid = response [ " KeyId " ]
response = client . tag_resource (
KeyId = keyid , Tags = [ { " TagKey " : " string " , " TagValue " : " string " } ]
)
response = client . list_resource_tags ( KeyId = keyid )
assert response [ " Tags " ] [ 0 ] [ " TagKey " ] == " string "
assert response [ " Tags " ] [ 0 ] [ " TagValue " ] == " string "
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 16:35:50 +00:00
def test_list_resource_tags_with_arn ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " cancel-key-deletion " )
client . schedule_key_deletion ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] )
keyid = key [ " KeyMetadata " ] [ " Arn " ]
client . tag_resource ( KeyId = keyid , Tags = [ { " TagKey " : " string " , " TagValue " : " string " } ] )
response = client . list_resource_tags ( KeyId = keyid )
assert response [ " Tags " ] [ 0 ] [ " TagKey " ] == " string "
assert response [ " Tags " ] [ 0 ] [ " TagValue " ] == " string "
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_unknown_tag_methods ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
with pytest . raises ( ClientError ) as ex :
client . tag_resource ( KeyId = " unknown " , Tags = [ ] )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Message " ] == " Invalid keyId unknown "
assert err [ " Code " ] == " NotFoundException "
2021-09-22 20:37:03 +00:00
with pytest . raises ( ClientError ) as ex :
client . untag_resource ( KeyId = " unknown " , TagKeys = [ ] )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Message " ] == " Invalid keyId unknown "
assert err [ " Code " ] == " NotFoundException "
2021-09-22 20:37:03 +00:00
with pytest . raises ( ClientError ) as ex :
client . list_resource_tags ( KeyId = " unknown " )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Message " ] == " Invalid keyId unknown "
assert err [ " Code " ] == " NotFoundException "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_list_resource_tags_after_untagging ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
client . tag_resource (
2022-12-17 21:35:07 +00:00
KeyId = key_id ,
2021-09-22 20:37:03 +00:00
Tags = [
{ " TagKey " : " key1 " , " TagValue " : " s1 " } ,
{ " TagKey " : " key2 " , " TagValue " : " s2 " } ,
] ,
)
2022-12-17 21:35:07 +00:00
client . untag_resource ( KeyId = key_id , TagKeys = [ " key2 " ] )
2021-09-22 20:37:03 +00:00
2022-12-17 21:35:07 +00:00
tags = client . list_resource_tags ( KeyId = key_id ) [ " Tags " ]
2023-08-02 09:41:44 +00:00
assert tags == [ { " TagKey " : " key1 " , " TagValue " : " s1 " } ]
2021-09-22 20:37:03 +00:00
2020-11-11 15:55:37 +00:00
@pytest.mark.parametrize (
" kwargs,expected_key_length " ,
2020-02-07 15:28:23 +00:00
(
( dict ( KeySpec = " AES_256 " ) , 32 ) ,
( dict ( KeySpec = " AES_128 " ) , 16 ) ,
( dict ( NumberOfBytes = 64 ) , 64 ) ,
( dict ( NumberOfBytes = 1 ) , 1 ) ,
( dict ( NumberOfBytes = 1024 ) , 1024 ) ,
2020-11-11 15:55:37 +00:00
) ,
2020-02-07 15:28:23 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_data_key_sizes ( kwargs , expected_key_length ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2020-02-07 15:28:23 +00:00
2022-12-17 21:35:07 +00:00
response = client . generate_data_key ( KeyId = key_id , * * kwargs )
2020-02-07 15:28:23 +00:00
assert len ( response [ " Plaintext " ] ) == expected_key_length
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_data_key_decrypt ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " generate-data-key-decrypt " )
resp1 = client . generate_data_key (
KeyId = key [ " KeyMetadata " ] [ " KeyId " ] , KeySpec = " AES_256 "
)
resp2 = client . decrypt ( CiphertextBlob = resp1 [ " CiphertextBlob " ] )
assert resp1 [ " Plaintext " ] == resp2 [ " Plaintext " ]
2020-11-11 15:55:37 +00:00
@pytest.mark.parametrize (
" kwargs " ,
[
dict ( KeySpec = " AES_257 " ) ,
dict ( KeySpec = " AES_128 " , NumberOfBytes = 16 ) ,
dict ( NumberOfBytes = 2048 ) ,
dict ( ) ,
] ,
2020-02-07 15:28:23 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_data_key_invalid_size_params ( kwargs ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " generate-data-key-size " )
2021-01-31 12:21:24 +00:00
with pytest . raises ( botocore . exceptions . ClientError ) :
2020-02-07 15:28:23 +00:00
client . generate_data_key ( KeyId = key [ " KeyMetadata " ] [ " KeyId " ] , * * kwargs )
2020-11-11 15:55:37 +00:00
@pytest.mark.parametrize (
" key_id " ,
[
" alias/DoesNotExist " ,
" arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist " ,
" d25652e4-d2d2-49f7-929a-671ccda580c6 " ,
" arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6 " ,
] ,
2020-02-07 15:28:23 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_data_key_invalid_key ( key_id ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . generate_data_key ( KeyId = key_id , KeySpec = " AES_256 " )
2020-11-11 15:55:37 +00:00
@pytest.mark.parametrize (
" prefix,append_key_id " ,
[
( " alias/DoesExist " , False ) ,
( " arn:aws:kms:us-east-1:012345678912:alias/DoesExist " , False ) ,
( " " , True ) ,
( " arn:aws:kms:us-east-1:012345678912:key/ " , True ) ,
] ,
2020-02-07 15:28:23 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_data_key_all_valid_key_ids ( prefix , append_key_id ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( )
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
client . create_alias ( AliasName = " alias/DoesExist " , TargetKeyId = key_id )
target_id = prefix
if append_key_id :
target_id + = key_id
2022-06-09 17:40:22 +00:00
resp = client . generate_data_key ( KeyId = target_id , NumberOfBytes = 32 )
2023-08-02 09:41:44 +00:00
assert resp [ " KeyId " ] == f " arn:aws:kms:us-east-1:123456789012:key/ { key_id } "
2020-02-07 15:28:23 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_data_key_without_plaintext_decrypt ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " generate-data-key-decrypt " )
resp1 = client . generate_data_key_without_plaintext (
KeyId = key [ " KeyMetadata " ] [ " KeyId " ] , KeySpec = " AES_256 "
)
assert " Plaintext " not in resp1
2020-11-11 15:54:01 +00:00
@pytest.mark.parametrize ( " number_of_bytes " , [ 12 , 44 , 91 , 1 , 1024 ] )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_random ( number_of_bytes ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
response = client . generate_random ( NumberOfBytes = number_of_bytes )
2023-08-02 09:41:44 +00:00
assert isinstance ( response [ " Plaintext " ] , bytes )
assert len ( response [ " Plaintext " ] ) == number_of_bytes
2020-02-07 15:28:23 +00:00
2020-11-11 15:55:37 +00:00
@pytest.mark.parametrize (
" number_of_bytes,error_type " ,
2021-01-31 12:21:24 +00:00
[ ( 2048 , botocore . exceptions . ClientError ) , ( 1025 , botocore . exceptions . ClientError ) ] ,
2020-02-07 15:28:23 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_generate_random_invalid_number_of_bytes ( number_of_bytes , error_type ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( error_type ) :
2020-02-07 15:28:23 +00:00
client . generate_random ( NumberOfBytes = number_of_bytes )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_enable_key_rotation_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . enable_key_rotation ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_disable_key_rotation_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . disable_key_rotation ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_enable_key_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . enable_key ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_disable_key_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . disable_key ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_cancel_key_deletion_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . cancel_key_deletion ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_schedule_key_deletion_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . schedule_key_deletion ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_get_key_rotation_status_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . get_key_rotation_status ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_get_key_policy_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . get_key_policy (
KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " , PolicyName = " default "
)
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_list_key_policies_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . list_key_policies ( KeyId = " 12366f9b-1230-123d-123e-123e6ae60c02 " )
2024-01-07 12:03:33 +00:00
@mock_aws
2020-02-07 15:28:23 +00:00
def test_put_key_policy_key_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2020-10-06 05:54:49 +00:00
with pytest . raises ( client . exceptions . NotFoundException ) :
2020-02-07 15:28:23 +00:00
client . put_key_policy (
KeyId = " 00000000-0000-0000-0000-000000000000 " ,
PolicyName = " default " ,
Policy = " new policy " ,
)
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize ( " id_or_arn " , [ " KeyId " , " Arn " ] )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_get_key_policy ( id_or_arn ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( Description = " key1 " , Policy = " my awesome key policy " )
key_id = key [ " KeyMetadata " ] [ id_or_arn ]
# Straight from the docs:
# PolicyName: Specifies the name of the key policy. The only valid name is default .
# But.. why.
response = client . get_key_policy ( KeyId = key_id , PolicyName = " default " )
2023-08-02 09:41:44 +00:00
assert response [ " Policy " ] == " my awesome key policy "
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize ( " id_or_arn " , [ " KeyId " , " Arn " ] )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_put_key_policy ( id_or_arn ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client , id_or_arn )
2021-09-22 20:37:03 +00:00
2021-10-18 19:44:29 +00:00
client . put_key_policy ( KeyId = key_id , PolicyName = " default " , Policy = " policy 2.0 " )
2021-09-22 20:37:03 +00:00
response = client . get_key_policy ( KeyId = key_id , PolicyName = " default " )
2023-08-02 09:41:44 +00:00
assert response [ " Policy " ] == " policy 2.0 "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_put_key_policy_using_alias_shouldnt_work ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client , policy = " my policy " )
2021-09-22 20:37:03 +00:00
client . create_alias ( AliasName = " alias/my-alias " , TargetKeyId = key_id )
with pytest . raises ( ClientError ) as ex :
client . put_key_policy (
KeyId = " alias/my-alias " , PolicyName = " default " , Policy = " policy 2.0 "
)
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " NotFoundException "
assert err [ " Message " ] == " Invalid keyId alias/my-alias "
2021-09-22 20:37:03 +00:00
response = client . get_key_policy ( KeyId = key_id , PolicyName = " default " )
2023-08-02 09:41:44 +00:00
assert response [ " Policy " ] == " my policy "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test_list_key_policies ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
policies = client . list_key_policies ( KeyId = key_id )
2023-08-02 09:41:44 +00:00
assert policies [ " PolicyNames " ] == [ " default " ]
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize (
" reserved_alias " ,
[ " alias/aws/ebs " , " alias/aws/s3 " , " alias/aws/redshift " , " alias/aws/rds " ] ,
)
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__raises_if_reserved_alias ( reserved_alias ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
with pytest . raises ( ClientError ) as ex :
client . create_alias ( AliasName = reserved_alias , TargetKeyId = key_id )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " NotAuthorizedException "
assert err [ " Message " ] == " "
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize (
" name " , [ " alias/my-alias! " , " alias/my-alias$ " , " alias/my-alias@ " ]
)
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__raises_if_alias_has_restricted_characters ( name ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
with pytest . raises ( ClientError ) as ex :
client . create_alias ( AliasName = name , TargetKeyId = key_id )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert (
err [ " Message " ]
== f " 1 validation error detected: Value ' { name } ' at ' aliasName ' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-zA-Z0-9:/_-]+$ "
2021-09-22 20:37:03 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__raises_if_alias_has_restricted_characters_semicolon ( ) :
# Similar test as above, but with different error msg
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
with pytest . raises ( ClientError ) as ex :
client . create_alias ( AliasName = " alias/my:alias " , TargetKeyId = key_id )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert err [ " Message " ] == " alias/my:alias contains invalid characters for an alias "
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize ( " name " , [ " alias/my-alias_/ " , " alias/my_alias-/ " ] )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__accepted_characters ( name ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
client . create_alias ( AliasName = name , TargetKeyId = key_id )
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__raises_if_target_key_id_is_existing_alias ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
name = " alias/my-alias "
client . create_alias ( AliasName = name , TargetKeyId = key_id )
with pytest . raises ( ClientError ) as ex :
client . create_alias ( AliasName = name , TargetKeyId = name )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert err [ " Message " ] == " Aliases must refer to keys. Not aliases "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__raises_if_wrong_prefix ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
with pytest . raises ( ClientError ) as ex :
client . create_alias ( AliasName = " wrongprefix/my-alias " , TargetKeyId = key_id )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert err [ " Message " ] == " Invalid identifier "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__create_alias__raises_if_duplicate ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2021-09-22 20:37:03 +00:00
alias = " alias/my-alias "
client . create_alias ( AliasName = alias , TargetKeyId = key_id )
with pytest . raises ( ClientError ) as ex :
client . create_alias ( AliasName = alias , TargetKeyId = key_id )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " AlreadyExistsException "
assert (
err [ " Message " ]
== f " An alias with the name arn:aws:kms:us-east-1: { ACCOUNT_ID } :alias/my-alias already exists "
2021-09-22 20:37:03 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__delete_alias ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
client . create_alias ( AliasName = " alias/a1 " , TargetKeyId = key_id )
2021-09-22 20:37:03 +00:00
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
client . create_alias ( AliasName = " alias/a2 " , TargetKeyId = key_id )
2021-09-22 20:37:03 +00:00
client . delete_alias ( AliasName = " alias/a1 " )
# we can create the alias again, since it has been deleted
2022-12-17 21:35:07 +00:00
client . create_alias ( AliasName = " alias/a1 " , TargetKeyId = key_id )
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__delete_alias__raises_if_wrong_prefix ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
with pytest . raises ( ClientError ) as ex :
client . delete_alias ( AliasName = " wrongprefix/my-alias " )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert err [ " Message " ] == " Invalid identifier "
2021-09-22 20:37:03 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2021-09-22 20:37:03 +00:00
def test__delete_alias__raises_if_alias_is_not_found ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
with pytest . raises ( ClientError ) as ex :
client . delete_alias ( AliasName = " alias/unknown-alias " )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " NotFoundException "
assert (
err [ " Message " ]
== f " Alias arn:aws:kms:us-east-1: { ACCOUNT_ID } :alias/unknown-alias is not found. "
2021-09-22 20:37:03 +00:00
)
2022-01-18 15:18:57 +00:00
2022-04-27 11:58:59 +00:00
def sort ( lst ) :
return sorted ( lst , key = lambda d : d . keys ( ) )
2022-01-18 15:18:57 +00:00
def _check_tags ( key_id , created_tags , client ) :
result = client . list_resource_tags ( KeyId = key_id )
actual = result . get ( " Tags " , [ ] )
assert sort ( created_tags ) == sort ( actual )
client . untag_resource ( KeyId = key_id , TagKeys = [ " key1 " ] )
actual = client . list_resource_tags ( KeyId = key_id ) . get ( " Tags " , [ ] )
expected = [ { " TagKey " : " key2 " , " TagValue " : " value2 " } ]
assert sort ( expected ) == sort ( actual )
2024-01-07 12:03:33 +00:00
@mock_aws
2022-01-18 15:18:57 +00:00
def test_key_tag_on_create_key_happy ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
tags = [
{ " TagKey " : " key1 " , " TagValue " : " value1 " } ,
{ " TagKey " : " key2 " , " TagValue " : " value2 " } ,
]
key = client . create_key ( Description = " test-key-tagging " , Tags = tags )
_check_tags ( key [ " KeyMetadata " ] [ " KeyId " ] , tags , client )
2024-01-07 12:03:33 +00:00
@mock_aws
2022-01-18 15:18:57 +00:00
def test_key_tag_on_create_key_on_arn_happy ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
tags = [
{ " TagKey " : " key1 " , " TagValue " : " value1 " } ,
{ " TagKey " : " key2 " , " TagValue " : " value2 " } ,
]
key = client . create_key ( Description = " test-key-tagging " , Tags = tags )
_check_tags ( key [ " KeyMetadata " ] [ " Arn " ] , tags , client )
2024-01-07 12:03:33 +00:00
@mock_aws
2022-01-18 15:18:57 +00:00
def test_key_tag_added_happy ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2022-01-18 15:18:57 +00:00
tags = [
{ " TagKey " : " key1 " , " TagValue " : " value1 " } ,
{ " TagKey " : " key2 " , " TagValue " : " value2 " } ,
]
client . tag_resource ( KeyId = key_id , Tags = tags )
_check_tags ( key_id , tags , client )
2024-01-07 12:03:33 +00:00
@mock_aws
2022-01-18 15:18:57 +00:00
def test_key_tag_added_arn_based_happy ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
2022-12-17 21:35:07 +00:00
key_id = create_simple_key ( client )
2022-01-18 15:18:57 +00:00
tags = [
{ " TagKey " : " key1 " , " TagValue " : " value1 " } ,
{ " TagKey " : " key2 " , " TagValue " : " value2 " } ,
]
client . tag_resource ( KeyId = key_id , Tags = tags )
_check_tags ( key_id , tags , client )
2022-06-21 17:18:51 +00:00
@pytest.mark.parametrize ( " plaintext " , PLAINTEXT_VECTORS )
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-21 17:18:51 +00:00
def test_sign_happy ( plaintext ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-21 17:18:51 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
key_arn = key [ " KeyMetadata " ] [ " Arn " ]
signing_algorithm = " RSASSA_PSS_SHA_256 "
sign_response = client . sign (
KeyId = key_id , Message = plaintext , SigningAlgorithm = signing_algorithm
)
2023-08-02 09:41:44 +00:00
assert sign_response [ " Signature " ] != plaintext
assert sign_response [ " SigningAlgorithm " ] == signing_algorithm
assert sign_response [ " KeyId " ] == key_arn
2022-06-21 17:18:51 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-21 17:18:51 +00:00
def test_sign_invalid_signing_algorithm ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-21 17:18:51 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
message = " My message "
signing_algorithm = " INVALID "
with pytest . raises ( ClientError ) as ex :
client . sign ( KeyId = key_id , Message = message , SigningAlgorithm = signing_algorithm )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert (
err [ " Message " ]
2023-08-19 20:49:45 +00:00
== " 1 validation error detected: Value ' INVALID ' at ' SigningAlgorithm ' failed to satisfy constraint: Member must satisfy enum value set: [ ' RSASSA_PKCS1_V1_5_SHA_256 ' , ' RSASSA_PKCS1_V1_5_SHA_384 ' , ' RSASSA_PKCS1_V1_5_SHA_512 ' , ' RSASSA_PSS_SHA_256 ' , ' RSASSA_PSS_SHA_384 ' , ' RSASSA_PSS_SHA_512 ' ] "
2022-06-21 17:18:51 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-23 09:45:07 +00:00
def test_sign_and_verify_ignoring_grant_tokens ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-23 09:45:07 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
message = " My message "
signing_algorithm = " RSASSA_PSS_SHA_256 "
sign_response = client . sign (
KeyId = key_id ,
Message = message ,
SigningAlgorithm = signing_algorithm ,
GrantTokens = [ " my-ignored-grant-token " ] ,
)
2023-08-02 09:41:44 +00:00
assert sign_response [ " Signature " ] != message
2022-06-23 09:45:07 +00:00
verify_response = client . verify (
KeyId = key_id ,
Message = message ,
Signature = sign_response [ " Signature " ] ,
SigningAlgorithm = signing_algorithm ,
GrantTokens = [ " my-ignored-grant-token " ] ,
)
2023-08-02 09:41:44 +00:00
assert verify_response [ " SignatureValid " ] is True
2022-06-23 09:45:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-24 07:52:11 +00:00
@pytest.mark.parametrize (
" key_spec, signing_algorithm " ,
list (
itertools . product (
[ " RSA_2048 " , " RSA_3072 " , " RSA_4096 " ] ,
2023-08-26 07:18:00 +00:00
[
" RSASSA_PSS_SHA_256 " ,
" RSASSA_PSS_SHA_384 " ,
" RSASSA_PSS_SHA_512 " ,
" RSASSA_PKCS1_V1_5_SHA_256 " ,
" RSASSA_PKCS1_V1_5_SHA_384 " ,
" RSASSA_PKCS1_V1_5_SHA_512 " ,
] ,
2023-08-24 07:52:11 +00:00
)
) ,
)
def test_sign_and_verify_digest_message_type_RSA ( key_spec , signing_algorithm ) :
2022-06-23 09:45:07 +00:00
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
2023-08-21 18:07:12 +00:00
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = key_spec
2023-08-19 20:49:45 +00:00
)
2022-06-23 09:45:07 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
digest = hashes . Hash ( hashes . SHA256 ( ) )
digest . update ( b " this works " )
digest . update ( b " as well " )
message = digest . finalize ( )
sign_response = client . sign (
KeyId = key_id ,
Message = message ,
SigningAlgorithm = signing_algorithm ,
MessageType = " DIGEST " ,
)
verify_response = client . verify (
KeyId = key_id ,
Message = message ,
Signature = sign_response [ " Signature " ] ,
SigningAlgorithm = signing_algorithm ,
)
2023-08-02 09:41:44 +00:00
assert verify_response [ " SignatureValid " ] is True
2022-06-23 09:45:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-26 07:16:51 +00:00
@pytest.mark.parametrize (
" signing_algorithm, another_signing_algorithm " ,
list (
itertools . combinations (
[ " RSASSA_PSS_SHA_256 " , " RSASSA_PSS_SHA_384 " , " RSASSA_PSS_SHA_512 " ] , 2
)
) ,
)
def test_fail_verify_digest_message_type_RSA (
signing_algorithm , another_signing_algorithm
) :
client = boto3 . client ( " kms " , region_name = " us-west-1 " )
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
digest = hashes . Hash ( hashes . SHA256 ( ) )
digest . update ( b " this works " )
digest . update ( b " as well " )
2023-08-28 18:39:50 +00:00
falsified_digest = digest . copy ( )
2023-08-26 07:16:51 +00:00
message = digest . finalize ( )
2023-08-28 18:39:50 +00:00
falsified_digest . update ( b " This sentence has been falsified " )
falsified_message = falsified_digest . finalize ( )
2023-08-26 07:16:51 +00:00
sign_response = client . sign (
KeyId = key_id ,
Message = message ,
SigningAlgorithm = signing_algorithm ,
MessageType = " DIGEST " ,
)
2023-08-28 18:39:50 +00:00
# Verification fails if a message has been falsified.
verify_response = client . verify (
KeyId = key_id ,
Message = falsified_message ,
Signature = sign_response [ " Signature " ] ,
SigningAlgorithm = signing_algorithm ,
)
assert verify_response [ " SignatureValid " ] is False
# Verification fails if a different signing algorithm is used than the one used in signature.
2023-08-26 07:16:51 +00:00
verify_response = client . verify (
KeyId = key_id ,
Message = message ,
Signature = sign_response [ " Signature " ] ,
SigningAlgorithm = another_signing_algorithm ,
)
assert verify_response [ " SignatureValid " ] is False
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-28 13:12:01 +00:00
@pytest.mark.parametrize (
" key_spec, signing_algorithm " ,
[
( " ECC_NIST_P256 " , " ECDSA_SHA_256 " ) ,
( " ECC_SECG_P256K1 " , " ECDSA_SHA_256 " ) ,
( " ECC_NIST_P384 " , " ECDSA_SHA_384 " ) ,
( " ECC_NIST_P521 " , " ECDSA_SHA_512 " ) ,
] ,
)
def test_sign_and_verify_digest_message_type_ECDSA ( key_spec , signing_algorithm ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = key_spec
)
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
digest = hashes . Hash ( hashes . SHA256 ( ) )
digest . update ( b " this works " )
digest . update ( b " as well " )
message = digest . finalize ( )
sign_response = client . sign (
KeyId = key_id ,
Message = message ,
SigningAlgorithm = signing_algorithm ,
MessageType = " DIGEST " ,
)
verify_response = client . verify (
KeyId = key_id ,
Message = message ,
Signature = sign_response [ " Signature " ] ,
SigningAlgorithm = signing_algorithm ,
)
assert verify_response [ " SignatureValid " ] is True
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-28 13:12:01 +00:00
@pytest.mark.parametrize (
" key_spec, signing_algorithm, valid_signing_algorithms " ,
[
( " ECC_NIST_P256 " , " ECDSA_SHA_384 " , [ " ECDSA_SHA_256 " ] ) ,
( " ECC_SECG_P256K1 " , " ECDSA_SHA_512 " , [ " ECDSA_SHA_256 " ] ) ,
( " ECC_NIST_P384 " , " ECDSA_SHA_256 " , [ " ECDSA_SHA_384 " ] ) ,
( " ECC_NIST_P521 " , " ECDSA_SHA_384 " , [ " ECDSA_SHA_512 " ] ) ,
] ,
)
def test_invalid_signing_algorithm_for_key_spec_type_ECDSA (
key_spec , signing_algorithm , valid_signing_algorithms
) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = key_spec
)
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
digest = hashes . Hash ( hashes . SHA256 ( ) )
digest . update ( b " this works " )
digest . update ( b " as well " )
message = digest . finalize ( )
with pytest . raises ( ClientError ) as ex :
_ = client . sign (
KeyId = key_id ,
Message = message ,
SigningAlgorithm = signing_algorithm ,
MessageType = " DIGEST " ,
)
err = ex . value . response [ " Error " ]
assert err [ " Code " ] == " ValidationException "
assert err [ " Message " ] == (
" 1 validation error detected: Value ' {signing_algorithm} ' at ' SigningAlgorithm ' failed "
" to satisfy constraint: Member must satisfy enum value set: "
" {valid_sign_algorithms} "
) . format (
signing_algorithm = signing_algorithm ,
valid_sign_algorithms = valid_signing_algorithms ,
)
2024-01-07 12:03:33 +00:00
@mock_aws
2023-08-28 13:12:01 +00:00
@pytest.mark.parametrize (
" key_spec, signing_algorithm " ,
[
( " ECC_NIST_P256 " , " ECDSA_SHA_256 " ) ,
( " ECC_SECG_P256K1 " , " ECDSA_SHA_256 " ) ,
( " ECC_NIST_P384 " , " ECDSA_SHA_384 " ) ,
( " ECC_NIST_P521 " , " ECDSA_SHA_512 " ) ,
] ,
)
def test_fail_verify_digest_message_type_ECDSA ( key_spec , signing_algorithm ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = key_spec
)
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
digest = hashes . Hash ( hashes . SHA256 ( ) )
digest . update ( b " this works " )
digest . update ( b " as well " )
falsified_digest = digest . copy ( )
message = digest . finalize ( )
falsified_digest . update ( b " This sentence has been falsified " )
falsified_message = falsified_digest . finalize ( )
sign_response = client . sign (
KeyId = key_id ,
Message = message ,
SigningAlgorithm = signing_algorithm ,
MessageType = " DIGEST " ,
)
verify_response = client . verify (
KeyId = key_id ,
Message = falsified_message ,
Signature = sign_response [ " Signature " ] ,
SigningAlgorithm = signing_algorithm ,
)
assert verify_response [ " SignatureValid " ] is False
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-21 17:18:51 +00:00
def test_sign_invalid_key_usage ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " ENCRYPT_DECRYPT " , KeySpec = " RSA_2048 "
)
2022-06-21 17:18:51 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
message = " My message "
signing_algorithm = " RSASSA_PSS_SHA_256 "
with pytest . raises ( ClientError ) as ex :
client . sign ( KeyId = key_id , Message = message , SigningAlgorithm = signing_algorithm )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert (
err [ " Message " ]
== f " 1 validation error detected: Value ' { key_id } ' at ' KeyId ' failed to satisfy constraint: Member must point to a key with usage: ' SIGN_VERIFY ' "
2022-06-21 17:18:51 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-21 17:18:51 +00:00
def test_sign_invalid_message ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-21 17:18:51 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
message = " "
signing_algorithm = " RSASSA_PSS_SHA_256 "
with pytest . raises ( ClientError ) as ex :
client . sign ( KeyId = key_id , Message = message , SigningAlgorithm = signing_algorithm )
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert (
err [ " Message " ]
== " 1 validation error detected: Value at ' Message ' failed to satisfy constraint: Member must have length greater than or equal to 1 "
2022-06-21 17:18:51 +00:00
)
@pytest.mark.parametrize ( " plaintext " , PLAINTEXT_VECTORS )
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-21 17:18:51 +00:00
def test_verify_happy ( plaintext ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-21 17:18:51 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
key_arn = key [ " KeyMetadata " ] [ " Arn " ]
signing_algorithm = " RSASSA_PSS_SHA_256 "
sign_response = client . sign (
KeyId = key_id , Message = plaintext , SigningAlgorithm = signing_algorithm
)
signature = sign_response [ " Signature " ]
verify_response = client . verify (
KeyId = key_id ,
Message = plaintext ,
Signature = signature ,
SigningAlgorithm = signing_algorithm ,
)
2023-08-02 09:41:44 +00:00
assert verify_response [ " SigningAlgorithm " ] == signing_algorithm
assert verify_response [ " KeyId " ] == key_arn
assert verify_response [ " SignatureValid " ] is True
2022-06-23 09:45:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-23 09:45:07 +00:00
def test_verify_happy_with_invalid_signature ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-23 09:45:07 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
key_arn = key [ " KeyMetadata " ] [ " Arn " ]
signing_algorithm = " RSASSA_PSS_SHA_256 "
verify_response = client . verify (
KeyId = key_id ,
Message = " my test " ,
Signature = " invalid signature " ,
SigningAlgorithm = signing_algorithm ,
)
2023-08-02 09:41:44 +00:00
assert verify_response [ " SigningAlgorithm " ] == signing_algorithm
assert verify_response [ " KeyId " ] == key_arn
assert verify_response [ " SignatureValid " ] is False
2022-06-23 09:45:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-23 09:45:07 +00:00
def test_verify_invalid_signing_algorithm ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-23 09:45:07 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
message = " My message "
signature = " any "
signing_algorithm = " INVALID "
with pytest . raises ( ClientError ) as ex :
client . verify (
KeyId = key_id ,
Message = message ,
Signature = signature ,
SigningAlgorithm = signing_algorithm ,
)
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert (
err [ " Message " ]
2023-08-19 20:49:45 +00:00
== " 1 validation error detected: Value ' INVALID ' at ' SigningAlgorithm ' failed to satisfy constraint: Member must satisfy enum value set: [ ' RSASSA_PKCS1_V1_5_SHA_256 ' , ' RSASSA_PKCS1_V1_5_SHA_384 ' , ' RSASSA_PKCS1_V1_5_SHA_512 ' , ' RSASSA_PSS_SHA_256 ' , ' RSASSA_PSS_SHA_384 ' , ' RSASSA_PSS_SHA_512 ' ] "
2022-06-23 09:45:07 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-23 09:45:07 +00:00
def test_verify_invalid_message ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-23 09:45:07 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
signing_algorithm = " RSASSA_PSS_SHA_256 "
with pytest . raises ( ClientError ) as ex :
client . verify (
KeyId = key_id ,
Message = " " ,
Signature = " a signature " ,
SigningAlgorithm = signing_algorithm ,
)
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert (
err [ " Message " ]
== " 1 validation error detected: Value at ' Message ' failed to satisfy constraint: Member must have length greater than or equal to 1 "
2022-06-23 09:45:07 +00:00
)
2024-01-07 12:03:33 +00:00
@mock_aws
2022-06-23 09:45:07 +00:00
def test_verify_empty_signature ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
2023-08-19 20:49:45 +00:00
key = client . create_key (
Description = " sign-key " , KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 "
)
2022-06-23 09:45:07 +00:00
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
message = " My message "
signing_algorithm = " RSASSA_PSS_SHA_256 "
signature = " "
with pytest . raises ( ClientError ) as ex :
client . verify (
KeyId = key_id ,
Message = message ,
Signature = signature ,
SigningAlgorithm = signing_algorithm ,
)
err = ex . value . response [ " Error " ]
2023-08-02 09:41:44 +00:00
assert err [ " Code " ] == " ValidationException "
assert (
err [ " Message " ]
== " 1 validation error detected: Value at ' Signature ' failed to satisfy constraint: Member must have length greater than or equal to 1 "
2022-06-23 09:45:07 +00:00
)
2022-12-17 21:35:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-04-17 19:59:33 +00:00
def test_get_public_key ( ) :
client = boto3 . client ( " kms " , region_name = " us-east-1 " )
key = client . create_key ( KeyUsage = " SIGN_VERIFY " , KeySpec = " RSA_2048 " )
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
public_key_response = client . get_public_key ( KeyId = key_id )
2023-08-02 09:41:44 +00:00
assert " PublicKey " in public_key_response
assert (
public_key_response [ " SigningAlgorithms " ]
== key [ " KeyMetadata " ] [ " SigningAlgorithms " ]
2023-04-17 19:59:33 +00:00
)
2023-08-02 09:41:44 +00:00
assert " EncryptionAlgorithms " not in public_key_response
2023-04-17 19:59:33 +00:00
2022-12-17 21:35:07 +00:00
def create_simple_key ( client , id_or_arn = " KeyId " , description = None , policy = None ) :
with mock . patch . object ( rsa , " generate_private_key " , return_value = " " ) :
params = { }
if description :
params [ " Description " ] = description
if policy :
params [ " Policy " ] = policy
return client . create_key ( * * params ) [ " KeyMetadata " ] [ id_or_arn ]
2023-09-09 09:57:39 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2023-09-09 09:57:39 +00:00
def test_ensure_key_can_be_verified_manually ( ) :
signing_algorithm : str = " ECDSA_SHA_256 "
kms_client = boto3 . client ( " kms " , region_name = " us-east-1 " )
response = kms_client . create_key (
Description = " example " ,
KeyUsage = " SIGN_VERIFY " ,
CustomerMasterKeySpec = " ECC_NIST_P256 " ,
)
key_id = response [ " KeyMetadata " ] [ " KeyId " ]
public_key_data = kms_client . get_public_key ( KeyId = key_id ) [ " PublicKey " ]
message = b " example message "
response = kms_client . sign (
KeyId = key_id ,
Message = message ,
MessageType = " RAW " ,
SigningAlgorithm = signing_algorithm ,
)
raw_signature = response [ " Signature " ]
sign_kwargs = dict ( signature_algorithm = ec . ECDSA ( hashes . SHA256 ( ) ) )
public_key = serialization . load_der_public_key ( public_key_data )
public_key . verify ( signature = raw_signature , data = message , * * sign_kwargs )