2021-08-03 15:21:15 +00:00
import json
2020-02-07 15:28:23 +00:00
from datetime import datetime
2022-06-23 09:45:07 +00:00
from cryptography . hazmat . primitives import hashes
2022-12-17 21:35:07 +00:00
from cryptography . hazmat . primitives . asymmetric import rsa
from unittest import mock
2020-02-07 15:28:23 +00:00
from dateutil . tz import tzutc
import base64
import os
import boto3
import botocore . exceptions
2021-10-18 19:44:29 +00:00
import sure # noqa # pylint: disable=unused-import
2021-09-22 20:37:03 +00:00
from botocore . exceptions import ClientError
2020-02-07 15:28:23 +00:00
from freezegun import freeze_time
2020-10-06 05:54:49 +00:00
import pytest
2020-02-07 15:28:23 +00:00
from moto import mock_kms
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
2021-09-22 20:37:03 +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 " )
2021-09-18 21:12:18 +00:00
@mock_kms
def test_create_key_without_description ( ) :
conn = boto3 . client ( " kms " , region_name = " us-east-1 " )
metadata = conn . create_key ( Policy = " my policy " ) [ " KeyMetadata " ]
metadata . should . have . key ( " AWSAccountId " ) . equals ( ACCOUNT_ID )
metadata . should . have . key ( " KeyId " )
metadata . should . have . key ( " Arn " )
metadata . should . have . key ( " Description " ) . equal ( " " )
2020-02-07 15:28:23 +00:00
@mock_kms
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 " } ] ,
)
key [ " KeyMetadata " ] [ " Arn " ] . should . equal (
2022-11-17 22:41:08 +00:00
f " arn:aws:kms:us-east-1: { ACCOUNT_ID } :key/ { key [ ' KeyMetadata ' ] [ ' KeyId ' ] } "
2020-02-07 15:28:23 +00:00
)
2021-09-18 21:12:18 +00:00
key [ " KeyMetadata " ] [ " AWSAccountId " ] . should . equal ( ACCOUNT_ID )
2020-02-07 15:28:23 +00:00
key [ " KeyMetadata " ] [ " CreationDate " ] . should . be . a ( datetime )
key [ " KeyMetadata " ] [ " CustomerMasterKeySpec " ] . should . equal ( " SYMMETRIC_DEFAULT " )
2022-06-21 17:18:51 +00:00
key [ " KeyMetadata " ] [ " KeySpec " ] . should . equal ( " SYMMETRIC_DEFAULT " )
2020-02-07 15:28:23 +00:00
key [ " KeyMetadata " ] [ " Description " ] . should . equal ( " my key " )
2022-04-18 20:44:56 +00:00
key [ " KeyMetadata " ] [ " Enabled " ] . should . equal ( True )
2020-02-07 15:28:23 +00:00
key [ " KeyMetadata " ] [ " EncryptionAlgorithms " ] . should . equal ( [ " SYMMETRIC_DEFAULT " ] )
2022-04-18 20:44:56 +00:00
key [ " KeyMetadata " ] [ " KeyId " ] . should . match ( " [-a-zA-Z0-9]+ " )
2020-02-07 15:28:23 +00:00
key [ " KeyMetadata " ] [ " KeyManager " ] . should . equal ( " CUSTOMER " )
key [ " KeyMetadata " ] [ " KeyState " ] . should . equal ( " Enabled " )
key [ " KeyMetadata " ] [ " KeyUsage " ] . should . equal ( " ENCRYPT_DECRYPT " )
key [ " KeyMetadata " ] [ " Origin " ] . should . equal ( " AWS_KMS " )
key [ " KeyMetadata " ] . should_not . have . key ( " SigningAlgorithms " )
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
sorted ( key [ " KeyMetadata " ] [ " EncryptionAlgorithms " ] ) . should . equal (
[ " RSAES_OAEP_SHA_1 " , " RSAES_OAEP_SHA_256 " ]
)
key [ " KeyMetadata " ] . should_not . have . key ( " SigningAlgorithms " )
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
key [ " KeyMetadata " ] . should_not . have . key ( " EncryptionAlgorithms " )
sorted ( key [ " KeyMetadata " ] [ " SigningAlgorithms " ] ) . should . equal (
[
" 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
key = conn . create_key ( KeyUsage = " SIGN_VERIFY " , KeySpec = " ECC_SECG_P256K1 " )
2020-02-07 15:28:23 +00:00
key [ " KeyMetadata " ] . should_not . have . key ( " EncryptionAlgorithms " )
key [ " KeyMetadata " ] [ " SigningAlgorithms " ] . should . equal ( [ " ECDSA_SHA_256 " ] )
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
key [ " KeyMetadata " ] . should_not . have . key ( " EncryptionAlgorithms " )
key [ " KeyMetadata " ] [ " SigningAlgorithms " ] . should . equal ( [ " ECDSA_SHA_384 " ] )
2022-06-21 17:18:51 +00:00
key = conn . create_key ( KeyUsage = " SIGN_VERIFY " , KeySpec = " ECC_NIST_P521 " )
key [ " KeyMetadata " ] . should_not . have . key ( " EncryptionAlgorithms " )
key [ " KeyMetadata " ] [ " SigningAlgorithms " ] . should . equal ( [ " ECDSA_SHA_512 " ] )
2022-07-27 09:30:41 +00:00
@mock_kms
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 " } ] ,
)
key [ " KeyMetadata " ] [ " KeyId " ] . should . match ( " ^mrk- " )
key [ " KeyMetadata " ] [ " MultiRegion " ] . should . equal ( True )
@mock_kms
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 " } ] ,
)
key [ " KeyMetadata " ] [ " KeyId " ] . should_not . match ( " ^mrk- " )
key [ " KeyMetadata " ] [ " MultiRegion " ] . should . equal ( False )
@mock_kms
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 = " " ) :
from_region_client . replicate_key (
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 )
2022-06-21 17:18:51 +00:00
@mock_kms
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
key [ " KeyMetadata " ] . should_not . have . key ( " EncryptionAlgorithms " )
key [ " KeyMetadata " ] [ " SigningAlgorithms " ] . should . equal ( [ " ECDSA_SHA_512 " ] )
2022-06-21 17:18:51 +00:00
key [ " KeyMetadata " ] [ " CustomerMasterKeySpec " ] . should . equal ( " ECC_NIST_P521 " )
key [ " KeyMetadata " ] [ " KeySpec " ] . should . equal ( " ECC_NIST_P521 " )
2020-02-07 15:28:23 +00:00
2021-09-22 20:37:03 +00:00
@pytest.mark.parametrize ( " id_or_arn " , [ " KeyId " , " Arn " ] )
2020-02-07 15:28:23 +00:00
@mock_kms
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 )
response [ " KeyMetadata " ] [ " AWSAccountId " ] . should . equal ( " 123456789012 " )
response [ " KeyMetadata " ] [ " CreationDate " ] . should . be . a ( datetime )
response [ " KeyMetadata " ] [ " CustomerMasterKeySpec " ] . should . equal ( " SYMMETRIC_DEFAULT " )
2022-06-21 17:18:51 +00:00
response [ " KeyMetadata " ] [ " KeySpec " ] . should . equal ( " SYMMETRIC_DEFAULT " )
2020-02-07 15:28:23 +00:00
response [ " KeyMetadata " ] [ " Description " ] . should . equal ( " my key " )
2022-04-18 20:44:56 +00:00
response [ " KeyMetadata " ] [ " Enabled " ] . should . equal ( True )
2020-02-07 15:28:23 +00:00
response [ " KeyMetadata " ] [ " EncryptionAlgorithms " ] . should . equal ( [ " SYMMETRIC_DEFAULT " ] )
2022-04-18 20:44:56 +00:00
response [ " KeyMetadata " ] [ " KeyId " ] . should . match ( " [-a-zA-Z0-9]+ " )
2020-02-07 15:28:23 +00:00
response [ " KeyMetadata " ] [ " KeyManager " ] . should . equal ( " CUSTOMER " )
response [ " KeyMetadata " ] [ " KeyState " ] . should . equal ( " Enabled " )
response [ " KeyMetadata " ] [ " KeyUsage " ] . should . equal ( " ENCRYPT_DECRYPT " )
response [ " KeyMetadata " ] [ " Origin " ] . should . equal ( " AWS_KMS " )
response [ " KeyMetadata " ] . should_not . have . key ( " SigningAlgorithms " )
2021-08-03 15:21:15 +00:00
@mock_kms
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
json . loads ( policy ) . should . equal (
{
" 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-09-22 20:37:03 +00:00
@mock_kms
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 " )
alias_key [ " KeyMetadata " ] [ " Description " ] . should . equal ( " my key " )
@mock_kms
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 } "
2021-09-22 20:37:03 +00:00
aliases . should . contain (
{ " AliasName " : name , " AliasArn " : alias_arn , " TargetKeyId " : key_id }
)
@mock_kms
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 " ]
2021-10-26 09:57:58 +00:00
aliases . should . have . length_of ( 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 ]
aliases . should . contain (
{ " AliasName " : full_name , " AliasArn " : arn , " TargetKeyId " : target_key_id }
)
2021-09-22 20:37:03 +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 " ,
] ,
)
2020-02-07 15:28:23 +00:00
@mock_kms
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 )
2021-09-22 20:37:03 +00:00
@mock_kms
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 " ]
keys . should . have . length_of ( 2 )
keys . should . contain ( { " KeyId " : k1 [ " KeyId " ] , " KeyArn " : k1 [ " Arn " ] } )
keys . should . contain ( { " KeyId " : k2 [ " KeyId " ] , " KeyArn " : k2 [ " Arn " ] } )
@pytest.mark.parametrize ( " id_or_arn " , [ " KeyId " , " Arn " ] )
@mock_kms
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
client . get_key_rotation_status ( KeyId = key_id ) [ " KeyRotationEnabled " ] . should . equal (
False
)
client . enable_key_rotation ( KeyId = key_id )
client . get_key_rotation_status ( KeyId = key_id ) [ " KeyRotationEnabled " ] . should . equal (
True
)
client . disable_key_rotation ( KeyId = key_id )
client . get_key_rotation_status ( KeyId = key_id ) [ " KeyRotationEnabled " ] . should . equal (
False
)
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " NotFoundException " )
err [ " Message " ] . should . equal ( " Invalid keyId alias/my-alias " )
2020-02-07 15:28:23 +00:00
@mock_kms
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 )
response [ " KeyId " ] . should . equal ( key_arn )
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
)
@mock_kms
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 )
@mock_kms
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 "
@mock_kms
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 "
@mock_kms
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 " ]
@mock_kms
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 " ]
@mock_kms
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 " ]
@mock_kms
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
@mock_kms
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
@mock_kms
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 "
2021-09-22 16:35:50 +00:00
@mock_kms
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 "
2021-09-22 20:37:03 +00:00
@mock_kms
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 " ]
err [ " Message " ] . should . equal ( " Invalid keyId unknown " )
err [ " Code " ] . should . equal ( " NotFoundException " )
with pytest . raises ( ClientError ) as ex :
client . untag_resource ( KeyId = " unknown " , TagKeys = [ ] )
err = ex . value . response [ " Error " ]
err [ " Message " ] . should . equal ( " Invalid keyId unknown " )
err [ " Code " ] . should . equal ( " NotFoundException " )
with pytest . raises ( ClientError ) as ex :
client . list_resource_tags ( KeyId = " unknown " )
err = ex . value . response [ " Error " ]
err [ " Message " ] . should . equal ( " Invalid keyId unknown " )
err [ " Code " ] . should . equal ( " NotFoundException " )
@mock_kms
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 " ]
2021-09-22 20:37:03 +00:00
tags . should . equal ( [ { " TagKey " : " key1 " , " TagValue " : " s1 " } ] )
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
)
@mock_kms
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
@mock_kms
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
)
@mock_kms
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
)
@mock_kms
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
)
@mock_kms
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 )
resp . should . have . key ( " KeyId " ) . equals (
f " arn:aws:kms:us-east-1:123456789012:key/ { key_id } "
)
2020-02-07 15:28:23 +00:00
@mock_kms
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 ] )
2020-02-07 15:28:23 +00:00
@mock_kms
def test_generate_random ( number_of_bytes ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
response = client . generate_random ( NumberOfBytes = number_of_bytes )
response [ " Plaintext " ] . should . be . a ( bytes )
len ( response [ " Plaintext " ] ) . should . equal ( number_of_bytes )
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
)
@mock_kms
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 )
@mock_kms
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 " )
@mock_kms
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 " )
@mock_kms
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 " )
@mock_kms
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 " )
@mock_kms
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 " )
@mock_kms
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 " )
@mock_kms
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 " )
@mock_kms
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 "
)
@mock_kms
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 " )
@mock_kms
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 " ] )
@mock_kms
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 " )
response [ " Policy " ] . should . equal ( " my awesome key policy " )
@pytest.mark.parametrize ( " id_or_arn " , [ " KeyId " , " Arn " ] )
@mock_kms
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 " )
response [ " Policy " ] . should . equal ( " policy 2.0 " )
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " NotFoundException " )
err [ " Message " ] . should . equal ( " Invalid keyId alias/my-alias " )
response = client . get_key_policy ( KeyId = key_id , PolicyName = " default " )
2022-12-17 21:35:07 +00:00
response [ " Policy " ] . should . equal ( " my policy " )
2021-09-22 20:37:03 +00:00
@mock_kms
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 )
policies [ " PolicyNames " ] . should . equal ( [ " default " ] )
@pytest.mark.parametrize (
" reserved_alias " ,
[ " alias/aws/ebs " , " alias/aws/s3 " , " alias/aws/redshift " , " alias/aws/rds " ] ,
)
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " NotAuthorizedException " )
err [ " Message " ] . should . equal ( " " )
@pytest.mark.parametrize (
" name " , [ " alias/my-alias! " , " alias/my-alias$ " , " alias/my-alias@ " ]
)
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
2022-11-17 22:41:08 +00:00
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
)
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
" alias/my:alias contains invalid characters for an alias "
)
@pytest.mark.parametrize ( " name " , [ " alias/my-alias_/ " , " alias/my_alias-/ " ] )
@mock_kms
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 )
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal ( " Aliases must refer to keys. Not aliases " )
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal ( " Invalid identifier " )
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " AlreadyExistsException " )
err [ " Message " ] . should . equal (
f " An alias with the name arn:aws:kms:us-east-1: { ACCOUNT_ID } :alias/my-alias already exists "
)
@mock_kms
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
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal ( " Invalid identifier " )
@mock_kms
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 " ]
err [ " Code " ] . should . equal ( " NotFoundException " )
err [ " Message " ] . should . equal (
f " Alias arn:aws:kms:us-east-1: { ACCOUNT_ID } :alias/unknown-alias is not found. "
)
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 )
@mock_kms
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 )
@mock_kms
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 )
@mock_kms
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 )
@mock_kms
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 )
@mock_kms
def test_sign_happy ( plaintext ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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
)
sign_response [ " Signature " ] . should_not . equal ( plaintext )
sign_response [ " SigningAlgorithm " ] . should . equal ( signing_algorithm )
sign_response [ " KeyId " ] . should . equal ( key_arn )
@mock_kms
def test_sign_invalid_signing_algorithm ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
" 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
@mock_kms
def test_sign_and_verify_ignoring_grant_tokens ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 " ] ,
)
sign_response [ " Signature " ] . should_not . equal ( message )
verify_response = client . verify (
KeyId = key_id ,
Message = message ,
Signature = sign_response [ " Signature " ] ,
SigningAlgorithm = signing_algorithm ,
GrantTokens = [ " my-ignored-grant-token " ] ,
)
verify_response [ " SignatureValid " ] . should . equal ( True )
@mock_kms
def test_sign_and_verify_digest_message_type_256 ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
key_id = key [ " KeyMetadata " ] [ " KeyId " ]
digest = hashes . Hash ( hashes . SHA256 ( ) )
digest . update ( b " this works " )
digest . update ( b " as well " )
message = digest . finalize ( )
signing_algorithm = " RSASSA_PSS_SHA_256 "
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 ,
)
verify_response [ " SignatureValid " ] . should . equal ( True )
2022-06-21 17:18:51 +00:00
@mock_kms
def test_sign_invalid_key_usage ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " ENCRYPT_DECRYPT " )
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
f " 1 validation error detected: Value ' { key_id } ' at ' KeyId ' failed to satisfy constraint: Member must point to a key with usage: ' SIGN_VERIFY ' "
)
@mock_kms
def test_sign_invalid_message ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
" 1 validation error detected: Value at ' Message ' failed to satisfy constraint: Member must have length greater than or equal to 1 "
)
@pytest.mark.parametrize ( " plaintext " , PLAINTEXT_VECTORS )
@mock_kms
def test_verify_happy ( plaintext ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 ,
)
verify_response [ " SigningAlgorithm " ] . should . equal ( signing_algorithm )
verify_response [ " KeyId " ] . should . equal ( key_arn )
verify_response [ " SignatureValid " ] . should . equal ( True )
2022-06-23 09:45:07 +00:00
@mock_kms
def test_verify_happy_with_invalid_signature ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 ,
)
verify_response [ " SigningAlgorithm " ] . should . equal ( signing_algorithm )
verify_response [ " KeyId " ] . should . equal ( key_arn )
verify_response [ " SignatureValid " ] . should . equal ( False )
@mock_kms
def test_verify_invalid_signing_algorithm ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
" 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 ' ] "
)
@mock_kms
def test_verify_invalid_message ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
" 1 validation error detected: Value at ' Message ' failed to satisfy constraint: Member must have length greater than or equal to 1 "
)
@mock_kms
def test_verify_empty_signature ( ) :
client = boto3 . client ( " kms " , region_name = " us-west-2 " )
key = client . create_key ( Description = " sign-key " , KeyUsage = " SIGN_VERIFY " )
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 " ]
err [ " Code " ] . should . equal ( " ValidationException " )
err [ " Message " ] . should . equal (
" 1 validation error detected: Value at ' Signature ' failed to satisfy constraint: Member must have length greater than or equal to 1 "
)
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 ]