Repository: getmoto/moto
Pull request #7503 (2024-03-21 10:06:10)

ACMPCA: Adding validation and unittests for revocation configuration
- Adding parameter validation for revocation configuration.
- Adding unittests to improve unittest coverage for `set_revocation_configuration` method in `moto/acmpca/models.py`
- Adding unittests for validation.

boto3 documentation: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/acm-pca/client/update_certificate_authority.html

aws api documentation: https://docs.aws.amazon.com/privateca/latest/APIReference/API_CrlConfiguration.html#privateca-Type-CrlConfiguration-S3ObjectAcl


tsugumi-sys: @bblommers 
I don't think the failure of this github action has anything to do with my changes.

https://github.com/getmoto/moto/actions/runs/8373118600/job/22925602827?pr=7503
![image](https://github.com/getmoto/moto/assets/61897166/ad75c339-8018-41cd-b523-c35b0bb945e0)

bblommers: If you can just resolve the conflict, I'd be happy to merge
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/7503?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 94.07%. Comparing base [(`9aef694`)](https://app.codecov.io/gh/getmoto/moto/commit/9aef6944da6a6f1b84be99cefb34f1724e6ca58f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`ffa8d60`)](https://app.codecov.io/gh/getmoto/moto/pull/7503?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).
> Report is 130 commits behind head on master.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #7503      +/-   ##
==========================================
- Coverage   95.88%   94.07%   -1.82%     
==========================================
  Files         843     1070     +227     
  Lines       82578    91877    +9299     
==========================================
+ Hits        79178    86430    +7252     
- Misses       3400     5447    +2047     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/7503/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/7503/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `29.60% <0.00%> (-2.93%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/7503/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `94.04% <100.00%> (-1.81%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/7503?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).


Patch:
diff --git a/moto/acm/models.py b/moto/acm/models.py
index 585d99530..1889ff36c 100644
--- a/moto/acm/models.py
+++ b/moto/acm/models.py
@@ -409,15 +409,6 @@ class AWSCertificateManagerBackend(BaseBackend):
         self._certificates: Dict[str, CertBundle] = {}
         self._idempotency_tokens: Dict[str, Any] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "acm-pca"
-        )
-
     def set_certificate_in_use_by(self, arn: str, load_balancer_name: str) -> None:
         if arn not in self._certificates:
             raise CertificateNotFound(arn=arn, account_id=self.account_id)
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/moto/applicationautoscaling/models.py b/moto/applicationautoscaling/models.py
index 50ce4c58f..41e7f2dda 100644
--- a/moto/applicationautoscaling/models.py
+++ b/moto/applicationautoscaling/models.py
@@ -73,15 +73,6 @@ class ApplicationAutoscalingBackend(BaseBackend):
         self.policies: Dict[str, FakeApplicationAutoscalingPolicy] = {}
         self.scheduled_actions: List[FakeScheduledAction] = list()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "application-autoscaling"
-        )
-
     def describe_scalable_targets(
         self, namespace: str, r_ids: Union[None, List[str]], dimension: Union[None, str]
     ) -> List["FakeScalableTarget"]:
