From 65dd0f1660b2e1b0eb256c8c0e3f7460e6a9b1c3 Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Wed, 22 Sep 2021 20:37:03 +0000 Subject: [PATCH] KMS - duplicate boto tests (#3916) --- moto/kms/responses.py | 16 +- tests/test_kms/test_kms.py | 36 ++++ tests/test_kms/test_kms_boto3.py | 351 ++++++++++++++++++++++++++++++- 3 files changed, 394 insertions(+), 9 deletions(-) diff --git a/moto/kms/responses.py b/moto/kms/responses.py index 17783fb48..3626f6c12 100644 --- a/moto/kms/responses.py +++ b/moto/kms/responses.py @@ -5,6 +5,7 @@ import json import os import re +from moto.core import ACCOUNT_ID from moto.core.responses import BaseResponse from .models import kms_backends from .exceptions import ( @@ -14,7 +15,6 @@ from .exceptions import ( NotAuthorizedException, ) -ACCOUNT_ID = "012345678912" reserved_aliases = [ "alias/aws/ebs", "alias/aws/s3", @@ -227,8 +227,10 @@ class KmsResponse(BaseResponse): if self.kms_backend.alias_exists(alias_name): raise AlreadyExistsException( - "An alias with the name arn:aws:kms:{region}:012345678912:{alias_name} " - "already exists".format(region=self.region, alias_name=alias_name) + "An alias with the name arn:aws:kms:{region}:{account_id}:{alias_name} " + "already exists".format( + region=self.region, account_id=ACCOUNT_ID, alias_name=alias_name + ) ) self._validate_cmk_id(target_key_id) @@ -258,8 +260,8 @@ class KmsResponse(BaseResponse): response_aliases = [ { - "AliasArn": "arn:aws:kms:{region}:012345678912:{reserved_alias}".format( - region=region, reserved_alias=reserved_alias + "AliasArn": "arn:aws:kms:{region}:{account_id}:{reserved_alias}".format( + region=region, account_id=ACCOUNT_ID, reserved_alias=reserved_alias ), "AliasName": reserved_alias, } @@ -271,8 +273,8 @@ class KmsResponse(BaseResponse): for alias_name in aliases: response_aliases.append( { - "AliasArn": "arn:aws:kms:{region}:012345678912:{alias_name}".format( - region=region, alias_name=alias_name + "AliasArn": "arn:aws:kms:{region}:{account_id}:{alias_name}".format( + region=region, account_id=ACCOUNT_ID, alias_name=alias_name ), "AliasName": alias_name, "TargetKeyId": target_key_id, diff --git a/tests/test_kms/test_kms.py b/tests/test_kms/test_kms.py index 2e0af4c5a..e012bfeaf 100644 --- a/tests/test_kms/test_kms.py +++ b/tests/test_kms/test_kms.py @@ -28,6 +28,7 @@ def _get_encoded_value(plaintext): return plaintext.encode("utf-8") +# Has boto3 equivalent @mock_kms_deprecated def test_describe_key(): conn = boto.kms.connect_to_region("us-west-2") @@ -41,6 +42,7 @@ def test_describe_key(): key["KeyMetadata"]["KeyUsage"].should.equal("ENCRYPT_DECRYPT") +# Has boto3 equivalent @mock_kms_deprecated def test_describe_key_via_alias(): conn = boto.kms.connect_to_region("us-west-2") @@ -57,6 +59,7 @@ def test_describe_key_via_alias(): alias_key["KeyMetadata"]["Arn"].should.equal(key["KeyMetadata"]["Arn"]) +# Has boto3 equivalent @mock_kms_deprecated def test_describe_key_via_alias_not_found(): conn = boto.kms.connect_to_region("us-west-2") @@ -72,6 +75,7 @@ def test_describe_key_via_alias_not_found(): ) +# Has boto3 equivalent @mock_kms_deprecated def test_describe_key_via_arn(): conn = boto.kms.connect_to_region("us-west-2") @@ -86,12 +90,14 @@ def test_describe_key_via_arn(): the_key["KeyMetadata"]["KeyId"].should.equal(key["KeyMetadata"]["KeyId"]) +# Has boto3 equivalent @mock_kms_deprecated def test_describe_missing_key(): conn = boto.kms.connect_to_region("us-west-2") conn.describe_key.when.called_with("not-a-key").should.throw(NotFoundException) +# Has boto3 equivalent @mock_kms_deprecated def test_list_keys(): conn = boto.kms.connect_to_region("us-west-2") @@ -107,6 +113,7 @@ def test_list_keys(): keys["Keys"].should.have.length_of(2) +# Has boto3 equivalent @mock_kms_deprecated def test_enable_key_rotation(): conn = boto.kms.connect_to_region("us-west-2") @@ -121,6 +128,7 @@ def test_enable_key_rotation(): conn.get_key_rotation_status(key_id)["KeyRotationEnabled"].should.equal(True) +# Has boto3 equivalent @mock_kms_deprecated def test_enable_key_rotation_via_arn(): conn = boto.kms.connect_to_region("us-west-2") @@ -135,6 +143,7 @@ def test_enable_key_rotation_via_arn(): conn.get_key_rotation_status(key_id)["KeyRotationEnabled"].should.equal(True) +# Has boto3 equivalent @mock_kms_deprecated def test_enable_key_rotation_with_missing_key(): conn = boto.kms.connect_to_region("us-west-2") @@ -143,6 +152,7 @@ def test_enable_key_rotation_with_missing_key(): ) +# Has boto3 equivalent @mock_kms_deprecated def test_enable_key_rotation_with_alias_name_should_fail(): conn = boto.kms.connect_to_region("us-west-2") @@ -161,6 +171,7 @@ def test_enable_key_rotation_with_alias_name_should_fail(): ) +# Has boto3 equivalent @mock_kms_deprecated def test_disable_key_rotation(): conn = boto.kms.connect_to_region("us-west-2") @@ -177,6 +188,7 @@ def test_disable_key_rotation(): conn.get_key_rotation_status(key_id)["KeyRotationEnabled"].should.equal(False) +# Has boto3 equivalent @mock_kms_deprecated def test_generate_data_key(): conn = boto.kms.connect_to_region("us-west-2") @@ -199,6 +211,7 @@ def test_generate_data_key(): response["KeyId"].should.equal(key_arn) +# Has boto3 equivalent @mock_kms_deprecated def test_disable_key_rotation_with_missing_key(): conn = boto.kms.connect_to_region("us-west-2") @@ -207,6 +220,7 @@ def test_disable_key_rotation_with_missing_key(): ) +# Has boto3 equivalent @mock_kms_deprecated def test_get_key_rotation_status_with_missing_key(): conn = boto.kms.connect_to_region("us-west-2") @@ -215,6 +229,7 @@ def test_get_key_rotation_status_with_missing_key(): ) +# Has boto3 equivalent @mock_kms_deprecated def test_get_key_rotation_status(): conn = boto.kms.connect_to_region("us-west-2") @@ -227,6 +242,7 @@ def test_get_key_rotation_status(): conn.get_key_rotation_status(key_id)["KeyRotationEnabled"].should.equal(False) +# Has boto3 equivalent @mock_kms_deprecated def test_create_key_defaults_key_rotation(): conn = boto.kms.connect_to_region("us-west-2") @@ -239,6 +255,7 @@ def test_create_key_defaults_key_rotation(): conn.get_key_rotation_status(key_id)["KeyRotationEnabled"].should.equal(False) +# Has boto3 equivalent @mock_kms_deprecated def test_get_key_policy(): conn = boto.kms.connect_to_region("us-west-2") @@ -252,6 +269,7 @@ def test_get_key_policy(): policy["Policy"].should.equal("my policy") +# Has boto3 equivalent @mock_kms_deprecated def test_get_key_policy_via_arn(): conn = boto.kms.connect_to_region("us-west-2") @@ -264,6 +282,7 @@ def test_get_key_policy_via_arn(): policy["Policy"].should.equal("my policy") +# Has boto3 equivalent @mock_kms_deprecated def test_put_key_policy(): conn = boto.kms.connect_to_region("us-west-2") @@ -278,6 +297,7 @@ def test_put_key_policy(): policy["Policy"].should.equal("new policy") +# Has boto3 equivalent @mock_kms_deprecated def test_put_key_policy_via_arn(): conn = boto.kms.connect_to_region("us-west-2") @@ -292,6 +312,7 @@ def test_put_key_policy_via_arn(): policy["Policy"].should.equal("new policy") +# Has boto3 equivalent @mock_kms_deprecated def test_put_key_policy_via_alias_should_not_update(): conn = boto.kms.connect_to_region("us-west-2") @@ -311,6 +332,7 @@ def test_put_key_policy_via_alias_should_not_update(): policy["Policy"].should.equal("my policy") +# Has boto3 equivalent @mock_kms_deprecated def test_list_key_policies(): conn = boto.kms.connect_to_region("us-west-2") @@ -324,6 +346,7 @@ def test_list_key_policies(): policies["PolicyNames"].should.equal(["default"]) +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__returns_none_if_correct(): kms = boto.connect_kms() @@ -335,6 +358,7 @@ def test__create_alias__returns_none_if_correct(): resp.should.be.none +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__raises_if_reserved_alias(): kms = boto.connect_kms() @@ -360,6 +384,7 @@ def test__create_alias__raises_if_reserved_alias(): ex.status.should.equal(400) +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__can_create_multiple_aliases_for_same_key_id(): kms = boto.connect_kms() @@ -371,6 +396,7 @@ def test__create_alias__can_create_multiple_aliases_for_same_key_id(): kms.create_alias("alias/my-alias5", key_id).should.be.none +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__raises_if_wrong_prefix(): kms = boto.connect_kms() @@ -390,6 +416,7 @@ def test__create_alias__raises_if_wrong_prefix(): ex.status.should.equal(400) +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__raises_if_duplicate(): region = "us-west-2" @@ -422,6 +449,7 @@ def test__create_alias__raises_if_duplicate(): ex.status.should.equal(400) +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__raises_if_alias_has_restricted_characters(): kms = boto.connect_kms() @@ -454,6 +482,7 @@ def test__create_alias__raises_if_alias_has_restricted_characters(): ex.status.should.equal(400) +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__raises_if_alias_has_colon_character(): # For some reason, colons are not accepted for an alias, even though they @@ -480,6 +509,7 @@ def test__create_alias__raises_if_alias_has_colon_character(): ex.status.should.equal(400) +# Has boto3 equivalent @pytest.mark.parametrize("alias_name", ["alias/my-alias_/", "alias/my_alias-/"]) @mock_kms_deprecated def test__create_alias__accepted_characters(alias_name): @@ -490,6 +520,7 @@ def test__create_alias__accepted_characters(alias_name): kms.create_alias(alias_name, key_id) +# Has boto3 equivalent @mock_kms_deprecated def test__create_alias__raises_if_target_key_id_is_existing_alias(): kms = boto.connect_kms() @@ -511,6 +542,7 @@ def test__create_alias__raises_if_target_key_id_is_existing_alias(): ex.status.should.equal(400) +# Has boto3 equivalent @mock_kms_deprecated def test__delete_alias(): kms = boto.connect_kms() @@ -535,6 +567,7 @@ def test__delete_alias(): kms.create_alias(alias, key_id) +# Has boto3 equivalent @mock_kms_deprecated def test__delete_alias__raises_if_wrong_prefix(): kms = boto.connect_kms() @@ -551,6 +584,7 @@ def test__delete_alias__raises_if_wrong_prefix(): ex.status.should.equal(400) +# Has boto3 equivalent @mock_kms_deprecated def test__delete_alias__raises_if_alias_is_not_found(): region = "us-west-2" @@ -574,6 +608,7 @@ def test__delete_alias__raises_if_alias_is_not_found(): ex.status.should.equal(400) +# Has boto3 equivalent @mock_kms_deprecated def test__list_aliases(): region = "eu-west-1" @@ -735,6 +770,7 @@ def test_key_tag_added_arn_based_happy(): _check_tags(key_id, tags, client) +# Has boto3 equivalent @mock_kms_deprecated def test_key_tagging_sad(): b = KmsBackend() diff --git a/tests/test_kms/test_kms_boto3.py b/tests/test_kms/test_kms_boto3.py index 34d0a6a4d..79a7f2ad6 100644 --- a/tests/test_kms/test_kms_boto3.py +++ b/tests/test_kms/test_kms_boto3.py @@ -9,6 +9,7 @@ import os import boto3 import botocore.exceptions +from botocore.exceptions import ClientError import sure # noqa from freezegun import freeze_time import pytest @@ -16,6 +17,7 @@ import pytest from moto import mock_kms from moto.core import ACCOUNT_ID + PLAINTEXT_VECTORS = [ b"some encodeable plaintext", b"some unencodeable plaintext \xec\x8a\xcf\xb6r\xe9\xb5\xeb\xff\xa23\x16", @@ -50,6 +52,7 @@ def test_create_key(): KeyUsage="ENCRYPT_DECRYPT", Tags=[{"TagKey": "project", "TagValue": "moto"}], ) + print(key["KeyMetadata"]) key["KeyMetadata"]["Arn"].should.equal( "arn:aws:kms:us-east-1:{}:key/{}".format( @@ -112,11 +115,12 @@ def test_create_key(): key["KeyMetadata"]["SigningAlgorithms"].should.equal(["ECDSA_SHA_512"]) +@pytest.mark.parametrize("id_or_arn", ["KeyId", "Arn"]) @mock_kms -def test_describe_key(): +def test_describe_key(id_or_arn): client = boto3.client("kms", region_name="us-east-1") response = client.create_key(Description="my key", KeyUsage="ENCRYPT_DECRYPT",) - key_id = response["KeyMetadata"]["KeyId"] + key_id = response["KeyMetadata"][id_or_arn] response = client.describe_key(KeyId=key_id) @@ -161,6 +165,51 @@ def test_get_key_policy_default(): ) +@mock_kms +def test_describe_key_via_alias(): + client = boto3.client("kms", region_name="us-east-1") + response = client.create_key(Description="my key") + key_id = response["KeyMetadata"]["KeyId"] + + 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") + response = client.create_key(Description="my key") + key_id = response["KeyMetadata"]["KeyId"] + + 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: + alias_arn = "arn:aws:kms:us-east-1:{}:{}".format(ACCOUNT_ID, name) + aliases.should.contain( + {"AliasName": name, "AliasArn": alias_arn, "TargetKeyId": key_id} + ) + + +@mock_kms +def test_list_aliases(): + client = boto3.client("kms", region_name="us-east-1") + client.create_key(Description="my key") + + aliases = client.list_aliases()["Aliases"] + aliases.should.have.length_of(4) + default_alias_names = ["aws/ebs", "aws/s3", "aws/redshift", "aws/rds"] + for name in default_alias_names: + full_name = "alias/{}".format(name) + arn = "arn:aws:kms:us-east-1:{}:{}".format(ACCOUNT_ID, full_name) + aliases.should.contain({"AliasName": full_name, "AliasArn": arn}) + + @pytest.mark.parametrize( "key_id", [ @@ -178,6 +227,54 @@ def test_describe_key_via_alias_invalid_alias(key_id): client.describe_key(KeyId=key_id) +@mock_kms +def test_list_keys(): + client = boto3.client("kms", region_name="us-east-1") + k1 = client.create_key(Description="key1")["KeyMetadata"] + k2 = client.create_key(Description="key2")["KeyMetadata"] + + 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") + key = client.create_key(Description="key1")["KeyMetadata"] + key_id = key[id_or_arn] + + 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") + key = client.create_key(Description="my key")["KeyMetadata"] + key_id = key["KeyId"] + + 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") + + @mock_kms def test_generate_data_key(): kms = boto3.client("kms", region_name="us-west-2") @@ -412,6 +509,50 @@ def test_list_resource_tags_with_arn(): assert response["Tags"][0]["TagValue"] == "string" +@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") + key = client.create_key(Description="cancel-key-deletion") + response = client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"]) + + keyid = response["KeyId"] + client.tag_resource( + KeyId=keyid, + Tags=[ + {"TagKey": "key1", "TagValue": "s1"}, + {"TagKey": "key2", "TagValue": "s2"}, + ], + ) + + client.untag_resource(KeyId=keyid, TagKeys=["key2"]) + + tags = client.list_resource_tags(KeyId=keyid)["Tags"] + tags.should.equal([{"TagKey": "key1", "TagValue": "s1"}]) + + @pytest.mark.parametrize( "kwargs,expected_key_length", ( @@ -685,3 +826,209 @@ def test_put_key_policy_key_not_found(): PolicyName="default", Policy="new policy", ) + + +@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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"][id_or_arn] + + r = client.put_key_policy(KeyId=key_id, PolicyName="default", Policy="policy 2.0") + + 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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + 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") + response["Policy"].should.equal("initial policy") + + +@mock_kms +def test_list_key_policies(): + client = boto3.client("kms", region_name="us-east-1") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + + 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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + + 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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + + 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( + "1 validation error detected: Value '{}' at 'aliasName' failed to satisfy constraint: Member must satisfy regular expression pattern: ^[a-zA-Z0-9:/_-]+$".format( + name + ) + ) + + +@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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + + 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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + + 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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + 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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + + 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") + key = client.create_key(Description="key1", Policy="initial policy") + key_id = key["KeyMetadata"]["KeyId"] + 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") + + key = client.create_key(Description="key1", Policy="initial policy") + client.create_alias(AliasName="alias/a1", TargetKeyId=key["KeyMetadata"]["KeyId"]) + + key = client.create_key(Description="key2", Policy="initial policy") + client.create_alias(AliasName="alias/a2", TargetKeyId=key["KeyMetadata"]["KeyId"]) + + client.delete_alias(AliasName="alias/a1") + + # we can create the alias again, since it has been deleted + client.create_alias(AliasName="alias/a1", TargetKeyId=key["KeyMetadata"]["KeyId"]) + + +@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." + )