From c8db699f3c1855231469b3f35e12a28371e5e022 Mon Sep 17 00:00:00 2001 From: Akira Noda <61897166+tsugumi-sys@users.noreply.github.com> Date: Sat, 23 Mar 2024 05:33:34 +0900 Subject: [PATCH] ACMPCA: Adding validation and unittests for revocation configuration (#7503) --- moto/acmpca/exceptions.py | 10 ++++++ moto/acmpca/models.py | 19 ++++++----- tests/test_acmpca/test_acmpca.py | 54 ++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/moto/acmpca/exceptions.py b/moto/acmpca/exceptions.py index 1107cdb12..9a584d67c 100644 --- a/moto/acmpca/exceptions.py +++ b/moto/acmpca/exceptions.py @@ -6,3 +6,13 @@ from moto.core.exceptions import JsonRESTError class ResourceNotFoundException(JsonRESTError): def __init__(self, arn: str): super().__init__("ResourceNotFoundException", f"Resource {arn} not found") + + +class InvalidS3ObjectAclInCrlConfiguration(JsonRESTError): + code = 400 + + def __init__(self, value: str): + super().__init__( + "InvalidS3ObjectAclInCrlConfiguration", + f"Invalid value for parameter RevocationConfiguration.CrlConfiguration.S3ObjectAcl, value: {value}, valid values: ['PUBLIC_READ', 'BUCKET_OWNER_FULL_CONTROL']", + ) diff --git a/moto/acmpca/models.py b/moto/acmpca/models.py index 3caf89c71..27a4565ec 100644 --- a/moto/acmpca/models.py +++ b/moto/acmpca/models.py @@ -16,7 +16,7 @@ from moto.core.utils import unix_time, utcnow from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService -from .exceptions import ResourceNotFoundException +from .exceptions import InvalidS3ObjectAclInCrlConfiguration, ResourceNotFoundException class CertificateAuthority(BaseModel): @@ -132,13 +132,16 @@ class CertificateAuthority(BaseModel): if revocation_configuration is not None: self.revocation_configuration = revocation_configuration if "CrlConfiguration" in self.revocation_configuration: - if ( - "S3ObjectAcl" - not in self.revocation_configuration["CrlConfiguration"] - ): - self.revocation_configuration["CrlConfiguration"]["S3ObjectAcl"] = ( - "PUBLIC_READ" - ) + acl = self.revocation_configuration["CrlConfiguration"].get( + "S3ObjectAcl", None + ) + if acl is None: + self.revocation_configuration["CrlConfiguration"][ + "S3ObjectAcl" + ] = "PUBLIC_READ" + else: + if acl not in ["PUBLIC_READ", "BUCKET_OWNER_FULL_CONTROL"]: + raise InvalidS3ObjectAclInCrlConfiguration(acl) @property def certificate_bytes(self) -> bytes: diff --git a/tests/test_acmpca/test_acmpca.py b/tests/test_acmpca/test_acmpca.py index 56d415711..e68345fc9 100644 --- a/tests/test_acmpca/test_acmpca.py +++ b/tests/test_acmpca/test_acmpca.py @@ -200,6 +200,60 @@ def test_update_certificate_authority(): assert ca["Status"] == "DISABLED" assert "LastStateChangeAt" in ca + # test when `RevocationConfiguration` passed to request parameters + client.update_certificate_authority( + CertificateAuthorityArn=ca_arn, + RevocationConfiguration={ + "CrlConfiguration": { + "Enabled": True, + } + }, + ) + ca = client.describe_certificate_authority(CertificateAuthorityArn=ca_arn)[ + "CertificateAuthority" + ] + revocation_crl_conf = ca["RevocationConfiguration"]["CrlConfiguration"] + assert revocation_crl_conf["Enabled"] + assert ( + revocation_crl_conf["S3ObjectAcl"] == "PUBLIC_READ" + ) # check if default value is applied. + + client.update_certificate_authority( + CertificateAuthorityArn=ca_arn, + RevocationConfiguration={ + "CrlConfiguration": { + "Enabled": True, + "S3ObjectAcl": "BUCKET_OWNER_FULL_CONTROL", + } + }, + ) + ca = client.describe_certificate_authority(CertificateAuthorityArn=ca_arn)[ + "CertificateAuthority" + ] + revocation_crl_conf = ca["RevocationConfiguration"]["CrlConfiguration"] + assert ( + revocation_crl_conf["S3ObjectAcl"] == "BUCKET_OWNER_FULL_CONTROL" + ) # check if the passed parameter is applied. + + # test when invald value passed for RevocationConfiguration.CrlConfiguration.S3ObjectAcl + invalid_s3object_acl = "INVALID_VALUE" + with pytest.raises(ClientError) as exc: + client.update_certificate_authority( + CertificateAuthorityArn=ca_arn, + RevocationConfiguration={ + "CrlConfiguration": { + "Enabled": True, + "S3ObjectAcl": invalid_s3object_acl, + } + }, + ) + err = exc.value.response["Error"] + assert err["Code"] == "InvalidS3ObjectAclInCrlConfiguration" + assert ( + err["Message"] + == f"Invalid value for parameter RevocationConfiguration.CrlConfiguration.S3ObjectAcl, value: {invalid_s3object_acl}, valid values: ['PUBLIC_READ', 'BUCKET_OWNER_FULL_CONTROL']" + ) + @mock_aws def test_delete_certificate_authority():