Repository: getmoto/moto (python)

Issue:
KMS key alias not supported in `re_encrypt` operation
Thanks for the quick fix on #5957. I believe the same issue is happening with the `DestinationKeyId` argument for [`re_encrypt()`](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kms.html#KMS.Client.re_encrypt):

```
>>> kms.re_encrypt(CiphertextBlob=ciphertext, DestinationKeyId="alias/foo")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/rolandcrosby/src/scratch/venv/lib/python3.8/site-packages/botocore/client.py", line 530, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/Users/rolandcrosby/src/scratch/venv/lib/python3.8/site-packages/botocore/client.py", line 960, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.errorfactory.NotFoundException: An error occurred (NotFoundException) when calling the ReEncrypt operation: Invalid keyId alias/foo
```

Pull request:
KMS: re_encrypt() should accept alias
Fixes #5963 

Follow-up  to #5959 

Patch:
diff --git a/moto/elasticache/exceptions.py b/moto/elasticache/exceptions.py
index 8ce9ff14f..fe14cb050 100644
--- a/moto/elasticache/exceptions.py
+++ b/moto/elasticache/exceptions.py
@@ -1,3 +1,4 @@
+from typing import Any
 from moto.core.exceptions import RESTError
 
 EXCEPTION_RESPONSE = """<?xml version="1.0"?>
@@ -15,21 +16,20 @@ class ElastiCacheException(RESTError):
 
     code = 400
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, code: str, message: str, **kwargs: Any):
         kwargs.setdefault("template", "ecerror")
         self.templates["ecerror"] = EXCEPTION_RESPONSE
-        super().__init__(*args, **kwargs)
+        super().__init__(code, message)
 
 
 class PasswordTooShort(ElastiCacheException):
 
     code = 404
 
-    def __init__(self, **kwargs):
+    def __init__(self) -> None:
         super().__init__(
             "InvalidParameterValue",
             message="Passwords length must be between 16-128 characters.",
-            **kwargs,
         )
 
 
@@ -37,11 +37,10 @@ class PasswordRequired(ElastiCacheException):
 
     code = 404
 
-    def __init__(self, **kwargs):
+    def __init__(self) -> None:
         super().__init__(
             "InvalidParameterValue",
             message="No password was provided. If you want to create/update the user without password, please use the NoPasswordRequired flag.",
-            **kwargs,
         )
 
 
@@ -49,15 +48,13 @@ class UserAlreadyExists(ElastiCacheException):
 
     code = 404
 
-    def __init__(self, **kwargs):
-        super().__init__(
-            "UserAlreadyExists", message="User user1 already exists.", **kwargs
-        )
+    def __init__(self) -> None:
+        super().__init__("UserAlreadyExists", message="User user1 already exists.")
 
 
 class UserNotFound(ElastiCacheException):
 
     code = 404
 
-    def __init__(self, user_id, **kwargs):
-        super().__init__("UserNotFound", message=f"User {user_id} not found.", **kwargs)
+    def __init__(self, user_id: str):
+        super().__init__("UserNotFound", message=f"User {user_id} not found.")
diff --git a/moto/elasticache/models.py b/moto/elasticache/models.py
index 6b99ebab9..198d75dee 100644
--- a/moto/elasticache/models.py
+++ b/moto/elasticache/models.py
@@ -1,3 +1,4 @@
+from typing import List, Optional
 from moto.core import BaseBackend, BackendDict, BaseModel
 
 from .exceptions import UserAlreadyExists, UserNotFound
@@ -6,14 +7,14 @@ from .exceptions import UserAlreadyExists, UserNotFound
 class User(BaseModel):
     def __init__(
         self,
-        account_id,
-        region,
-        user_id,
-        user_name,
-        access_string,
-        engine,
-        no_password_required,
-        passwords=None,
+        account_id: str,
+        region: str,
+        user_id: str,
+        user_name: str,
+        access_string: str,
+        engine: str,
+        no_password_required: bool,
+        passwords: Optional[List[str]] = None,
     ):
         self.id = user_id
         self.name = user_name
@@ -23,7 +24,7 @@ class User(BaseModel):
         self.no_password_required = no_password_required
         self.status = "active"
         self.minimum_engine_version = "6.0"
-        self.usergroupids = []
+        self.usergroupids: List[str] = []
         self.region = region
         self.arn = f"arn:aws:elasticache:{self.region}:{account_id}:user:{self.id}"
 
@@ -31,7 +32,7 @@ class User(BaseModel):
 class ElastiCacheBackend(BaseBackend):
     """Implementation of ElastiCache APIs."""
 
-    def __init__(self, region_name, account_id):
+    def __init__(self, region_name: str, account_id: str):
         super().__init__(region_name, account_id)
         self.users = dict()
         self.users["default"] = User(
@@ -45,8 +46,14 @@ class ElastiCacheBackend(BaseBackend):
         )
 
     def create_user(
-        self, user_id, user_name, engine, passwords, access_string, no_password_required
-    ):
+        self,
+        user_id: str,
+        user_name: str,
+        engine: str,
+        passwords: List[str],
+        access_string: str,
+        no_password_required: bool,
+    ) -> User:
         if user_id in self.users:
             raise UserAlreadyExists
         user = User(
@@ -62,7 +69,7 @@ class ElastiCacheBackend(BaseBackend):
         self.users[user_id] = user
         return user
 
-    def delete_user(self, user_id):
+    def delete_user(self, user_id: str) -> User:
         if user_id in self.users:
             user = self.users[user_id]
             if user.status == "active":
@@ -70,7 +77,7 @@ class ElastiCacheBackend(BaseBackend):
             return user
         raise UserNotFound(user_id)
 
-    def describe_users(self, user_id):
+    def describe_users(self, user_id: Optional[str]) -> List[User]:
         """
         Only the `user_id` parameter is currently supported.
         Pagination is not yet implemented.
