KMS: Validate key specs (#6630)

* validate key specs

* fix failed tests

* add unittests

* fix typo

---------

Co-authored-by: Akira Noda <akira.noda@onecareer.com>
This commit is contained in:
Akira Noda 2023-08-19 19:53:54 +09:00 committed by GitHub
parent c072bac9ee
commit 27f025320a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 1 deletions

View File

@ -22,6 +22,7 @@ from .utils import (
generate_key_id, generate_key_id,
generate_master_key, generate_master_key,
generate_private_key, generate_private_key,
KeySpec,
) )
@ -302,6 +303,8 @@ class KmsBackend(BaseBackend):
- The resource is set to "*" - The resource is set to "*"
- The Action matches `describe_key` - The Action matches `describe_key`
""" """
if key_spec:
self.__ensure_valid_key_spec(key_spec)
key = Key( key = Key(
policy, policy,
key_usage, key_usage,
@ -615,6 +618,16 @@ class KmsBackend(BaseBackend):
) )
) )
def __ensure_valid_key_spec(self, key_spec: str) -> None:
if key_spec not in KeySpec.key_specs():
raise ValidationException(
(
"1 validation error detected: Value '{key_spec}' at 'KeySpec' failed "
"to satisfy constraint: Member must satisfy enum value set: "
"{valid_key_specs}"
).format(key_spec=key_spec, valid_key_specs=KeySpec.key_specs())
)
def sign( def sign(
self, key_id: str, message: bytes, signing_algorithm: str self, key_id: str, message: bytes, signing_algorithm: str
) -> Tuple[str, bytes, str]: ) -> Tuple[str, bytes, str]:

View File

@ -1,5 +1,6 @@
from collections import namedtuple from collections import namedtuple
from typing import Any, Dict, Tuple from typing import Any, Dict, Tuple, List
from enum import Enum
import io import io
import os import os
import struct import struct
@ -48,6 +49,28 @@ RESERVED_ALIASE_TARGET_KEY_IDS = {
RESERVED_ALIASES = list(RESERVED_ALIASE_TARGET_KEY_IDS.keys()) RESERVED_ALIASES = list(RESERVED_ALIASE_TARGET_KEY_IDS.keys())
class KeySpec(str, Enum):
# Asymmetric key specs
RSA_2048 = "RSA_2048"
RSA_3072 = "RSA_3072"
RSA_4096 = "RSA_4096"
ECC_NIST_P256 = "ECC_NIST_P256"
ECC_SECG_P256K1 = "ECC_SECG_P256K1"
ECC_NIST_P384 = "ECC_NIST_P384"
ECC_NIST_P512 = "ECC_NIST_P521"
SM2 = "SM2" # China Regions only
# Symmetric key specs
SYMMETRIC_DEFAULT = "SYMMETRIC_DEFAULT"
HMAC_224 = "HMAC_224"
HMAC_256 = "HMAC_256"
HMAC_284 = "HMAC_384"
HMAC_512 = "HMAC_512"
@classmethod
def key_specs(self) -> List[str]:
return sorted([item.value for item in KeySpec])
def generate_key_id(multi_region: bool = False) -> str: def generate_key_id(multi_region: bool = False) -> str:
key = str(mock_random.uuid4()) key = str(mock_random.uuid4())
# https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html # https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html

View File

@ -42,6 +42,21 @@ def test_create_key_without_description():
assert metadata["Description"] == "" assert metadata["Description"] == ""
@mock_kms
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)
@mock_kms @mock_kms
def test_create_key(): def test_create_key():
conn = boto3.client("kms", region_name="us-east-1") conn = boto3.client("kms", region_name="us-east-1")