diff --git a/moto/athena/models.py b/moto/athena/models.py
index 38d4449db..327405c4f 100644
--- a/moto/athena/models.py
+++ b/moto/athena/models.py
@@ -173,15 +173,6 @@ class AthenaBackend(BaseBackend):
             name="primary", description="", configuration=dict(), tags=[]
         )
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "athena"
-        )
-
     def create_work_group(
         self,
         name: str,
diff --git a/moto/autoscaling/models.py b/moto/autoscaling/models.py
index 5d03c85bf..5f22a7727 100644
--- a/moto/autoscaling/models.py
+++ b/moto/autoscaling/models.py
@@ -882,17 +882,6 @@ class AutoScalingBackend(BaseBackend):
         self.elb_backend: ELBBackend = elb_backends[self.account_id][region_name]
         self.elbv2_backend: ELBv2Backend = elbv2_backends[self.account_id][region_name]
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, Any]]:  # type: ignore[misc]
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "autoscaling"
-        ) + BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "autoscaling-plans"
-        )
-
     def create_launch_configuration(
         self,
         name: str,
diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py
index bba211abc..37e9c4c1f 100644
--- a/moto/awslambda/models.py
+++ b/moto/awslambda/models.py
@@ -1893,15 +1893,6 @@ class LambdaBackend(BaseBackend):
         self._event_source_mappings: Dict[str, EventSourceMapping] = {}
         self._layers = LayerStorage()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "lambda"
-        )
-
     def create_alias(
         self,
         name: str,
diff --git a/moto/cloudwatch/models.py b/moto/cloudwatch/models.py
index 9a8da6fa8..60a5dd03f 100644
--- a/moto/cloudwatch/models.py
+++ b/moto/cloudwatch/models.py
@@ -442,15 +442,6 @@ class CloudWatchBackend(BaseBackend):
         self.paged_metric_data: Dict[str, List[MetricDatumBase]] = {}
         self.tagger = TaggingService()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "monitoring"
-        )
-
     @property
     # Retrieve a list of all OOTB metrics that are provided by metrics providers
     # Computed on the fly
diff --git a/moto/codecommit/models.py b/moto/codecommit/models.py
index 3f87569ef..49eb5391e 100644
--- a/moto/codecommit/models.py
+++ b/moto/codecommit/models.py
@@ -40,15 +40,6 @@ class CodeCommitBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.repositories: Dict[str, CodeCommit] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "codecommit"
-        )
-
     def create_repository(
         self, repository_name: str, repository_description: str
     ) -> Dict[str, str]:
diff --git a/moto/config/models.py b/moto/config/models.py
index aaea0dc4e..171e6d4fc 100644
--- a/moto/config/models.py
+++ b/moto/config/models.py
@@ -917,15 +917,6 @@ class ConfigBackend(BaseBackend):
         self.config_schema: Optional[AWSServiceSpec] = None
         self.retention_configuration: Optional[RetentionConfiguration] = None
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, Any]]:  # type: ignore[misc]
-        """List of dicts representing default VPC endpoints for this service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "config"
-        )
-
     def _validate_resource_types(self, resource_list: List[str]) -> None:
         if not self.config_schema:
             self.config_schema = AWSServiceSpec(
diff --git a/moto/datasync/models.py b/moto/datasync/models.py
index a5d0437a8..3834c65a7 100644
--- a/moto/datasync/models.py
+++ b/moto/datasync/models.py
@@ -103,15 +103,6 @@ class DataSyncBackend(BaseBackend):
         self.tasks: Dict[str, Task] = OrderedDict()
         self.task_executions: Dict[str, TaskExecution] = OrderedDict()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, Any]]:  # type: ignore[misc]
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "datasync"
-        )
-
     def create_location(
         self, location_uri: str, typ: str, metadata: Dict[str, Any]
     ) -> str:
diff --git a/moto/dms/models.py b/moto/dms/models.py
index 82d8965b0..13d31adfe 100644
--- a/moto/dms/models.py
+++ b/moto/dms/models.py
@@ -18,15 +18,6 @@ class DatabaseMigrationServiceBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.replication_tasks: Dict[str, "FakeReplicationTask"] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, Any]]:  # type: ignore[misc]
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "dms"
-        )
-
     def create_replication_task(
         self,
         replication_task_identifier: str,
diff --git a/moto/ds/models.py b/moto/ds/models.py
index 0dd46d45c..ec1945e38 100644
--- a/moto/ds/models.py
+++ b/moto/ds/models.py
@@ -200,15 +200,6 @@ class DirectoryServiceBackend(BaseBackend):
         self.directories: Dict[str, Directory] = {}
         self.tagger = TaggingService()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """List of dicts representing default VPC endpoints for this service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "ds"