@@ -83,7 +90,7 @@ class ElastiCacheBackend(BaseBackend):
                 return [user]
             else:
                 raise UserNotFound(user_id)
-        return self.users.values()
+        return list(self.users.values())
 
 
 elasticache_backends = BackendDict(ElastiCacheBackend, "elasticache")
diff --git a/moto/elasticache/responses.py b/moto/elasticache/responses.py
index 087ad6814..273fa002d 100644
--- a/moto/elasticache/responses.py
+++ b/moto/elasticache/responses.py
@@ -1,20 +1,20 @@
 from moto.core.responses import BaseResponse
 from .exceptions import PasswordTooShort, PasswordRequired
-from .models import elasticache_backends
+from .models import elasticache_backends, ElastiCacheBackend
 
 
 class ElastiCacheResponse(BaseResponse):
     """Handler for ElastiCache requests and responses."""
 
-    def __init__(self):
+    def __init__(self) -> None:
         super().__init__(service_name="elasticache")
 
     @property
-    def elasticache_backend(self):
+    def elasticache_backend(self) -> ElastiCacheBackend:
         """Return backend instance specific for this region."""
         return elasticache_backends[self.current_account][self.region]
 
-    def create_user(self):
+    def create_user(self) -> str:
         params = self._get_params()
         user_id = params.get("UserId")
         user_name = params.get("UserName")
@@ -28,24 +28,24 @@ class ElastiCacheResponse(BaseResponse):
             raise PasswordTooShort
         access_string = params.get("AccessString")
         user = self.elasticache_backend.create_user(
-            user_id=user_id,
-            user_name=user_name,
-            engine=engine,
+            user_id=user_id,  # type: ignore[arg-type]
+            user_name=user_name,  # type: ignore[arg-type]
+            engine=engine,  # type: ignore[arg-type]
             passwords=passwords,
-            access_string=access_string,
+            access_string=access_string,  # type: ignore[arg-type]
             no_password_required=no_password_required,
         )
         template = self.response_template(CREATE_USER_TEMPLATE)
         return template.render(user=user)
 
-    def delete_user(self):
+    def delete_user(self) -> str:
         params = self._get_params()
         user_id = params.get("UserId")
-        user = self.elasticache_backend.delete_user(user_id=user_id)
+        user = self.elasticache_backend.delete_user(user_id=user_id)  # type: ignore[arg-type]
         template = self.response_template(DELETE_USER_TEMPLATE)
         return template.render(user=user)
 
-    def describe_users(self):
+    def describe_users(self) -> str:
         params = self._get_params()
         user_id = params.get("UserId")
         users = self.elasticache_backend.describe_users(user_id=user_id)
diff --git a/moto/kms/responses.py b/moto/kms/responses.py
index cf354d5c4..8e3d595eb 100644
--- a/moto/kms/responses.py
+++ b/moto/kms/responses.py
@@ -451,7 +451,7 @@ class KmsResponse(BaseResponse):
             "DestinationEncryptionContext", {}
         )
 
-        self._validate_cmk_id(destination_key_id)
+        self._validate_key_id(destination_key_id)
 
         (
             new_ciphertext_blob,
diff --git a/setup.cfg b/setup.cfg
index 228066350..15ba29675 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -229,7 +229,7 @@ disable = W,C,R,E
 enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
 
 [mypy]
-files= moto/a*,moto/b*,moto/c*,moto/d*,moto/ebs/,moto/ec2,moto/ec2instanceconnect,moto/ecr,moto/ecs,moto/efs,moto/eks,moto/es,moto/moto_api
+files= moto/a*,moto/b*,moto/c*,moto/d*,moto/ebs/,moto/ec2,moto/ec2instanceconnect,moto/ecr,moto/ecs,moto/efs,moto/eks,moto/elasticache,moto/es,moto/moto_api
 show_column_numbers=True
 show_error_codes = True
 disable_error_code=abstract


Test patch:
diff --git a/tests/test_kms/test_kms_encrypt.py b/tests/test_kms/test_kms_encrypt.py
index 6db34dcc3..a1b4c8aea 100644
--- a/tests/test_kms/test_kms_encrypt.py
+++ b/tests/test_kms/test_kms_encrypt.py
@@ -76,6 +76,24 @@ def test_encrypt_using_key_arn():
     kms.encrypt(KeyId=key_details["KeyMetadata"]["Arn"], Plaintext="hello")
 
 
+@mock_kms
+def test_re_encrypt_using_aliases():
+    client = boto3.client("kms", region_name="us-west-2")
+
+    key_1_id = client.create_key(Description="key 1")["KeyMetadata"]["KeyId"]
+    key_2_arn = client.create_key(Description="key 2")["KeyMetadata"]["Arn"]
+
+    key_alias = "alias/examplekey"
+    client.create_alias(AliasName=key_alias, TargetKeyId=key_2_arn)
+
+    encrypt_response = client.encrypt(KeyId=key_1_id, Plaintext="data")
+
+    client.re_encrypt(
+        CiphertextBlob=encrypt_response["CiphertextBlob"],
+        DestinationKeyId=key_alias,
+    )
+
+
 @pytest.mark.parametrize("plaintext", PLAINTEXT_VECTORS)
 @mock_kms
 def test_decrypt(plaintext):