diff --git a/moto/iam/models.py b/moto/iam/models.py index 62d63cf2f..8259a4296 100644 --- a/moto/iam/models.py +++ b/moto/iam/models.py @@ -59,6 +59,9 @@ SERVICE_NAME_CONVERSION = { } +LIMIT_KEYS_PER_USER = 2 + + class MFADevice(object): """MFA Device class.""" @@ -2423,6 +2426,12 @@ class IAMBackend(BaseBackend): def create_access_key(self, user_name=None, status="Active"): user = self.get_user(user_name) + keys = self.list_access_keys(user_name) + if len(keys) >= LIMIT_KEYS_PER_USER: + raise IAMLimitExceededException( + f"Cannot exceed quota for AccessKeysPerUser: {LIMIT_KEYS_PER_USER}" + ) + key = user.create_access_key(status) self.access_keys[key.physical_resource_id] = key return key diff --git a/tests/test_iam/test_iam.py b/tests/test_iam/test_iam.py index f013137c7..95f39d914 100644 --- a/tests/test_iam/test_iam.py +++ b/tests/test_iam/test_iam.py @@ -15,6 +15,8 @@ from datetime import datetime from uuid import uuid4 from urllib import parse +from moto.s3.responses import DEFAULT_REGION_NAME + MOCK_CERT = """-----BEGIN CERTIFICATE----- MIIBpzCCARACCQCY5yOdxCTrGjANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQKDAxt @@ -1422,6 +1424,22 @@ def test_create_access_key(): assert access_key["AccessKeyId"].startswith("AKIA") +@mock_iam +def test_limit_access_key_per_user(): + conn = boto3.client("iam", region_name=DEFAULT_REGION_NAME) + user_name = "test-user" + conn.create_user(UserName=user_name) + + conn.create_access_key(UserName=user_name) + conn.create_access_key(UserName=user_name) + with pytest.raises(ClientError) as ex: + conn.create_access_key(UserName=user_name) + + err = ex.value.response["Error"] + err["Code"].should.equal("LimitExceeded") + err["Message"].should.equal("Cannot exceed quota for AccessKeysPerUser: 2") + + @mock_iam def test_list_access_keys(): conn = boto3.client("iam", region_name="us-east-1")