-        )
-
     def _verify_subnets(self, region: str, vpc_settings: Dict[str, Any]) -> None:
         """Verify subnets are valid, else raise an exception.
 
diff --git a/moto/ec2/models/__init__.py b/moto/ec2/models/__init__.py
index d474f9050..9f96a95e9 100644
--- a/moto/ec2/models/__init__.py
+++ b/moto/ec2/models/__init__.py
@@ -163,17 +163,6 @@ class EC2Backend(
             self.create_subnet(vpc.id, cidr_block, availability_zone=az_name)
             ip[2] += 16  # type: ignore
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, Any]]:  # type: ignore[misc]
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "ec2"
-        ) + BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "ec2messages"
-        )
-
     # Use this to generate a proper error template response when in a response
     # handler.
     def raise_error(self, code: str, message: str) -> None:
diff --git a/moto/ec2/models/vpcs.py b/moto/ec2/models/vpcs.py
index d20b5490b..d4d856614 100644
--- a/moto/ec2/models/vpcs.py
+++ b/moto/ec2/models/vpcs.py
@@ -6,6 +6,7 @@ from collections import defaultdict
 from operator import itemgetter
 from typing import Any, Dict, List, Optional
 
+from moto.core.base_backend import BaseBackend
 from moto.core.common_models import CloudFormationModel
 
 from ..exceptions import (
@@ -37,52 +38,290 @@ from ..utils import (
 from .availability_zones_and_regions import RegionsAndZonesBackend
 from .core import TaggedEC2Resource
 
-# We used to load the entirety of Moto into memory, and check every module if it's supported
-# But having a fixed list is much more performant
-# Maintaining it is more difficult, but the contents of this list does not change very often
+# List of Moto services that exposes a non-standard EndpointService config
 IMPLEMENTED_ENDPOINT_SERVICES = [
-    "acm",
-    "applicationautoscaling",
+    "cloudformation",
+    "codepipeline",
+    "dynamodb",
+    "ecr",
+    "firehose",
+    "iot",
+    "kinesis",
+    "redshiftdata",
+    "route53resolver",
+    "s3",
+    "sagemaker",
+]
+# List of names used by AWS that are implemented by our services
+COVERED_ENDPOINT_SERVICES = IMPLEMENTED_ENDPOINT_SERVICES + [
+    "ecr.api",
+    "ecr.dkr",
+    "iot.data",
+    "kinesis-firehose",
+    "kinesis-streams",
+    "redshift-data",
+    "sagemaker.api",
+]
+# All endpoints offered by AWS
+# We expose a sensible default for these services, if we don't implement a service-specific non-standard
+AWS_ENDPOINT_SERVICES = [
+    "access-analyzer",
+    "account",
+    "acm-pca",
+    "airflow.api",
+    "airflow.env",
+    "airflow.ops",
+    "analytics-omics",
+    "app-integrations",
+    "appconfig",
+    "appconfigdata",
+    "application-autoscaling",
+    "appmesh",
+    "appmesh-envoy-management",
+    "apprunner",
+    "apprunner.requests",
+    "appstream.api",
+    "appstream.streaming",
+    "appsync-api",
+    "aps",
+    "aps-workspaces",
     "athena",
+    "auditmanager",
     "autoscaling",
-    "awslambda",
+    "autoscaling-plans",
+    "awsconnector",
+    "b2bi",
+    "backup",
+    "backup-gateway",
+    "batch",
+    "bedrock",
+    "bedrock-agent",
+    "bedrock-agent-runtime",
+    "bedrock-runtime",
+    "billingconductor",
+    "braket",
+    "cases",
+    "cassandra",
+    "cassandra-fips",
+    "cleanrooms",
+    "cloudcontrolapi",
+    "cloudcontrolapi-fips",
+    "clouddirectory",
     "cloudformation",
-    "cloudwatch",
+    "cloudhsmv2",
+    "cloudtrail",
+    "codeartifact.api",
+    "codeartifact.repositories",
+    "codebuild",
+    "codebuild-fips",
     "codecommit",
+    "codecommit-fips",
+    "codedeploy",
+    "codedeploy-commands-secure",
+    "codeguru-profiler",
+    "codeguru-reviewer",
     "codepipeline",
+    "codestar-connections.api",
+    "codewhisperer",
+    "comprehend",
+    "comprehendmedical",
     "config",
+    "connect-campaigns",
+    "console",
+    "control-storage-omics",
+    "data-servicediscovery",
+    "data-servicediscovery-fips",
+    "databrew",
+    "dataexchange",
     "datasync",
+    "datazone",
+    "deviceadvisor.iot",
+    "devops-guru",
     "dms",
+    "dms-fips",
+    "drs",
     "ds",
     "dynamodb",
+    "ebs",
     "ec2",
-    "ecr",
+    "ec2messages",
+    "ecr.api",
+    "ecr.dkr",
     "ecs",
+    "ecs-agent",
+    "ecs-telemetry",
+    "eks",
+    "eks-auth",
+    "elastic-inference.runtime",
+    "elasticache",
+    "elasticache-fips",
     "elasticbeanstalk",
-    "elbv2",
-    "emr",
+    "elasticbeanstalk-health",
+    "elasticfilesystem",
+    "elasticfilesystem-fips",
+    "elasticloadbalancing",
+    "elasticmapreduce",
+    "email-smtp",
+    "emr-containers",
+    "emr-serverless",
+    "emrwal.prod",
+    "entityresolution",
     "events",
-    "firehose",
+    "evidently",
+    "evidently-dataplane",
+    "execute-api",
+    "finspace",
+    "finspace-api",
+    "fis",
+    "forecast",
+    "forecast-fips",
+    "forecastquery",
+    "forecastquery-fips",
+    "frauddetector",
+    "fsx",
+    "fsx-fips",
+    "git-codecommit",
+    "git-codecommit-fips",
     "glue",
-    "iot",
-    "kinesis",
+    "grafana",
+    "grafana-workspace",
+    "greengrass",
+    "groundstation",
+    "guardduty-data",
+    "guardduty-data-fips",
+    "healthlake",
+    "identitystore",
+    "imagebuilder",
+    "inspector2",
+    "iot.credentials",
+    "iot.data",
+    "iot.fleethub.api",
+    "iotfleetwise",
+    "iotroborunner",
+    "iotsitewise.api",
+    "iotsitewise.data",
+    "iottwinmaker.api",
+    "iottwinmaker.data",
+    "iotwireless.api",
+    "kendra",
+    "kinesis-firehose",
+    "kinesis-streams",
     "kms",
+    "kms-fips",
+    "lakeformation",
+    "lambda",
+    "license-manager",
+    "license-manager-fips",
+    "license-manager-user-subscriptions",
     "logs",
+    "lookoutequipment",
+    "lookoutmetrics",
+    "lookoutvision",
+    "lorawan.cups",
+    "lorawan.lns",
+    "m2",
+    "macie2",
+    "managedblockchain-query",
+    "managedblockchain.bitcoin.mainnet",
+    "managedblockchain.bitcoin.testnet",
+    "mediaconnect",
+    "medical-imaging",
+    "memory-db",
+    "memorydb-fips",
+    "mgn",
+    "migrationhub-orchestrator",
+    "models-v2-lex",
+    "monitoring",
+    "neptune-graph",
+    "networkmonitor",
+    "nimble",
+    "organizations",
+    "organizations-fips",
+    "panorama",
+    "payment-cryptography.controlplane",
+    "payment-cryptography.dataplane",
+    "pca-connector-ad",
+    "personalize",
+    "personalize-events",
+    "personalize-runtime",
+    "pinpoint",
+    "pinpoint-sms-voice-v2",
+    "polly",
+    "private-networks",
+    "profile",
+    "proton",
+    "qldb.session",
     "rds",
+    "rds-data",
     "redshift",
-    "route53resolver",
+    "redshift-data",
+    "redshift-fips",
+    "refactor-spaces",
+    "rekognition",
+    "rekognition-fips",
+    "robomaker",
+    "rolesanywhere",
+    "rum",
+    "rum-dataplane",
+    "runtime-medical-imaging",
+    "runtime-v2-lex",
     "s3",
-    "sagemaker",
+    "s3",
+    "s3-outposts",
+    "s3express",
+    "sagemaker.api",
+    "sagemaker.featurestore-runtime",
+    "sagemaker.metrics",
+    "sagemaker.runtime",
+    "sagemaker.runtime-fips",
+    "scn",
     "secretsmanager",
+    "securityhub",
+    "servicecatalog",
+    "servicecatalog-appregistry",
+    "servicediscovery",
+    "servicediscovery-fips",
+    "signin",
+    "simspaceweaver",
+    "snow-device-management",
     "sns",
     "sqs",
     "ssm",
+    "ssm-contacts",
+    "ssm-incidents",
+    "ssmmessages",
+    "states",
+    "storage-omics",
+    "storagegateway",
+    "streaming-rekognition",
+    "streaming-rekognition-fips",
     "sts",
+    "swf",
+    "swf-fips",
+    "sync-states",
+    "synthetics",
+    "tags-omics",
+    "textract",
+    "textract-fips",
+    "thinclient.api",
+    "timestream-influxdb",
+    "tnb",
     "transcribe",
+    "transcribestreaming",
+    "transfer",
+    "transfer.server",
+    "translate",
+    "trustedadvisor",
+    "verifiedpermissions",
+    "voiceid",
+    "vpc-lattice",
+    "wisdom",
+    "workflows-omics",
+    "workspaces",
     "xray",
 ]
 MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS = 1000
-DEFAULT_VPC_ENDPOINT_SERVICES: List[Dict[str, str]] = []
+DEFAULT_VPC_ENDPOINT_SERVICES: Dict[str, List[Dict[str, str]]] = {}
 ENDPOINT_SERVICE_COLLECTION_LOCK = threading.Lock()
 
 
@@ -772,9 +1011,10 @@ class VPCBackend:
     ) -> List[Dict[str, str]]:
         """Return list of default services using list of backends."""
         with ENDPOINT_SERVICE_COLLECTION_LOCK:
-            if DEFAULT_VPC_ENDPOINT_SERVICES:
-                return DEFAULT_VPC_ENDPOINT_SERVICES
+            if region in DEFAULT_VPC_ENDPOINT_SERVICES:
+                return DEFAULT_VPC_ENDPOINT_SERVICES[region]
 
+            DEFAULT_VPC_ENDPOINT_SERVICES[region] = []
             zones = [
                 zone.name
                 for zones in RegionsAndZonesBackend.zones.values()
@@ -792,15 +1032,22 @@ class VPCBackend:
                         region, zones
                     )
                     if service:
-                        DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)
+                        DEFAULT_VPC_ENDPOINT_SERVICES[region].extend(service)
 
                 if "global" in account_backend:
                     service = account_backend["global"].default_vpc_endpoint_service(
                         region, zones
                     )
                     if service:
-                        DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)
-            return DEFAULT_VPC_ENDPOINT_SERVICES
+                        DEFAULT_VPC_ENDPOINT_SERVICES[region].extend(service)
+
+            # Return sensible defaults, for services that do not offer a custom implementation
+            for aws_service in AWS_ENDPOINT_SERVICES:
+                if aws_service not in COVERED_ENDPOINT_SERVICES:
+                    service_configs = BaseBackend.default_vpc_endpoint_service_factory(region, zones, aws_service)
+                    DEFAULT_VPC_ENDPOINT_SERVICES[region].extend(service_configs)
+
+            return DEFAULT_VPC_ENDPOINT_SERVICES[region]
 
     @staticmethod
     def _matches_service_by_tags(
diff --git a/moto/ecs/models.py b/moto/ecs/models.py
index 3e06e3c82..a48f390dd 100644
--- a/moto/ecs/models.py
+++ b/moto/ecs/models.py
@@ -962,15 +962,6 @@ class EC2ContainerServiceBackend(BaseBackend):
         self.services: Dict[str, Service] = {}
         self.container_instances: Dict[str, Dict[str, ContainerInstance]] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, Any]]:  # type: ignore[misc]
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "ecs"
-        )
-
     def _get_cluster(self, name: str) -> Cluster:
         # short name or full ARN of the cluster
         cluster_name = name.split("/")[-1]
diff --git a/moto/elasticbeanstalk/models.py b/moto/elasticbeanstalk/models.py
index e2a92f105..13fcb2cde 100644
--- a/moto/elasticbeanstalk/models.py
+++ b/moto/elasticbeanstalk/models.py
@@ -84,17 +84,6 @@ class EBBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.applications: Dict[str, FakeApplication] = dict()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "elasticbeanstalk"
-        ) + BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "elasticbeanstalk-health"
-        )
-
     def create_application(self, application_name: str) -> FakeApplication:
         if application_name in self.applications:
             raise InvalidParameterValueError(
diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py
index 4a52abddd..011b5592a 100644
--- a/moto/elbv2/models.py
+++ b/moto/elbv2/models.py
@@ -722,15 +722,6 @@ class ELBv2Backend(BaseBackend):
         self.load_balancers: Dict[str, FakeLoadBalancer] = OrderedDict()
         self.tagging_service = TaggingService()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "elasticloadbalancing"
-        )
-
     @property
     def ec2_backend(self) -> Any:  # type: ignore[misc]
         """
diff --git a/moto/emr/models.py b/moto/emr/models.py
index cc7beb3aa..536a26d0d 100644
--- a/moto/emr/models.py
+++ b/moto/emr/models.py
@@ -556,15 +556,6 @@ class ElasticMapReduceBackend(BaseBackend):
         self.instance_groups: Dict[str, FakeInstanceGroup] = {}
         self.security_configurations: Dict[str, FakeSecurityConfiguration] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "elasticmapreduce"
-        )
-
     @property
     def ec2_backend(self) -> Any:  # type: ignore[misc]
         """
diff --git a/moto/events/models.py b/moto/events/models.py
index 10f0904e0..251a06353 100644
--- a/moto/events/models.py
+++ b/moto/events/models.py
@@ -1026,15 +1026,6 @@ class EventsBackend(BaseBackend):
         self.partner_event_sources: Dict[str, PartnerEventSource] = {}
         self.approved_parent_event_bus_names: List[str] = []
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "events"
-        )
-
     def _add_default_event_bus(self) -> None:
         self.event_buses["default"] = EventBus(
             self.account_id, self.region_name, "default"
diff --git a/moto/glue/models.py b/moto/glue/models.py
index 74155237b..e6780dbbc 100644
--- a/moto/glue/models.py
+++ b/moto/glue/models.py
@@ -113,15 +113,6 @@ class GlueBackend(BaseBackend):
         self.num_schemas = 0
         self.num_schema_versions = 0
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "glue"
-        )
-
     def create_database(
         self,
         database_name: str,
diff --git a/moto/kms/models.py b/moto/kms/models.py
index d12d9834a..8f8c50f32 100644
--- a/moto/kms/models.py
+++ b/moto/kms/models.py
@@ -260,15 +260,6 @@ class KmsBackend(BaseBackend):
         self.key_to_aliases: Dict[str, Set[str]] = defaultdict(set)
         self.tagger = TaggingService(key_name="TagKey", value_name="TagValue")
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "kms"
-        )
-
     def _generate_default_keys(self, alias_name: str) -> Optional[str]:
         """Creates default kms keys"""
         if alias_name in RESERVED_ALIASES:
diff --git a/moto/logs/models.py b/moto/logs/models.py
index b2057d18a..6a07de367 100644
--- a/moto/logs/models.py
+++ b/moto/logs/models.py
@@ -766,15 +766,6 @@ class LogsBackend(BaseBackend):
         self.tagger = TaggingService()
         self.export_tasks: Dict[str, ExportTask] = dict()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "logs"
-        )
-
     def create_log_group(
         self, log_group_name: str, tags: Dict[str, str], **kwargs: Any
     ) -> LogGroup:
diff --git a/moto/rds/models.py b/moto/rds/models.py
index 8125b544d..bf151de9b 100644
--- a/moto/rds/models.py
+++ b/moto/rds/models.py
@@ -1736,17 +1736,6 @@ class RDSBackend(BaseBackend):
             ]
         return self._db_cluster_options
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "rds"
-        ) + BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "rds-data"
-        )
-
     def create_db_instance(self, db_kwargs: Dict[str, Any]) -> Database:
         database_id = db_kwargs["db_instance_identifier"]
         self._validate_db_identifier(database_id)
diff --git a/moto/redshift/models.py b/moto/redshift/models.py
index 5f66e77cc..a885b1145 100644
--- a/moto/redshift/models.py
+++ b/moto/redshift/models.py
@@ -595,17 +595,6 @@ class RedshiftBackend(BaseBackend):
         }
         self.snapshot_copy_grants: Dict[str, SnapshotCopyGrant] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "redshift"
-        ) + BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "redshift-data", policy_supported=False
-        )
-
     def enable_snapshot_copy(self, **kwargs: Any) -> Cluster:
         cluster_identifier = kwargs["cluster_identifier"]
         cluster = self.clusters[cluster_identifier]
diff --git a/moto/redshiftdata/models.py b/moto/redshiftdata/models.py
index 61e689d0f..b5a64dad2 100644
--- a/moto/redshiftdata/models.py
+++ b/moto/redshiftdata/models.py
@@ -117,6 +117,15 @@ class RedshiftDataAPIServiceBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.statements: Dict[str, Statement] = {}
 
+    @staticmethod
+    def default_vpc_endpoint_service(
+        service_region: str, zones: List[str]
+    ) -> List[Dict[str, str]]:
+        """Default VPC endpoint service."""
+        return BaseBackend.default_vpc_endpoint_service_factory(
+            service_region, zones, "redshift-data", policy_supported=False
+        )
+
     def cancel_statement(self, statement_id: str) -> None:
         _validate_uuid(statement_id)
 
diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py
index e1be5a0c8..95f1c1b65 100644
--- a/moto/secretsmanager/models.py
+++ b/moto/secretsmanager/models.py
@@ -361,15 +361,6 @@ class SecretsManagerBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.secrets = SecretsStore()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint services."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "secretsmanager"
-        )
-
     def _is_valid_identifier(self, identifier: str) -> bool:
         return identifier in self.secrets
 
diff --git a/moto/sns/models.py b/moto/sns/models.py
index 481599150..d1539a21a 100644
--- a/moto/sns/models.py
+++ b/moto/sns/models.py
@@ -409,15 +409,6 @@ class SNSBackend(BaseBackend):
             "+447700900907",
         ]
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """List of dicts representing default VPC endpoints for this service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "sns"
-        )
-
     def get_sms_attributes(self, filter_list: Set[str]) -> Dict[str, str]:
         if len(filter_list) > 0:
             return {k: v for k, v in self.sms_attributes.items() if k in filter_list}
diff --git a/moto/sqs/models.py b/moto/sqs/models.py
index 66860fe49..3b6f3efb6 100644
--- a/moto/sqs/models.py
+++ b/moto/sqs/models.py
@@ -679,15 +679,6 @@ class SQSBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.queues: Dict[str, Queue] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "sqs"
-        )
-
     def create_queue(
         self, name: str, tags: Optional[Dict[str, str]] = None, **kwargs: Any
     ) -> Queue:
diff --git a/moto/ssm/models.py b/moto/ssm/models.py
index 7395cbff3..be084dc6a 100644
--- a/moto/ssm/models.py
+++ b/moto/ssm/models.py
@@ -1188,17 +1188,6 @@ class SimpleSystemManagerBackend(BaseBackend):
         self.windows: Dict[str, FakeMaintenanceWindow] = dict()
         self.baselines: Dict[str, FakePatchBaseline] = dict()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint services."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "ssm"
-        ) + BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "ssmmessages"
-        )
-
     def _generate_document_information(
         self, ssm_document: Document, document_format: str
     ) -> Dict[str, Any]:
diff --git a/moto/sts/models.py b/moto/sts/models.py
index 4a237551a..1ff40ae00 100644
--- a/moto/sts/models.py
+++ b/moto/sts/models.py
@@ -81,15 +81,6 @@ class STSBackend(BaseBackend):
         super().__init__(region_name, account_id)
         self.assumed_roles: List[AssumedRole] = []
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "sts"
-        )
-
     def get_session_token(self, duration: int) -> Token:
         return Token(duration=duration)
 
diff --git a/moto/transcribe/models.py b/moto/transcribe/models.py
index fb81d894f..d4e1c2e68 100644
--- a/moto/transcribe/models.py
+++ b/moto/transcribe/models.py
@@ -480,17 +480,6 @@ class TranscribeBackend(BaseBackend):
         self.medical_vocabularies: Dict[str, FakeMedicalVocabulary] = {}
         self.vocabularies: Dict[str, FakeVocabulary] = {}
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint services."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "transcribe"
-        ) + BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "transcribestreaming"
-        )
-
     def start_transcription_job(
         self,
         transcription_job_name: str,
diff --git a/moto/xray/models.py b/moto/xray/models.py
index 46a5f7c07..f0f49cfdb 100644
--- a/moto/xray/models.py
+++ b/moto/xray/models.py
@@ -250,15 +250,6 @@ class XRayBackend(BaseBackend):
         self._telemetry_records: List[TelemetryRecords] = []
         self._segment_collection = SegmentCollection()
 
-    @staticmethod
-    def default_vpc_endpoint_service(
-        service_region: str, zones: List[str]
-    ) -> List[Dict[str, str]]:
-        """Default VPC endpoint service."""
-        return BaseBackend.default_vpc_endpoint_service_factory(
-            service_region, zones, "xray"
-        )
-
     def add_telemetry_records(self, src: Any) -> None:
         self._telemetry_records.append(TelemetryRecords.from_json(src))
 


Test patch:
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():
diff --git a/tests/test_core/test_ec2_vpc_endpoint_services.py b/tests/test_core/test_ec2_vpc_endpoint_services.py
index 00936092e..58ad37bd5 100644
--- a/tests/test_core/test_ec2_vpc_endpoint_services.py
+++ b/tests/test_core/test_ec2_vpc_endpoint_services.py
@@ -51,6 +51,16 @@ def test_describe_vpc_endpoint_services_bad_args() -> None:
     assert "The token 'foo' is invalid" in err["Message"]
 
 
+@mock_aws
+def test_describe_vpc_endpoint_services_unimplemented_service() -> None:
+    """Verify exceptions are raised for bad arguments."""
+    ec2 = boto3.client("ec2", region_name="us-east-1")
+
+    service_name = "com.amazonaws.us-east-1.bedrock-agent-runtime"
+    resp = ec2.describe_vpc_endpoint_services(ServiceNames=[service_name])
+    assert resp["ServiceNames"] == [service_name]
+
+
 @mock_aws
 def test_describe_vpc_default_endpoint_services() -> None:
     """Test successfull calls as well as the next_token arg."""