diff --git a/moto/acm/utils.py b/moto/acm/utils.py index e8b81a378afb..670159a6efac 100644 --- a/moto/acm/utils.py +++ b/moto/acm/utils.py @@ -1,7 +1,8 @@ from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition def make_arn_for_certificate(account_id: str, region_name: str) -> str: # Example # arn:aws:acm:eu-west-2:764371465172:certificate/c4b738b8-56fe-4b3a-b841-1c047654780b - return f"arn:aws:acm:{region_name}:{account_id}:certificate/{mock_random.uuid4()}" + return f"arn:{get_partition(region_name)}:acm:{region_name}:{account_id}:certificate/{mock_random.uuid4()}" diff --git a/moto/amp/models.py b/moto/amp/models.py index 9ce1edfa29cf..318be4999c65 100644 --- a/moto/amp/models.py +++ b/moto/amp/models.py @@ -8,6 +8,7 @@ from moto.moto_api._internal import mock_random from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import RuleGroupNamespaceNotFound, WorkspaceNotFound from .utils import PAGINATION_MODEL @@ -26,7 +27,7 @@ def __init__( self.name = name self.data = data self.tag_fn = tag_fn - self.arn = f"arn:aws:aps:{region}:{account_id}:rulegroupsnamespace/{workspace_id}/{self.name}" + self.arn = f"arn:{get_partition(region)}:aps:{region}:{account_id}:rulegroupsnamespace/{workspace_id}/{self.name}" self.created_at = unix_time() self.modified_at = self.created_at @@ -56,7 +57,7 @@ def __init__( ): self.alias = alias self.workspace_id = f"ws-{mock_random.uuid4()}" - self.arn = f"arn:aws:aps:{region}:{account_id}:workspace/{self.workspace_id}" + self.arn = f"arn:{get_partition(region)}:aps:{region}:{account_id}:workspace/{self.workspace_id}" self.endpoint = f"https://aps-workspaces.{region}.amazonaws.com/workspaces/{self.workspace_id}/" self.status = {"statusCode": "ACTIVE"} self.created_at = unix_time() diff --git a/moto/apigatewayv2/models.py b/moto/apigatewayv2/models.py index a53b58cc09c0..69d3117c45c1 100644 --- a/moto/apigatewayv2/models.py +++ b/moto/apigatewayv2/models.py @@ -11,6 +11,7 @@ from moto.core.utils import unix_time from moto.moto_api._internal import mock_random as random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ( ApiMappingNotFound, @@ -594,7 +595,9 @@ def __init__( self.routes: Dict[str, Route] = dict() self.stages: Dict[str, Stage] = dict() - self.arn = f"arn:aws:apigateway:{region}::/apis/{self.api_id}" + self.arn = ( + f"arn:{get_partition(region)}:apigateway:{region}::/apis/{self.api_id}" + ) self.backend.tag_resource(self.arn, tags) def clear(self) -> None: @@ -1061,7 +1064,7 @@ def __init__( self.sg_ids = sg_ids self.subnet_ids = subnet_ids - self.arn = f"arn:aws:apigateway:{backend.region_name}::/vpclinks/{self.id}" + self.arn = f"arn:{get_partition(backend.region_name)}:apigateway:{backend.region_name}::/vpclinks/{self.id}" self.backend = backend self.backend.tag_resource(self.arn, tags) diff --git a/moto/appconfig/models.py b/moto/appconfig/models.py index 7a8a3a03de3a..f8f862975a4d 100644 --- a/moto/appconfig/models.py +++ b/moto/appconfig/models.py @@ -4,6 +4,7 @@ from moto.core.common_models import BaseModel from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ( AppNotFoundException, @@ -56,7 +57,7 @@ def __init__( _type: str, ): self.id = mock_random.get_random_hex(7) - self.arn = f"arn:aws:appconfig:{region}:{account_id}:application/{application_id}/configurationprofile/{self.id}" + self.arn = f"arn:{get_partition(region)}:appconfig:{region}:{account_id}:application/{application_id}/configurationprofile/{self.id}" self.application_id = application_id self.name = name self.description = description @@ -116,7 +117,7 @@ def __init__( self, name: str, description: Optional[str], region: str, account_id: str ): self.id = mock_random.get_random_hex(7) - self.arn = f"arn:aws:appconfig:{region}:{account_id}:application/{self.id}" + self.arn = f"arn:{get_partition(region)}:appconfig:{region}:{account_id}:application/{self.id}" self.name = name self.description = description diff --git a/moto/applicationautoscaling/models.py b/moto/applicationautoscaling/models.py index 91214821f55d..acddc77063b0 100644 --- a/moto/applicationautoscaling/models.py +++ b/moto/applicationautoscaling/models.py @@ -7,6 +7,7 @@ from moto.core.common_models import BaseModel from moto.ecs import ecs_backends from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition from .exceptions import AWSValidationException @@ -463,7 +464,7 @@ def __init__( self.policy_name = policy_name self.policy_type = policy_type self._guid = mock_random.uuid4() - self.policy_arn = f"arn:aws:autoscaling:{region_name}:{account_id}:scalingPolicy:{self._guid}:resource/{self.service_namespace}/{self.resource_id}:policyName/{self.policy_name}" + self.policy_arn = f"arn:{get_partition(region_name)}:autoscaling:{region_name}:{account_id}:scalingPolicy:{self._guid}:resource/{self.service_namespace}/{self.resource_id}:policyName/{self.policy_name}" self.creation_time = time.time() self.alarms: List["FakeAlarm"] = [] @@ -638,7 +639,7 @@ def __init__( account_id: str, region: str, ) -> None: - self.arn = f"arn:aws:autoscaling:{region}:{account_id}:scheduledAction:{service_namespace}:scheduledActionName/{scheduled_action_name}" + self.arn = f"arn:{get_partition(region)}:autoscaling:{region}:{account_id}:scheduledAction:{service_namespace}:scheduledActionName/{scheduled_action_name}" self.service_namespace = service_namespace self.schedule = schedule self.timezone = timezone diff --git a/moto/appsync/models.py b/moto/appsync/models.py index e2a568b64e27..fe99700289a7 100644 --- a/moto/appsync/models.py +++ b/moto/appsync/models.py @@ -8,6 +8,7 @@ from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import BadRequestException, GraphqlAPINotFound, GraphQLSchemaException @@ -155,7 +156,7 @@ def __init__( self.user_pool_config = user_pool_config self.xray_enabled = xray_enabled - self.arn = f"arn:aws:appsync:{self.region}:{account_id}:apis/{self.api_id}" + self.arn = f"arn:{get_partition(self.region)}:appsync:{self.region}:{account_id}:apis/{self.api_id}" self.graphql_schema: Optional[GraphqlSchema] = None self.api_keys: Dict[str, GraphqlAPIKey] = dict() diff --git a/moto/athena/models.py b/moto/athena/models.py index f03d4ff929f1..93a563ae21c0 100644 --- a/moto/athena/models.py +++ b/moto/athena/models.py @@ -6,6 +6,7 @@ from moto.core.common_models import BaseModel from moto.moto_api._internal import mock_random from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition class TaggableResourceMixin: @@ -22,7 +23,7 @@ def __init__( self.region = region_name self.resource_name = resource_name self.tags = tags or [] - self.arn = f"arn:aws:athena:{region_name}:{account_id}:{resource_name}" + self.arn = f"arn:{get_partition(region_name)}:athena:{region_name}:{account_id}:{resource_name}" def create_tags(self, tags: List[Dict[str, str]]) -> List[Dict[str, str]]: new_keys = [tag_set["Key"] for tag_set in tags] diff --git a/moto/autoscaling/models.py b/moto/autoscaling/models.py index 0a0ca2313ca9..3cd6371d1179 100644 --- a/moto/autoscaling/models.py +++ b/moto/autoscaling/models.py @@ -18,6 +18,7 @@ BlockDeviceMapping, BlockDeviceType, ) +from moto.utilities.utils import get_partition from .exceptions import ( AutoscalingClientError, @@ -112,7 +113,7 @@ def __init__( @property def arn(self) -> str: - return f"arn:aws:autoscaling:{self.autoscaling_backend.region_name}:{self.autoscaling_backend.account_id}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/{self.as_name}:policyName/{self.name}" + return f"arn:{get_partition(self.autoscaling_backend.region_name)}:autoscaling:{self.autoscaling_backend.region_name}:{self.autoscaling_backend.account_id}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/{self.as_name}:policyName/{self.name}" def execute(self) -> None: if self.adjustment_type == "ExactCapacity": @@ -174,7 +175,7 @@ def __init__( self.metadata_options = metadata_options self.classic_link_vpc_id = classic_link_vpc_id self.classic_link_vpc_security_groups = classic_link_vpc_security_groups - self.arn = f"arn:aws:autoscaling:{region_name}:{account_id}:launchConfiguration:9dbbbf87-6141-428a-a409-0752edbe6cad:launchConfigurationName/{self.name}" + self.arn = f"arn:{get_partition(region_name)}:autoscaling:{region_name}:{account_id}:launchConfiguration:9dbbbf87-6141-428a-a409-0752edbe6cad:launchConfigurationName/{self.name}" @classmethod def create_from_instance( @@ -502,7 +503,7 @@ def tags(self, tags: List[Dict[str, str]]) -> None: @property def arn(self) -> str: - return f"arn:aws:autoscaling:{self.region}:{self.account_id}:autoScalingGroup:{self._id}:autoScalingGroupName/{self.name}" + return f"arn:{get_partition(self.region)}:autoscaling:{self.region}:{self.account_id}:autoScalingGroup:{self._id}:autoScalingGroupName/{self.name}" def active_instances(self) -> List[InstanceState]: return [x for x in self.instance_states if x.lifecycle_state == "InService"] diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 8437195b225b..2674cffb0877 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -40,7 +40,7 @@ from moto.s3.models import FakeKey, s3_backends from moto.sqs.models import sqs_backends from moto.utilities.docker_utilities import DockerModel -from moto.utilities.utils import load_resource_as_bytes +from moto.utilities.utils import get_partition, load_resource_as_bytes from .exceptions import ( ConflictException, @@ -529,9 +529,7 @@ def __init__( description: str, routing_config: str, ): - self.arn = ( - f"arn:aws:lambda:{region}:{account_id}:function:{function_name}:{name}" - ) + self.arn = f"arn:{get_partition(region)}:lambda:{region}:{account_id}:function:{function_name}:{name}" self.name = name self.function_version = function_version self.description = description @@ -1451,7 +1449,7 @@ def get_alias(self, name: str, function_name: str) -> LambdaAlias: if name in aliases: return aliases[name] - arn = f"arn:aws:lambda:{self.region_name}:{self.account_id}:function:{function_name}:{name}" + arn = f"arn:{get_partition(self.region_name)}:lambda:{self.region_name}:{self.account_id}:function:{function_name}:{name}" raise UnknownAliasException(arn) def put_alias( @@ -1467,7 +1465,7 @@ def put_alias( ) aliases = self._get_function_aliases(function_name) if name in aliases: - arn = f"arn:aws:lambda:{self.region_name}:{self.account_id}:function:{function_name}:{name}" + arn = f"arn:{get_partition(self.region_name)}:lambda:{self.region_name}:{self.account_id}:function:{function_name}:{name}" raise ConflictException(f"Alias already exists: {arn}") alias = LambdaAlias( diff --git a/moto/awslambda/utils.py b/moto/awslambda/utils.py index 946905faabe5..003483af6966 100644 --- a/moto/awslambda/utils.py +++ b/moto/awslambda/utils.py @@ -2,6 +2,8 @@ from functools import partial from typing import TYPE_CHECKING, Any, Callable +from moto.utilities.utils import get_partition + if TYPE_CHECKING: from .models import LambdaBackend @@ -10,7 +12,9 @@ def make_arn(resource_type: str, region: str, account: str, name: str) -> str: - return f"arn:aws:lambda:{region}:{account}:{resource_type}:{name}" + return ( + f"arn:{get_partition(region)}:lambda:{region}:{account}:{resource_type}:{name}" + ) make_function_arn = partial(make_arn, "function") diff --git a/moto/backup/models.py b/moto/backup/models.py index 5f8d3011f827..f71d0fd3d7bf 100644 --- a/moto/backup/models.py +++ b/moto/backup/models.py @@ -6,6 +6,7 @@ from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import AlreadyExistsException, ResourceNotFoundException @@ -18,7 +19,7 @@ def __init__( backend: "BackupBackend", ): self.backup_plan_id = str(mock_random.uuid4()) - self.backup_plan_arn = f"arn:aws:backup:{backend.region_name}:{backend.account_id}:backup-plan:{self.backup_plan_id}" + self.backup_plan_arn = f"arn:{get_partition(backend.region_name)}:backup:{backend.region_name}:{backend.account_id}:backup-plan:{self.backup_plan_id}" self.creation_date = unix_time() ran_str = mock_random.get_random_string(length=48) self.version_id = ran_str @@ -84,7 +85,7 @@ def __init__( backend: "BackupBackend", ): self.backup_vault_name = backup_vault_name - self.backup_vault_arn = f"arn:aws:backup:{backend.region_name}:{backend.account_id}:backup-vault:{backup_vault_name}" + self.backup_vault_arn = f"arn:{get_partition(backend.region_name)}:backup:{backend.region_name}:{backend.account_id}:backup-vault:{backup_vault_name}" self.creation_date = unix_time() self.encryption_key_arn = encryption_key_arn self.creator_request_id = creator_request_id diff --git a/moto/batch/models.py b/moto/batch/models.py index a7a35fd089f2..7f5e474a9db5 100644 --- a/moto/batch/models.py +++ b/moto/batch/models.py @@ -27,6 +27,7 @@ from moto.moto_api._internal.managed_state_model import ManagedState from moto.utilities.docker_utilities import DockerModel from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ClientException, InvalidParameterValueException, ValidationError from .utils import ( @@ -977,7 +978,7 @@ def __init__( tags: Dict[str, str], ): self.name = name - self.arn = f"arn:aws:batch:{region}:{account_id}:scheduling-policy/{name}" + self.arn = f"arn:{get_partition(region)}:batch:{region}:{account_id}:scheduling-policy/{name}" self.fairshare_policy = { "computeReservation": fairshare_policy.get("computeReservation") or 0, "shareDecaySeconds": fairshare_policy.get("shareDecaySeconds") or 0, diff --git a/moto/batch/utils.py b/moto/batch/utils.py index bb6e02746362..b308ffa98998 100644 --- a/moto/batch/utils.py +++ b/moto/batch/utils.py @@ -1,25 +1,27 @@ from enum import Enum from typing import Any, Dict, List, Optional, Tuple +from moto.utilities.utils import get_partition + from .exceptions import ValidationError def make_arn_for_compute_env(account_id: str, name: str, region_name: str) -> str: - return f"arn:aws:batch:{region_name}:{account_id}:compute-environment/{name}" + return f"arn:{get_partition(region_name)}:batch:{region_name}:{account_id}:compute-environment/{name}" def make_arn_for_job_queue(account_id: str, name: str, region_name: str) -> str: - return f"arn:aws:batch:{region_name}:{account_id}:job-queue/{name}" + return f"arn:{get_partition(region_name)}:batch:{region_name}:{account_id}:job-queue/{name}" def make_arn_for_job(account_id: str, job_id: str, region_name: str) -> str: - return f"arn:aws:batch:{region_name}:{account_id}:job/{job_id}" + return f"arn:{get_partition(region_name)}:batch:{region_name}:{account_id}:job/{job_id}" def make_arn_for_task_def( account_id: str, name: str, revision: int, region_name: str ) -> str: - return f"arn:aws:batch:{region_name}:{account_id}:job-definition/{name}:{revision}" + return f"arn:{get_partition(region_name)}:batch:{region_name}:{account_id}:job-definition/{name}:{revision}" def lowercase_first_key(some_dict: Dict[str, Any]) -> Dict[str, Any]: diff --git a/moto/bedrock/models.py b/moto/bedrock/models.py index 6023b1b5528f..4ace313a952a 100644 --- a/moto/bedrock/models.py +++ b/moto/bedrock/models.py @@ -14,6 +14,7 @@ from moto.core.common_models import BaseModel from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition class ModelCustomizationJob(BaseModel): @@ -80,16 +81,16 @@ def __init__( self.vpc_config = vpc_config self.region_name = region_name self.account_id = account_id - self.job_arn = f"arn:aws:bedrock:{self.region_name}:{self.account_id}:model-customization-job/{self.job_name}" + self.job_arn = f"arn:{get_partition(self.region_name)}:bedrock:{self.region_name}:{self.account_id}:model-customization-job/{self.job_name}" self.output_model_name = f"{self.custom_model_name}-{self.job_name}" - self.output_model_arn = f"arn:aws:bedrock:{self.region_name}:{self.account_id}:custom-model/{self.output_model_name}" + self.output_model_arn = f"arn:{get_partition(self.region_name)}:bedrock:{self.region_name}:{self.account_id}:custom-model/{self.output_model_name}" self.status = "InProgress" self.failure_message = "Failure Message" self.creation_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.last_modified_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.end_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - self.base_model_arn = f"arn:aws:bedrock:{self.region_name}::foundation-model/{self.base_model_identifier}" - self.output_model_kms_key_arn = f"arn:aws:kms:{self.region_name}:{self.account_id}:key/{self.output_model_name}-kms-key" + self.base_model_arn = f"arn:{get_partition(self.region_name)}:bedrock:{self.region_name}::foundation-model/{self.base_model_identifier}" + self.output_model_kms_key_arn = f"arn:{get_partition(self.region_name)}:kms:{self.region_name}:{self.account_id}:key/{self.output_model_name}-kms-key" self.training_metrics = {"trainingLoss": 0.0} # hard coded self.validation_metrics = [{"validationLoss": 0.0}] # hard coded @@ -153,7 +154,7 @@ def __init__( self.validation_metrics = validation_metrics self.region_name = region_name self.account_id = account_id - self.model_arn = f"arn:aws:bedrock:{self.region_name}:{self.account_id}:custom-model/{self.model_name}" + self.model_arn = f"arn:{get_partition(self.region_name)}:bedrock:{self.region_name}:{self.account_id}:custom-model/{self.model_name}" self.creation_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.base_model_name = base_model_name diff --git a/moto/bedrockagent/models.py b/moto/bedrockagent/models.py index 245c23c73887..e9c36eddf690 100644 --- a/moto/bedrockagent/models.py +++ b/moto/bedrockagent/models.py @@ -13,6 +13,7 @@ from moto.moto_api._internal import mock_random from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition class Agent(BaseModel): @@ -46,7 +47,7 @@ def __init__( self.prepared_at = unix_time() self.agent_status = "PREPARED" self.agent_id = self.agent_name + str(mock_random.uuid4())[:8] - self.agent_arn = f"arn:aws:bedrock:{self.region_name}:{self.account_id}:agent/{self.agent_id}" + self.agent_arn = f"arn:{get_partition(self.region_name)}:bedrock:{self.region_name}:{self.account_id}:agent/{self.agent_id}" self.agent_version = "1.0" self.failure_reasons: List[str] = [] self.recommended_actions = ["action"] @@ -124,7 +125,7 @@ def __init__( self.region_name = region_name self.account_id = account_id self.knowledge_base_id = self.name + str(mock_random.uuid4())[:8] - self.knowledge_base_arn = f"arn:aws:bedrock:{self.region_name}:{self.account_id}:knowledge-base/{self.knowledge_base_id}" + self.knowledge_base_arn = f"arn:{get_partition(self.region_name)}:bedrock:{self.region_name}:{self.account_id}:knowledge-base/{self.knowledge_base_id}" self.created_at = unix_time() self.updated_at = unix_time() self.status = "Active" diff --git a/moto/cloudformation/utils.py b/moto/cloudformation/utils.py index 7225b5c21b21..a529b479fa1c 100644 --- a/moto/cloudformation/utils.py +++ b/moto/cloudformation/utils.py @@ -6,18 +6,19 @@ import yaml from moto.moto_api._internal import mock_random as random +from moto.utilities.utils import get_partition def generate_stack_id(stack_name: str, region: str, account: str) -> str: random_id = random.uuid4() - return f"arn:aws:cloudformation:{region}:{account}:stack/{stack_name}/{random_id}" + return f"arn:{get_partition(region)}:cloudformation:{region}:{account}:stack/{stack_name}/{random_id}" def generate_changeset_id( changeset_name: str, region_name: str, account_id: str ) -> str: random_id = random.uuid4() - return f"arn:aws:cloudformation:{region_name}:{account_id}:changeSet/{changeset_name}/{random_id}" + return f"arn:{get_partition(region_name)}:cloudformation:{region_name}:{account_id}:changeSet/{changeset_name}/{random_id}" def generate_stackset_id(stackset_name: str) -> str: @@ -26,7 +27,7 @@ def generate_stackset_id(stackset_name: str) -> str: def generate_stackset_arn(stackset_id: str, region_name: str, account_id: str) -> str: - return f"arn:aws:cloudformation:{region_name}:{account_id}:stackset/{stackset_id}" + return f"arn:{get_partition(region_name)}:cloudformation:{region_name}:{account_id}:stackset/{stackset_id}" def random_suffix() -> str: diff --git a/moto/cloudtrail/models.py b/moto/cloudtrail/models.py index af8b331413f7..ff3fbd4dca83 100644 --- a/moto/cloudtrail/models.py +++ b/moto/cloudtrail/models.py @@ -7,6 +7,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import iso_8601_datetime_without_milliseconds, utcnow from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ( InsufficientSnsTopicPolicyException, @@ -111,12 +112,12 @@ def __init__( @property def arn(self) -> str: - return f"arn:aws:cloudtrail:{self.region_name}:{self.account_id}:trail/{self.trail_name}" + return f"arn:{get_partition(self.region_name)}:cloudtrail:{self.region_name}:{self.account_id}:trail/{self.trail_name}" @property def topic_arn(self) -> Optional[str]: if self.sns_topic_name: - return f"arn:aws:sns:{self.region_name}:{self.account_id}:{self.sns_topic_name}" + return f"arn:{get_partition(self.region_name)}:sns:{self.region_name}:{self.account_id}:{self.sns_topic_name}" return None def check_name(self) -> None: @@ -312,9 +313,7 @@ def get_trail_status(self, name: str) -> TrailStatus: ) if not trail: # This particular method returns the ARN as part of the error message - arn = ( - f"arn:aws:cloudtrail:{self.region_name}:{self.account_id}:trail/{name}" - ) + arn = f"arn:{get_partition(self.region_name)}:cloudtrail:{self.region_name}:{self.account_id}:trail/{name}" raise TrailNotFoundException(account_id=self.account_id, name=arn) return trail.status diff --git a/moto/cloudwatch/utils.py b/moto/cloudwatch/utils.py index d2d68d7107e8..c106a9a768a0 100644 --- a/moto/cloudwatch/utils.py +++ b/moto/cloudwatch/utils.py @@ -1,6 +1,9 @@ +from moto.utilities.utils import get_partition + + def make_arn_for_dashboard(account_id: str, name: str) -> str: return f"arn:aws:cloudwatch::{account_id}dashboard/{name}" def make_arn_for_alarm(region: str, account_id: str, alarm_name: str) -> str: - return f"arn:aws:cloudwatch:{region}:{account_id}:alarm:{alarm_name}" + return f"arn:{get_partition(region)}:cloudwatch:{region}:{account_id}:alarm:{alarm_name}" diff --git a/moto/codebuild/models.py b/moto/codebuild/models.py index 695c295d7f19..9ac25c4b33a5 100644 --- a/moto/codebuild/models.py +++ b/moto/codebuild/models.py @@ -8,6 +8,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition class CodeBuildProjectMetadata(BaseModel): @@ -26,7 +27,7 @@ def __init__( self.build_metadata["id"] = build_id self.build_metadata["arn"] = ( - f"arn:aws:codebuild:{region_name}:{account_id}:build/{build_id}" + f"arn:{get_partition(region_name)}:codebuild:{region_name}:{account_id}:build/{build_id}" ) self.build_metadata["buildNumber"] = mock_random.randint(1, 100) @@ -77,7 +78,7 @@ def __init__( self.build_metadata["logs"] = { "deepLink": "https://console.aws.amazon.com/cloudwatch/home?region=eu-west-2#logEvent:group=null;stream=null", - "cloudWatchLogsArn": f"arn:aws:logs:{region_name}:{account_id}:log-group:null:log-stream:null", + "cloudWatchLogsArn": f"arn:{get_partition(region_name)}:logs:{region_name}:{account_id}:log-group:null:log-stream:null", "cloudWatchLogs": {"status": "ENABLED"}, "s3Logs": {"status": "DISABLED", "encryptionDisabled": False}, } @@ -87,7 +88,7 @@ def __init__( self.build_metadata["buildComplete"] = False self.build_metadata["initiator"] = "rootme" self.build_metadata["encryptionKey"] = ( - f"arn:aws:kms:{region_name}:{account_id}:alias/aws/s3" + f"arn:{get_partition(region_name)}:kms:{region_name}:{account_id}:alias/aws/s3" ) @@ -107,10 +108,10 @@ def __init__( self.project_metadata["name"] = project_name self.project_metadata["arn"] = ( - f"arn:aws:codebuild:{region}:{account_id}:project/{project_name}" + f"arn:{get_partition(region)}:codebuild:{region}:{account_id}:project/{project_name}" ) self.project_metadata["encryptionKey"] = ( - f"arn:aws:kms:{region}:{account_id}:alias/aws/s3" + f"arn:{get_partition(region)}:kms:{region}:{account_id}:alias/aws/s3" ) self.project_metadata["serviceRole"] = ( f"arn:aws:iam::{account_id}:role/service-role/{serviceRole}" diff --git a/moto/codecommit/models.py b/moto/codecommit/models.py index 184c0c4956e2..da55dbf93267 100644 --- a/moto/codecommit/models.py +++ b/moto/codecommit/models.py @@ -4,6 +4,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition from .exceptions import RepositoryDoesNotExistException, RepositoryNameExistsException @@ -30,7 +31,7 @@ def __init__( self.repository_metadata["repositoryDescription"] = repository_description self.repository_metadata["repositoryId"] = str(mock_random.uuid4()) self.repository_metadata["Arn"] = ( - f"arn:aws:codecommit:{region}:{account_id}:{repository_name}" + f"arn:{get_partition(region)}:codecommit:{region}:{account_id}:{repository_name}" ) self.repository_metadata["accountId"] = account_id diff --git a/moto/codepipeline/models.py b/moto/codepipeline/models.py index 98552ff20fef..51ca6944f344 100644 --- a/moto/codepipeline/models.py +++ b/moto/codepipeline/models.py @@ -13,6 +13,7 @@ from moto.core.utils import iso_8601_datetime_with_milliseconds, utcnow from moto.iam.exceptions import IAMNotFoundException from moto.iam.models import IAMBackend, iam_backends +from moto.utilities.utils import get_partition class CodePipeline(BaseModel): @@ -23,7 +24,7 @@ def __init__(self, account_id: str, region: str, pipeline: Dict[str, Any]): self.pipeline = self.add_default_values(pipeline) self.tags: Dict[str, str] = {} - self._arn = f"arn:aws:codepipeline:{region}:{account_id}:{pipeline['name']}" + self._arn = f"arn:{get_partition(region)}:codepipeline:{region}:{account_id}:{pipeline['name']}" self._created = utcnow() self._updated = utcnow() diff --git a/moto/comprehend/models.py b/moto/comprehend/models.py index ff37e0b64fba..945004016551 100644 --- a/moto/comprehend/models.py +++ b/moto/comprehend/models.py @@ -5,6 +5,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ( DetectPIIValidationException, @@ -78,7 +79,7 @@ def __init__( model_policy: str, ): self.name = recognizer_name - self.arn = f"arn:aws:comprehend:{region_name}:{account_id}:entity-recognizer/{recognizer_name}" + self.arn = f"arn:{get_partition(region_name)}:comprehend:{region_name}:{account_id}:entity-recognizer/{recognizer_name}" if version_name: self.arn += f"/version/{version_name}" self.language_code = language_code diff --git a/moto/config/models.py b/moto/config/models.py index 171e6d4fc3be..197013765cab 100644 --- a/moto/config/models.py +++ b/moto/config/models.py @@ -57,7 +57,7 @@ from moto.moto_api._internal import mock_random as random from moto.s3.config import s3_config_query from moto.s3control.config import s3_account_public_access_block_query -from moto.utilities.utils import load_resource +from moto.utilities.utils import get_partition, load_resource POP_STRINGS = [ "capitalizeStart", @@ -400,7 +400,7 @@ def __init__( super().__init__(capitalize_start=True, capitalize_arn=False) self.configuration_aggregator_name = name - self.configuration_aggregator_arn = f"arn:aws:config:{region}:{account_id}:config-aggregator/config-aggregator-{random_string()}" + self.configuration_aggregator_arn = f"arn:{get_partition(region)}:config:{region}:{account_id}:config-aggregator/config-aggregator-{random_string()}" self.account_aggregation_sources = account_sources self.organization_aggregation_source = org_source self.creation_time = datetime2int(utcnow()) @@ -438,7 +438,7 @@ def __init__( ): super().__init__(capitalize_start=True, capitalize_arn=False) - self.aggregation_authorization_arn = f"arn:aws:config:{current_region}:{account_id}:aggregation-authorization/{authorized_account_id}/{authorized_aws_region}" + self.aggregation_authorization_arn = f"arn:{get_partition(current_region)}:config:{current_region}:{account_id}:aggregation-authorization/{authorized_account_id}/{authorized_aws_region}" self.authorized_account_id = authorized_account_id self.authorized_aws_region = authorized_aws_region self.creation_time = datetime2int(utcnow()) @@ -468,7 +468,7 @@ def __init__( self.delivery_s3_key_prefix = delivery_s3_key_prefix self.excluded_accounts = excluded_accounts or [] self.last_update_time = datetime2int(utcnow()) - self.organization_conformance_pack_arn = f"arn:aws:config:{region}:{account_id}:organization-conformance-pack/{self._unique_pack_name}" + self.organization_conformance_pack_arn = f"arn:{get_partition(region)}:config:{region}:{account_id}:organization-conformance-pack/{self._unique_pack_name}" self.organization_conformance_pack_name = name def update( @@ -741,9 +741,7 @@ def __init__( self.maximum_execution_frequency = None # keeps pylint happy self.modify_fields(region, config_rule, tags) self.config_rule_id = f"config-rule-{random_string():.6}" - self.config_rule_arn = ( - f"arn:aws:config:{region}:{account_id}:config-rule/{self.config_rule_id}" - ) + self.config_rule_arn = f"arn:{get_partition(region)}:config:{region}:{account_id}:config-rule/{self.config_rule_id}" def modify_fields( self, region: str, config_rule: Dict[str, Any], tags: Dict[str, str] diff --git a/moto/core/utils.py b/moto/core/utils.py index 2a73db789c6f..315069f74cc7 100644 --- a/moto/core/utils.py +++ b/moto/core/utils.py @@ -393,14 +393,6 @@ def gzip_decompress(body: bytes) -> bytes: return decompress(body) -def get_partition_from_region(region_name: str) -> str: - # Very rough implementation - # In an ideal world we check `boto3.Session.get_partition_for_region`, but that is quite computationally heavy - if region_name.startswith("cn-"): - return "aws-cn" - return "aws" - - def get_equivalent_url_in_aws_domain(url: str) -> Tuple[ParseResult, bool]: """Parses a URL and converts non-standard AWS endpoint hostnames (from ISO regions or custom S3 endpoints) to the equivalent standard AWS domain. diff --git a/moto/databrew/models.py b/moto/databrew/models.py index 825ff42f362d..4bf1d9a275bb 100644 --- a/moto/databrew/models.py +++ b/moto/databrew/models.py @@ -9,6 +9,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import camelcase_to_pascal, underscores_to_camelcase from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition from .exceptions import ( AlreadyExistsException, @@ -601,9 +602,7 @@ def __init__( @property def resource_arn(self) -> str: - return ( - f"arn:aws:databrew:{self.region_name}:{self.account_id}:dataset/{self.name}" - ) + return f"arn:{get_partition(self.region_name)}:databrew:{self.region_name}:{self.account_id}:dataset/{self.name}" def as_dict(self) -> Dict[str, Any]: return { @@ -667,7 +666,7 @@ def job_type(self) -> str: @property def resource_arn(self) -> str: - return f"arn:aws:databrew:{self.region_name}:{self.account_id}:job/{self.name}" + return f"arn:{get_partition(self.region_name)}:databrew:{self.region_name}:{self.account_id}:job/{self.name}" def as_dict(self) -> Dict[str, Any]: rtn_dict = { diff --git a/moto/datasync/models.py b/moto/datasync/models.py index 429802c9d15c..32b965f04282 100644 --- a/moto/datasync/models.py +++ b/moto/datasync/models.py @@ -3,6 +3,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel +from moto.utilities.utils import get_partition from .exceptions import InvalidRequestException @@ -21,7 +22,7 @@ def __init__( self.metadata = metadata self.typ = typ # Generate ARN - self.arn = f"arn:aws:datasync:{region_name}:111222333444:location/loc-{str(arn_counter).zfill(17)}" + self.arn = f"arn:{get_partition(region_name)}:datasync:{region_name}:111222333444:location/loc-{str(arn_counter).zfill(17)}" class Task(BaseModel): @@ -42,7 +43,7 @@ def __init__( self.status = "AVAILABLE" self.current_task_execution_arn: Optional[str] = None # Generate ARN - self.arn = f"arn:aws:datasync:{region_name}:111222333444:task/task-{str(arn_counter).zfill(17)}" + self.arn = f"arn:{get_partition(region_name)}:datasync:{region_name}:111222333444:task/task-{str(arn_counter).zfill(17)}" class TaskExecution(BaseModel): diff --git a/moto/dax/models.py b/moto/dax/models.py index d188ed8ac71c..f5e3e577e9c9 100644 --- a/moto/dax/models.py +++ b/moto/dax/models.py @@ -9,6 +9,7 @@ from moto.moto_api._internal.managed_state_model import ManagedState from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ClusterNotFoundFault from .utils import PAGINATION_MODEL @@ -90,7 +91,9 @@ def __init__( # Set internal properties self.name = name self.description = description - self.arn = f"arn:aws:dax:{region}:{account_id}:cache/{self.name}" + self.arn = ( + f"arn:{get_partition(region)}:dax:{region}:{account_id}:cache/{self.name}" + ) self.node_type = node_type self.replication_factor = replication_factor self.cluster_hex = random.get_random_hex(6) diff --git a/moto/dms/models.py b/moto/dms/models.py index 13d31adfebc2..6cb77d373ee6 100644 --- a/moto/dms/models.py +++ b/moto/dms/models.py @@ -4,6 +4,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.core.utils import utcnow +from moto.utilities.utils import get_partition from .exceptions import ( InvalidResourceStateFault, @@ -119,7 +120,7 @@ def __init__( self.table_mappings = table_mappings self.replication_task_settings = replication_task_settings - self.arn = f"arn:aws:dms:{region_name}:{account_id}:task:{self.id}" + self.arn = f"arn:{get_partition(region_name)}:dms:{region_name}:{account_id}:task:{self.id}" self.status = "creating" self.creation_date = utcnow() diff --git a/moto/dynamodb/models/table.py b/moto/dynamodb/models/table.py index c309ff9252e8..9a19a4dcb852 100644 --- a/moto/dynamodb/models/table.py +++ b/moto/dynamodb/models/table.py @@ -19,6 +19,7 @@ from moto.dynamodb.models.dynamo_type import DynamoType, Item from moto.dynamodb.models.utilities import dynamo_json_dump from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition RESULT_SIZE_LIMIT = 1000000 # DynamoDB has a 1MB size limit @@ -421,7 +422,7 @@ def delete_from_cloudformation_json( # type: ignore[misc] dynamodb_backends[account_id][region_name].delete_table(name=resource_name) def _generate_arn(self, name: str) -> str: - return f"arn:aws:dynamodb:{self.region_name}:{self.account_id}:table/{name}" + return f"arn:{get_partition(self.region_name)}:dynamodb:{self.region_name}:{self.account_id}:table/{name}" def set_stream_specification(self, streams: Optional[Dict[str, Any]]) -> None: self.stream_specification = streams @@ -1069,7 +1070,7 @@ def _make_identifier(self) -> str: @property def arn(self) -> str: - return f"arn:aws:dynamodb:{self.region_name}:{self.account_id}:table/{self.table.name}/backup/{self.identifier}" + return f"arn:{get_partition(self.region_name)}:dynamodb:{self.region_name}:{self.account_id}:table/{self.table.name}/backup/{self.identifier}" @property def details(self) -> Dict[str, Any]: # type: ignore[misc] diff --git a/moto/dynamodb/models/table_import.py b/moto/dynamodb/models/table_import.py index 905a70219efa..f841379a4c95 100644 --- a/moto/dynamodb/models/table_import.py +++ b/moto/dynamodb/models/table_import.py @@ -3,6 +3,7 @@ from uuid import uuid4 from moto.core.utils import gzip_decompress +from moto.utilities.utils import get_partition if TYPE_CHECKING: from moto.dynamodb.models import DynamoDBBackend @@ -25,7 +26,7 @@ def __init__( compression_type: Optional[str], ): super().__init__() - self.arn = f"arn:aws:dynamodb:{region_name}:{account_id}:table/{table_name}/import/{str(uuid4()).replace('-', '')}" + self.arn = f"arn:{get_partition(region_name)}:dynamodb:{region_name}:{account_id}:table/{table_name}/import/{str(uuid4()).replace('-', '')}" self.status = "IN_PROGRESS" self.account_id = account_id self.s3_source = s3_source @@ -42,9 +43,7 @@ def __init__( self.failure_code: Optional[str] = None self.failure_message: Optional[str] = None self.table: Optional["Table"] = None - self.table_arn = ( - f"arn:aws:dynamodb:{self.region_name}:{self.account_id}:table/{table_name}" - ) + self.table_arn = f"arn:{get_partition(self.region_name)}:dynamodb:{self.region_name}:{self.account_id}:table/{table_name}" self.processed_count = 0 self.processed_bytes = 0 diff --git a/moto/ecr/models.py b/moto/ecr/models.py index 4ede050f4172..71207497bc23 100644 --- a/moto/ecr/models.py +++ b/moto/ecr/models.py @@ -30,6 +30,7 @@ from moto.iam.policy_validation import IAMPolicyDocumentValidator from moto.moto_api._internal import mock_random as random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition ECR_REPOSITORY_ARN_PATTERN = "^arn:(?P[^:]+):ecr:(?P[^:]+):(?P[^:]+):repository/(?P.*)$" ECR_REPOSITORY_NAME_PATTERN = ( @@ -79,9 +80,7 @@ def __init__( self.account_id = account_id self.region_name = region_name self.registry_id = registry_id or account_id - self.arn = ( - f"arn:aws:ecr:{region_name}:{self.registry_id}:repository/{repository_name}" - ) + self.arn = f"arn:{get_partition(region_name)}:ecr:{region_name}:{self.registry_id}:repository/{repository_name}" self.name = repository_name self.created_at = utcnow() self.uri = ( @@ -110,7 +109,7 @@ def _determine_encryption_config( return {"encryptionType": "AES256"} if encryption_config == {"encryptionType": "KMS"}: encryption_config["kmsKey"] = ( - f"arn:aws:kms:{self.region_name}:{self.account_id}:key/{random.uuid4()}" + f"arn:{get_partition(self.region_name)}:kms:{self.region_name}:{self.account_id}:key/{random.uuid4()}" ) return encryption_config diff --git a/moto/ecs/models.py b/moto/ecs/models.py index adfc7b5ec02b..f2518953161e 100644 --- a/moto/ecs/models.py +++ b/moto/ecs/models.py @@ -12,6 +12,7 @@ from moto.ec2 import ec2_backends from moto.moto_api._internal import mock_random from moto.moto_api._internal.managed_state_model import ManagedState +from moto.utilities.utils import get_partition from ..ec2.utils import random_private_ip from .exceptions import ( @@ -73,7 +74,7 @@ def __init__( service_connect_defaults: Optional[Dict[str, str]] = None, ): self.active_services_count = 0 - self.arn = f"arn:aws:ecs:{region_name}:{account_id}:cluster/{cluster_name}" + self.arn = f"arn:{get_partition(region_name)}:ecs:{region_name}:{account_id}:cluster/{cluster_name}" self.name = cluster_name self.pending_tasks_count = 0 self.registered_container_instances_count = 0 @@ -189,7 +190,7 @@ def __init__( ): self.family = family self.revision = revision - self.arn = f"arn:aws:ecs:{region_name}:{account_id}:task-definition/{family}:{revision}" + self.arn = f"arn:{get_partition(region_name)}:ecs:{region_name}:{account_id}:task-definition/{family}:{revision}" default_container_definition = { "cpu": 0, @@ -433,8 +434,8 @@ def last_status(self, value: Optional[str]) -> None: @property def task_arn(self) -> str: if self._backend.enable_long_arn_for_name(name="taskLongArnFormat"): - return f"arn:aws:ecs:{self.region_name}:{self._account_id}:task/{self.cluster_name}/{self.id}" - return f"arn:aws:ecs:{self.region_name}:{self._account_id}:task/{self.id}" + return f"arn:{get_partition(self.region_name)}:ecs:{self.region_name}:{self._account_id}:task/{self.cluster_name}/{self.id}" + return f"arn:{get_partition(self.region_name)}:ecs:{self.region_name}:{self._account_id}:task/{self.id}" def response_object(self, include_tags: bool = True) -> Dict[str, Any]: # type: ignore response_object = self.gen_response_object() @@ -455,9 +456,7 @@ def __init__( tags: Optional[List[Dict[str, str]]], ): self._id = str(mock_random.uuid4()) - self.capacity_provider_arn = ( - f"arn:aws:ecs:{region_name}:{account_id}:capacity-provider/{name}" - ) + self.capacity_provider_arn = f"arn:{get_partition(region_name)}:ecs:{region_name}:{account_id}:capacity-provider/{name}" self.name = name self.status = "ACTIVE" self.auto_scaling_group_provider = self._prepare_asg_provider(asg_details) @@ -509,7 +508,7 @@ def update(self, asg_details: Dict[str, Any]) -> None: class CapacityProviderFailure(BaseObject): def __init__(self, reason: str, name: str, account_id: str, region_name: str): self.reason = reason - self.arn = f"arn:aws:ecs:{region_name}:{account_id}:capacity_provider/{name}" + self.arn = f"arn:{get_partition(region_name)}:ecs:{region_name}:{account_id}:capacity_provider/{name}" @property def response_object(self) -> Dict[str, Any]: # type: ignore[misc] @@ -593,8 +592,8 @@ def __init__( @property def arn(self) -> str: if self._backend.enable_long_arn_for_name(name="serviceLongArnFormat"): - return f"arn:aws:ecs:{self.region_name}:{self._account_id}:service/{self.cluster_name}/{self.name}" - return f"arn:aws:ecs:{self.region_name}:{self._account_id}:service/{self.name}" + return f"arn:{get_partition(self.region_name)}:ecs:{self.region_name}:{self._account_id}:service/{self.cluster_name}/{self.name}" + return f"arn:{get_partition(self.region_name)}:ecs:{self.region_name}:{self._account_id}:service/{self.name}" @property def physical_resource_id(self) -> str: @@ -828,8 +827,8 @@ def container_instance_arn(self) -> str: if self._backend.enable_long_arn_for_name( name="containerInstanceLongArnFormat" ): - return f"arn:aws:ecs:{self.region_name}:{self._account_id}:container-instance/{self.cluster_name}/{self.id}" - return f"arn:aws:ecs:{self.region_name}:{self._account_id}:container-instance/{self.id}" + return f"arn:{get_partition(self.region_name)}:ecs:{self.region_name}:{self._account_id}:container-instance/{self.cluster_name}/{self.id}" + return f"arn:{get_partition(self.region_name)}:ecs:{self.region_name}:{self._account_id}:container-instance/{self.id}" @property def response_object(self) -> Dict[str, Any]: # type: ignore[misc] @@ -857,7 +856,7 @@ def __init__( self, reason: str, cluster_name: str, account_id: str, region_name: str ): self.reason = reason - self.arn = f"arn:aws:ecs:{region_name}:{account_id}:cluster/{cluster_name}" + self.arn = f"arn:{get_partition(region_name)}:ecs:{region_name}:{account_id}:cluster/{cluster_name}" @property def response_object(self) -> Dict[str, Any]: # type: ignore[misc] @@ -872,7 +871,7 @@ def __init__( self, reason: str, container_instance_id: str, account_id: str, region_name: str ): self.reason = reason - self.arn = f"arn:aws:ecs:{region_name}:{account_id}:container-instance/{container_instance_id}" + self.arn = f"arn:{get_partition(region_name)}:ecs:{region_name}:{account_id}:container-instance/{container_instance_id}" @property def response_object(self) -> Dict[str, Any]: # type: ignore[misc] @@ -926,7 +925,7 @@ def __init__( cluster_name = self.cluster.split("/")[-1] service_name = self.service.split("/")[-1] - self.task_set_arn = f"arn:aws:ecs:{region_name}:{account_id}:task-set/{cluster_name}/{service_name}/{self.id}" + self.task_set_arn = f"arn:{get_partition(region_name)}:ecs:{region_name}:{account_id}:task-set/{cluster_name}/{service_name}/{self.id}" @property def response_object(self) -> Dict[str, Any]: # type: ignore[misc] @@ -1677,7 +1676,7 @@ def describe_services( if name_or_arn.startswith("arn:aws:ecs"): missing_arn = name_or_arn else: - missing_arn = f"arn:aws:ecs:{self.region_name}:{self.account_id}:service/{name}" + missing_arn = f"arn:{get_partition(self.region_name)}:ecs:{self.region_name}:{self.account_id}:service/{name}" failures.append({"arn": missing_arn, "reason": "MISSING"}) return result, failures diff --git a/moto/efs/models.py b/moto/efs/models.py index ce1419243a3c..9094f2eda5e6 100644 --- a/moto/efs/models.py +++ b/moto/efs/models.py @@ -31,7 +31,7 @@ ) from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService -from moto.utilities.utils import md5_hash +from moto.utilities.utils import get_partition, md5_hash def _lookup_az_id(account_id: str, az_name: str) -> Optional[str]: @@ -56,7 +56,7 @@ def __init__( context: "EFSBackend", ): self.access_point_id = f"fsap-{mock_random.get_random_hex(8)}" - self.access_point_arn = f"arn:aws:elasticfilesystem:{region_name}:{account_id}:access-point/{self.access_point_id}" + self.access_point_arn = f"arn:{get_partition(region_name)}:elasticfilesystem:{region_name}:{account_id}:access-point/{self.access_point_id}" self.client_token = client_token self.file_system_id = file_system_id self.name = name @@ -161,7 +161,7 @@ def __init__( # Generate AWS-assigned parameters self.file_system_id = file_system_id - self.file_system_arn = f"arn:aws:elasticfilesystem:{region_name}:{account_id}:file-system/{self.file_system_id}" + self.file_system_arn = f"arn:{get_partition(region_name)}:elasticfilesystem:{region_name}:{account_id}:file-system/{self.file_system_id}" self.creation_time = time.time() self.owner_id = account_id diff --git a/moto/eks/models.py b/moto/eks/models.py index 10203074258e..b09e81f8fe1c 100644 --- a/moto/eks/models.py +++ b/moto/eks/models.py @@ -4,6 +4,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.utils import iso_8601_datetime_without_milliseconds from moto.moto_api._internal import mock_random as random +from moto.utilities.utils import get_partition from .exceptions import ( InvalidParameterException, @@ -11,7 +12,7 @@ ResourceInUseException, ResourceNotFoundException, ) -from .utils import get_partition, validate_role_arn +from .utils import validate_role_arn # String Templates CLUSTER_ARN_TEMPLATE = "arn:{partition}:eks:{region}:{account_id}:cluster/{name}" diff --git a/moto/elasticache/models.py b/moto/elasticache/models.py index 8f470006a35f..ffade587504e 100644 --- a/moto/elasticache/models.py +++ b/moto/elasticache/models.py @@ -5,6 +5,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import utcnow from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition from ..moto_api._internal import mock_random from .exceptions import ( @@ -39,7 +40,7 @@ def __init__( self.minimum_engine_version = "6.0" self.usergroupids: List[str] = [] self.region = region - self.arn = f"arn:aws:elasticache:{self.region}:{account_id}:user:{self.id}" + self.arn = f"arn:{get_partition(self.region)}:elasticache:{self.region}:{account_id}:user:{self.id}" class CacheCluster(BaseModel): @@ -124,9 +125,7 @@ def __init__( self.cache_cluster_create_time = utcnow() self.auth_token_last_modified_date = utcnow() self.cache_cluster_status = "available" - self.arn = ( - f"arn:aws:elasticache:{region_name}:{account_id}:cluster:{cache_cluster_id}" - ) + self.arn = f"arn:{get_partition(region_name)}:elasticache:{region_name}:{account_id}:cluster:{cache_cluster_id}" self.cache_node_id = str(mock_random.uuid4()) def get_tags(self) -> List[Dict[str, str]]: diff --git a/moto/elastictranscoder/models.py b/moto/elastictranscoder/models.py index 8997c3ca8d06..0eb5f749693c 100644 --- a/moto/elastictranscoder/models.py +++ b/moto/elastictranscoder/models.py @@ -4,6 +4,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.moto_api._internal import mock_random as random +from moto.utilities.utils import get_partition class Pipeline(BaseModel): @@ -22,7 +23,7 @@ def __init__( b = "".join(random.choice(string.ascii_lowercase) for _ in range(6)) self.id = f"{a}-{b}" self.name = name - self.arn = f"arn:aws:elastictranscoder:{region}:{account_id}:pipeline/{self.id}" + self.arn = f"arn:{get_partition(region)}:elastictranscoder:{region}:{account_id}:pipeline/{self.id}" self.status = "Active" self.input_bucket = input_bucket self.output_bucket = output_bucket or content_config["Bucket"] diff --git a/moto/elbv2/utils.py b/moto/elbv2/utils.py index 32b647f1938c..5447f9dc872a 100644 --- a/moto/elbv2/utils.py +++ b/moto/elbv2/utils.py @@ -1,6 +1,9 @@ +from moto.utilities.utils import get_partition + + def make_arn_for_load_balancer(account_id: str, name: str, region_name: str) -> str: - return f"arn:aws:elasticloadbalancing:{region_name}:{account_id}:loadbalancer/app/{name}/50dc6c495c0c9188" + return f"arn:{get_partition(region_name)}:elasticloadbalancing:{region_name}:{account_id}:loadbalancer/app/{name}/50dc6c495c0c9188" def make_arn_for_target_group(account_id: str, name: str, region_name: str) -> str: - return f"arn:aws:elasticloadbalancing:{region_name}:{account_id}:targetgroup/{name}/50dc6c495c0c9188" + return f"arn:{get_partition(region_name)}:elasticloadbalancing:{region_name}:{account_id}:targetgroup/{name}/50dc6c495c0c9188" diff --git a/moto/emr/models.py b/moto/emr/models.py index 536a26d0d13c..1e13818787f5 100644 --- a/moto/emr/models.py +++ b/moto/emr/models.py @@ -10,6 +10,7 @@ ResourceNotFoundException, ValidationException, ) +from moto.utilities.utils import get_partition from .utils import ( CamelToUnderscoresWalker, @@ -322,7 +323,7 @@ def __init__( @property def arn(self) -> str: - return f"arn:aws:elasticmapreduce:{self.emr_backend.region_name}:{self.emr_backend.account_id}:cluster/{self.id}" + return f"arn:{get_partition(self.emr_backend.region_name)}:elasticmapreduce:{self.emr_backend.region_name}:{self.emr_backend.account_id}:cluster/{self.id}" @property def instance_groups(self) -> List[FakeInstanceGroup]: diff --git a/moto/emrcontainers/models.py b/moto/emrcontainers/models.py index aa3f6876e1d6..0ce175ae3a4e 100644 --- a/moto/emrcontainers/models.py +++ b/moto/emrcontainers/models.py @@ -7,10 +7,11 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.core.utils import iso_8601_datetime_without_milliseconds +from moto.utilities.utils import get_partition from ..config.exceptions import ValidationException from .exceptions import ResourceNotFoundException -from .utils import get_partition, paginated_list, random_cluster_id, random_job_id +from .utils import paginated_list, random_cluster_id, random_job_id VIRTUAL_CLUSTER_ARN_TEMPLATE = "arn:{partition}:emr-containers:{region}:{account_id}:/virtualclusters/{virtual_cluster_id}" diff --git a/moto/emrcontainers/utils.py b/moto/emrcontainers/utils.py index 5ab3f79f77f5..e21129d32184 100644 --- a/moto/emrcontainers/utils.py +++ b/moto/emrcontainers/utils.py @@ -5,21 +5,6 @@ from moto.moto_api._internal import mock_random as random -def get_partition(region: str) -> str: - valid_matches = [ - # (region prefix, aws partition) - ("cn-", "aws-cn"), - ("us-gov-", "aws-us-gov"), - ("us-gov-iso-", "aws-iso"), - ("us-gov-iso-b-", "aws-iso-b"), - ] - - for prefix, partition in valid_matches: - if region.startswith(prefix): - return partition - return "aws" - - def random_id(size: int = 13) -> str: chars = list(range(10)) + list(string.ascii_lowercase) return "".join(str(random.choice(chars)) for x in range(size)) diff --git a/moto/emrserverless/models.py b/moto/emrserverless/models.py index 493f08440ebb..3dd3d3e00246 100644 --- a/moto/emrserverless/models.py +++ b/moto/emrserverless/models.py @@ -8,7 +8,8 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.core.utils import iso_8601_datetime_without_milliseconds -from moto.emrcontainers.utils import get_partition, paginated_list +from moto.emrcontainers.utils import paginated_list +from moto.utilities.utils import get_partition from .exceptions import ( AccessDeniedException, diff --git a/moto/es/models.py b/moto/es/models.py index 56b557a55a5e..6c7631752548 100644 --- a/moto/es/models.py +++ b/moto/es/models.py @@ -3,6 +3,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition from .exceptions import DomainNotFound @@ -49,7 +50,7 @@ def __init__( @property def arn(self) -> str: - return f"arn:aws:es:{self.region_name}:domain/{self.domain_id}" + return f"arn:{get_partition(self.region_name)}:es:{self.region_name}:domain/{self.domain_id}" def to_json(self) -> Dict[str, Any]: return { diff --git a/moto/events/models.py b/moto/events/models.py index 72fbd859b22e..6cd308bcd5ab 100644 --- a/moto/events/models.py +++ b/moto/events/models.py @@ -33,6 +33,7 @@ from moto.utilities.arns import parse_arn from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .utils import _BASE_EVENT_MESSAGE, PAGINATION_MODEL, EventMessageType @@ -74,7 +75,7 @@ def arn(self) -> str: "" if self.event_bus_name == "default" else f"{self.event_bus_name}/" ) - return f"arn:aws:events:{self.region_name}:{self.account_id}:rule/{event_bus_name}{self.name}" + return f"arn:{get_partition(self.region_name)}:events:{self.region_name}:{self.account_id}:rule/{event_bus_name}{self.name}" @property def physical_resource_id(self) -> str: @@ -342,7 +343,7 @@ def __init__( self.account_id = account_id self.region = region_name self.name = name - self.arn = f"arn:aws:events:{self.region}:{account_id}:event-bus/{name}" + self.arn = f"arn:{get_partition(self.region)}:events:{self.region}:{account_id}:event-bus/{name}" self.tags = tags or [] self._statements: Dict[str, EventBusPolicyStatement] = {} @@ -554,7 +555,7 @@ def __init__( self.event_pattern = EventPattern.load(event_pattern) self.retention = retention if retention else 0 - self.arn = f"arn:aws:events:{region_name}:{account_id}:archive/{name}" + self.arn = f"arn:{get_partition(region_name)}:events:{region_name}:{account_id}:archive/{name}" self.creation_time = unix_time() self.state = "ENABLED" self.uuid = str(random.uuid4()) @@ -702,7 +703,7 @@ def __init__( self.event_end_time = end_time self.destination = destination - self.arn = f"arn:aws:events:{region_name}:{account_id}:replay/{name}" + self.arn = f"arn:{get_partition(region_name)}:events:{region_name}:{account_id}:replay/{name}" self.state = ReplayState.STARTING self.start_time = unix_time() self.end_time: Optional[float] = None @@ -766,7 +767,7 @@ def __init__( self.creation_time = unix_time() self.state = "AUTHORIZED" - self.arn = f"arn:aws:events:{region_name}:{account_id}:connection/{self.name}/{self.uuid}" + self.arn = f"arn:{get_partition(region_name)}:events:{region_name}:{account_id}:connection/{self.name}/{self.uuid}" def describe_short(self) -> Dict[str, Any]: """ @@ -843,7 +844,7 @@ def __init__( self.creation_time = unix_time() self.http_method = http_method self.state = "ACTIVE" - self.arn = f"arn:aws:events:{region_name}:{account_id}:api-destination/{name}/{self.uuid}" + self.arn = f"arn:{get_partition(region_name)}:events:{region_name}:{account_id}:api-destination/{name}/{self.uuid}" def describe(self) -> Dict[str, Any]: return { @@ -975,7 +976,7 @@ def parse(self) -> Dict[str, Any]: class PartnerEventSource(BaseModel): def __init__(self, region: str, name: str): self.name = name - self.arn = f"arn:aws:events:{region}::event-source/aws.partner/{name}" + self.arn = f"arn:{get_partition(region)}:events:{region}::event-source/aws.partner/{name}" self.created_on = unix_time() self.accounts: List[str] = [] self.state = "ACTIVE" @@ -1621,7 +1622,7 @@ def create_archive( [ { "Id": rule.name, - "Arn": f"arn:aws:events:{self.region_name}:::", + "Arn": f"arn:{get_partition(self.region_name)}:events:{self.region_name}:::", "InputTransformer": { "InputPathsMap": {}, "InputTemplate": json.dumps( diff --git a/moto/firehose/models.py b/moto/firehose/models.py index 7ec291b7ae91..d77172bee108 100644 --- a/moto/firehose/models.py +++ b/moto/firehose/models.py @@ -37,6 +37,7 @@ from moto.moto_api._internal import mock_random from moto.s3.models import s3_backends from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition MAX_TAGS_PER_DELIVERY_STREAM = 50 @@ -160,7 +161,7 @@ def __init__( del self.destinations[0][destination_name][old] self.delivery_stream_status = "ACTIVE" - self.delivery_stream_arn = f"arn:aws:firehose:{region}:{account_id}:deliverystream/{delivery_stream_name}" + self.delivery_stream_arn = f"arn:{get_partition(region)}:firehose:{region}:{account_id}:deliverystream/{delivery_stream_name}" self.create_timestamp = datetime.now(timezone.utc).isoformat() self.version_id = "1" # Used to track updates of destination configs diff --git a/moto/forecast/models.py b/moto/forecast/models.py index ca4a51b4556f..19707754af6a 100644 --- a/moto/forecast/models.py +++ b/moto/forecast/models.py @@ -4,6 +4,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.utils import iso_8601_datetime_without_milliseconds +from moto.utilities.utils import get_partition from .exceptions import ( InvalidInputException, @@ -38,7 +39,7 @@ def __init__( self.creation_date = iso_8601_datetime_without_milliseconds(datetime.now()) self.modified_date = self.creation_date - self.arn = f"arn:aws:forecast:{region_name}:{account_id}:dataset-group/{dataset_group_name}" + self.arn = f"arn:{get_partition(region_name)}:forecast:{region_name}:{account_id}:dataset-group/{dataset_group_name}" self.dataset_arns = dataset_arns if dataset_arns else [] self.dataset_group_name = dataset_group_name self.domain = domain diff --git a/moto/glacier/models.py b/moto/glacier/models.py index c7ed6b052652..4d21456f65c1 100644 --- a/moto/glacier/models.py +++ b/moto/glacier/models.py @@ -5,7 +5,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.core.exceptions import JsonRESTError -from moto.utilities.utils import md5_hash +from moto.utilities.utils import get_partition, md5_hash from .utils import get_job_id @@ -100,7 +100,7 @@ def __init__(self, vault_name: str, account_id: str, region: str): self.region = region self.archives: Dict[str, Dict[str, Any]] = {} self.jobs: Dict[str, Job] = {} - self.arn = f"arn:aws:glacier:{region}:{account_id}:vaults/{vault_name}" + self.arn = f"arn:{get_partition(region)}:glacier:{region}:{account_id}:vaults/{vault_name}" def to_dict(self) -> Dict[str, Any]: archives_size = 0 diff --git a/moto/glue/models.py b/moto/glue/models.py index e6780dbbc662..4b0724e06976 100644 --- a/moto/glue/models.py +++ b/moto/glue/models.py @@ -10,6 +10,7 @@ from moto.core.utils import unix_time, utcnow from moto.moto_api._internal import mock_random from moto.moto_api._internal.managed_state_model import ManagedState +from moto.utilities.utils import get_partition from ..utilities.paginator import paginate from ..utilities.tagging_service import TaggingService @@ -126,7 +127,7 @@ def create_database( database_name, database_input, catalog_id=self.account_id ) self.databases[database_name] = database - resource_arn = f"arn:aws:glue:{self.region_name}:{self.account_id}:database/{database_name}" + resource_arn = f"arn:{get_partition(self.region_name)}:glue:{self.region_name}:{self.account_id}:database/{database_name}" self.tag_resource(resource_arn, tags) return database @@ -1213,7 +1214,7 @@ def __init__( self.version = 1 self.crawl_elapsed_time = 0 self.last_crawl_info = None - self.arn = f"arn:aws:glue:{backend.region_name}:{backend.account_id}:crawler/{self.name}" + self.arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:crawler/{self.name}" self.backend = backend self.backend.tag_resource(self.arn, tags) @@ -1347,9 +1348,7 @@ def __init__( self.source_control_details = source_control_details self.created_on = utcnow() self.last_modified_on = utcnow() - self.arn = ( - f"arn:aws:glue:{backend.region_name}:{backend.account_id}:job/{self.name}" - ) + self.arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:job/{self.name}" self.backend = backend self.backend.tag_resource(self.arn, tags) @@ -1476,7 +1475,7 @@ def __init__( self.created_time = utcnow() self.updated_time = utcnow() self.status = "AVAILABLE" - self.registry_arn = f"arn:aws:glue:{backend.region_name}:{backend.account_id}:registry/{self.name}" + self.registry_arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:registry/{self.name}" self.schemas: Dict[str, FakeSchema] = OrderedDict() def as_dict(self) -> Dict[str, Any]: @@ -1500,9 +1499,9 @@ def __init__( description: Optional[str] = None, ): self.registry_name = registry_name - self.registry_arn = f"arn:aws:glue:{backend.region_name}:{backend.account_id}:registry/{self.registry_name}" + self.registry_arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:registry/{self.registry_name}" self.schema_name = schema_name - self.schema_arn = f"arn:aws:glue:{backend.region_name}:{backend.account_id}:schema/{self.registry_name}/{self.schema_name}" + self.schema_arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:schema/{self.registry_name}/{self.schema_name}" self.description = description self.data_format = data_format self.compatibility = compatibility @@ -1554,7 +1553,7 @@ def __init__( ): self.registry_name = registry_name self.schema_name = schema_name - self.schema_arn = f"arn:aws:glue:{backend.region_name}:{backend.account_id}:schema/{self.registry_name}/{self.schema_name}" + self.schema_arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:schema/{self.registry_name}/{self.schema_name}" self.schema_definition = schema_definition self.schema_version_status = AVAILABLE_STATUS self.version_number = version_number @@ -1631,7 +1630,7 @@ def __init__( self.request_origin = request_origin self.creation_time = utcnow() self.last_updated = self.creation_time - self.arn = f"arn:aws:glue:{backend.region_name}:{backend.account_id}:session/{self.session_id}" + self.arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:session/{self.session_id}" self.backend = backend self.backend.tag_resource(self.arn, tags) self.state = "READY" @@ -1689,7 +1688,7 @@ def __init__( else: self.state = "CREATED" self.event_batching_condition = event_batching_condition - self.arn = f"arn:aws:glue:{backend.region_name}:{backend.account_id}:trigger/{self.name}" + self.arn = f"arn:{get_partition(backend.region_name)}:glue:{backend.region_name}:{backend.account_id}:trigger/{self.name}" self.backend = backend self.backend.tag_resource(self.arn, tags) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index c9162b8ee7d9..3dc15f04ed66 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -8,6 +8,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import iso_8601_datetime_with_milliseconds, utcnow from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition from .exceptions import ( GreengrassClientError, @@ -25,7 +26,7 @@ def __init__(self, account_id: str, region_name: str, name: str): self.region_name = region_name self.name = name self.id = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/cores/{self.id}" + self.arn = f"arn:{get_partition(region_name)}:greengrass:{region_name}:{account_id}:greengrass/definition/cores/{self.id}" self.created_at_datetime = utcnow() self.latest_version = "" self.latest_version_arn = "" @@ -58,7 +59,7 @@ def __init__( self.core_definition_id = core_definition_id self.definition = definition self.version = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/cores/{self.core_definition_id}/versions/{self.version}" + self.arn = f"arn:{get_partition(region_name)}:greengrass:{region_name}:{account_id}:greengrass/definition/cores/{self.core_definition_id}/versions/{self.version}" self.created_at_datetime = utcnow() def to_dict(self, include_detail: bool = False) -> Dict[str, Any]: @@ -87,7 +88,7 @@ def __init__( ): self.region_name = region_name self.id = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/devices/{self.id}" + self.arn = f"arn:{get_partition(region_name)}:greengrass:{region_name}:{account_id}:greengrass/definition/devices/{self.id}" self.created_at_datetime = utcnow() self.update_at_datetime = utcnow() self.latest_version = "" @@ -125,7 +126,7 @@ def __init__( self.device_definition_id = device_definition_id self.devices = devices self.version = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/devices/{self.device_definition_id}/versions/{self.version}" + self.arn = f"arn:{get_partition(region_name)}:greengrass:{region_name}:{account_id}:greengrass/definition/devices/{self.device_definition_id}/versions/{self.version}" self.created_at_datetime = utcnow() def to_dict(self, include_detail: bool = False) -> Dict[str, Any]: @@ -154,7 +155,7 @@ def __init__( ): self.region_name = region_name self.id = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/resources/{self.id}" + self.arn = f"arn:{get_partition(region_name)}:greengrass:{region_name}:{account_id}:greengrass/definition/resources/{self.id}" self.created_at_datetime = utcnow() self.update_at_datetime = utcnow() self.latest_version = "" @@ -190,7 +191,7 @@ def __init__( self.resource_definition_id = resource_definition_id self.resources = resources self.version = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{region_name}:{account_id}:greengrass/definition/resources/{self.resource_definition_id}/versions/{self.version}" + self.arn = f"arn:{get_partition(region_name)}:greengrass:{region_name}:{account_id}:greengrass/definition/resources/{self.resource_definition_id}/versions/{self.version}" self.created_at_datetime = utcnow() def to_dict(self) -> Dict[str, Any]: @@ -215,7 +216,7 @@ def __init__( ): self.region_name = region_name self.id = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/functions/{self.id}" + self.arn = f"arn:{get_partition(self.region_name)}:greengrass:{self.region_name}:{account_id}:greengrass/definition/functions/{self.id}" self.created_at_datetime = utcnow() self.update_at_datetime = utcnow() self.latest_version = "" @@ -255,7 +256,7 @@ def __init__( self.functions = functions self.default_config = default_config self.version = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/functions/{self.function_definition_id}/versions/{self.version}" + self.arn = f"arn:{get_partition(self.region_name)}:greengrass:{self.region_name}:{account_id}:greengrass/definition/functions/{self.function_definition_id}/versions/{self.version}" self.created_at_datetime = utcnow() def to_dict(self) -> Dict[str, Any]: @@ -280,7 +281,7 @@ def __init__( ): self.region_name = region_name self.id = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/subscriptions/{self.id}" + self.arn = f"arn:{get_partition(self.region_name)}:greengrass:{self.region_name}:{account_id}:greengrass/definition/subscriptions/{self.id}" self.created_at_datetime = utcnow() self.update_at_datetime = utcnow() self.latest_version = "" @@ -316,7 +317,7 @@ def __init__( self.subscription_definition_id = subscription_definition_id self.subscriptions = subscriptions self.version = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/definition/subscriptions/{self.subscription_definition_id}/versions/{self.version}" + self.arn = f"arn:{get_partition(self.region_name)}:greengrass:{self.region_name}:{account_id}:greengrass/definition/subscriptions/{self.subscription_definition_id}/versions/{self.version}" self.created_at_datetime = utcnow() def to_dict(self) -> Dict[str, Any]: @@ -336,7 +337,7 @@ def __init__(self, account_id: str, region_name: str, name: str): self.region_name = region_name self.group_id = str(mock_random.uuid4()) self.name = name - self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/groups/{self.group_id}" + self.arn = f"arn:{get_partition(self.region_name)}:greengrass:{self.region_name}:{account_id}:greengrass/groups/{self.group_id}" self.created_at_datetime = utcnow() self.last_updated_datetime = utcnow() self.latest_version = "" @@ -374,7 +375,7 @@ def __init__( self.region_name = region_name self.group_id = group_id self.version = str(mock_random.uuid4()) - self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:greengrass/groups/{self.group_id}/versions/{self.version}" + self.arn = f"arn:{get_partition(self.region_name)}:greengrass:{self.region_name}:{account_id}:greengrass/groups/{self.group_id}/versions/{self.version}" self.created_at_datetime = utcnow() self.core_definition_version_arn = core_definition_version_arn self.device_definition_version_arn = device_definition_version_arn @@ -439,7 +440,7 @@ def __init__( self.update_at_datetime = utcnow() self.deployment_status = "InProgress" self.deployment_type = deployment_type - self.arn = f"arn:aws:greengrass:{self.region_name}:{account_id}:/greengrass/groups/{self.group_id}/deployments/{self.id}" + self.arn = f"arn:{get_partition(self.region_name)}:greengrass:{self.region_name}:{account_id}:/greengrass/groups/{self.group_id}/deployments/{self.id}" def to_dict(self, include_detail: bool = False) -> Dict[str, Any]: obj = {"DeploymentId": self.id, "DeploymentArn": self.arn} diff --git a/moto/iam/models.py b/moto/iam/models.py index cf12506c428d..11273f5e4b61 100644 --- a/moto/iam/models.py +++ b/moto/iam/models.py @@ -16,7 +16,6 @@ from moto.core.common_models import BaseModel, CloudFormationModel from moto.core.exceptions import RESTError from moto.core.utils import ( - get_partition_from_region, iso_8601_datetime_with_milliseconds, iso_8601_datetime_without_milliseconds, unix_time, @@ -28,7 +27,7 @@ ) from moto.moto_api._internal import mock_random as random from moto.settings import load_iam_aws_managed_policies -from moto.utilities.utils import md5_hash +from moto.utilities.utils import get_partition, md5_hash from ..utilities.tagging_service import TaggingService from .aws_managed_policies import aws_managed_policies_data @@ -1300,7 +1299,7 @@ def __init__( @property def arn(self) -> str: - partition = get_partition_from_region(self.region_name) + partition = get_partition(self.region_name) return f"arn:{partition}:iam::{self.account_id}:user{self.path}{self.name}" @property diff --git a/moto/iot/models.py b/moto/iot/models.py index 2f96e55a80fd..fe2d0ba9df62 100644 --- a/moto/iot/models.py +++ b/moto/iot/models.py @@ -16,6 +16,7 @@ from moto.core.utils import utcnow from moto.moto_api._internal import mock_random as random from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition from .exceptions import ( CertificateStateException, @@ -48,7 +49,7 @@ def __init__( self.thing_name = thing_name self.thing_type = thing_type self.attributes = attributes - self.arn = f"arn:aws:iot:{region_name}:{account_id}:thing/{thing_name}" + self.arn = f"arn:{get_partition(region_name)}:iot:{region_name}:{account_id}:thing/{thing_name}" self.version = 1 # TODO: we need to handle "version"? @@ -112,7 +113,7 @@ def __init__( self.thing_type_id = str(random.uuid4()) # I don't know the rule of id t = time.time() self.metadata = {"deprecated": False, "creationDate": int(t * 1000) / 1000.0} - self.arn = f"arn:aws:iot:{self.region_name}:{self.account_id}:thingtype/{thing_type_name}" + self.arn = f"arn:{get_partition(self.region_name)}:iot:{self.region_name}:{self.account_id}:thingtype/{thing_type_name}" def to_dict(self) -> Dict[str, Any]: return { @@ -168,7 +169,7 @@ def __init__( } ] ) - self.arn = f"arn:aws:iot:{self.region_name}:{self.account_id}:thinggroup/{thing_group_name}" + self.arn = f"arn:{get_partition(self.region_name)}:iot:{self.region_name}:{self.account_id}:thinggroup/{thing_group_name}" self.things: Dict[str, FakeThing] = OrderedDict() def to_dict(self) -> Dict[str, Any]: @@ -194,7 +195,7 @@ def __init__( m = hashlib.sha256() m.update(certificate_pem.encode("utf-8")) self.certificate_id = m.hexdigest() - self.arn = f"arn:aws:iot:{region_name}:{account_id}:cert/{self.certificate_id}" + self.arn = f"arn:{get_partition(region_name)}:iot:{region_name}:{account_id}:cert/{self.certificate_id}" self.certificate_pem = certificate_pem self.status = status @@ -267,7 +268,7 @@ def __init__( ): self.name = name self.document = document - self.arn = f"arn:aws:iot:{region_name}:{account_id}:policy/{name}" + self.arn = f"arn:{get_partition(region_name)}:iot:{region_name}:{account_id}:policy/{name}" self.default_version_id = default_version_id self.versions = [ FakePolicyVersion(self.name, document, True, account_id, region_name) @@ -305,7 +306,7 @@ def __init__( version_id: int = 1, ): self.name = policy_name - self.arn = f"arn:aws:iot:{region_name}:{account_id}:policy/{policy_name}" + self.arn = f"arn:{get_partition(region_name)}:iot:{region_name}:{account_id}:policy/{policy_name}" self.document = document or {} self.is_default = is_default self._version_id = version_id @@ -369,7 +370,7 @@ def __init__( self.account_id = account_id self.region_name = region_name self.job_id = job_id - self.job_arn = f"arn:aws:iot:{self.region_name}:{self.account_id}:job/{job_id}" + self.job_arn = f"arn:{get_partition(self.region_name)}:iot:{self.region_name}:{self.account_id}:job/{job_id}" self.targets = targets self.document_source = document_source self.document = document @@ -539,7 +540,7 @@ def __init__( self.error_action = error_action or {} self.sql = sql self.aws_iot_sql_version = aws_iot_sql_version or "2016-03-23" - self.arn = f"arn:aws:iot:{self.region_name}:{self.account_id}:rule/{rule_name}" + self.arn = f"arn:{get_partition(self.region_name)}:iot:{self.region_name}:{self.account_id}:rule/{rule_name}" def to_get_dict(self) -> Dict[str, Any]: return { @@ -585,7 +586,7 @@ def __init__( f"operation: Service type {service_type} not recognized." ) self.domain_configuration_name = domain_configuration_name - self.domain_configuration_arn = f"arn:aws:iot:{region_name}:{account_id}:domainconfiguration/{domain_configuration_name}/{random.get_random_string(length=5)}" + self.domain_configuration_arn = f"arn:{get_partition(region_name)}:iot:{region_name}:{account_id}:domainconfiguration/{domain_configuration_name}/{random.get_random_string(length=5)}" self.domain_name = domain_name self.server_certificates = [] if server_certificate_arns: diff --git a/moto/ivs/models.py b/moto/ivs/models.py index dbea7b2780f9..f5a430f10de7 100644 --- a/moto/ivs/models.py +++ b/moto/ivs/models.py @@ -6,6 +6,7 @@ from moto.ivs.exceptions import ResourceNotFoundException from moto.moto_api._internal import mock_random from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition class IVSBackend(BaseBackend): @@ -36,9 +37,7 @@ def create_channel( channel_type: str, ) -> Tuple[Dict[str, Any], Dict[str, Any]]: channel_id = mock_random.get_random_string(12) - channel_arn = ( - f"arn:aws:ivs:{self.region_name}:{self.account_id}:channel/{channel_id}" - ) + channel_arn = f"arn:{get_partition(self.region_name)}:ivs:{self.region_name}:{self.account_id}:channel/{channel_id}" channel = { "arn": channel_arn, "authorized": authorized, @@ -54,7 +53,7 @@ def create_channel( } self.channels.append(channel) stream_key_id = mock_random.get_random_string(12) - stream_key_arn = f"arn:aws:ivs:{self.region_name}:{self.account_id}:stream-key/{stream_key_id}" + stream_key_arn = f"arn:{get_partition(self.region_name)}:ivs:{self.region_name}:{self.account_id}:stream-key/{stream_key_id}" stream_key = { "arn": stream_key_arn, "channelArn": channel_arn, diff --git a/moto/kinesis/models.py b/moto/kinesis/models.py index c683e30b4ced..51a4a21e0b1c 100644 --- a/moto/kinesis/models.py +++ b/moto/kinesis/models.py @@ -14,7 +14,7 @@ from moto.core.utils import unix_time, utcnow from moto.moto_api._internal import mock_random as random from moto.utilities.paginator import paginate -from moto.utilities.utils import md5_hash +from moto.utilities.utils import get_partition, md5_hash from .exceptions import ( ConsumerNotFound, @@ -51,7 +51,7 @@ def __init__( self.created = unix_time() self.stream_arn = stream_arn stream_name = stream_arn.split("/")[-1] - self.consumer_arn = f"arn:aws:kinesis:{region_name}:{account_id}:stream/{stream_name}/consumer/{consumer_name}" + self.consumer_arn = f"arn:{get_partition(region_name)}:kinesis:{region_name}:{account_id}:stream/{stream_name}/consumer/{consumer_name}" def to_json(self, include_stream_arn: bool = False) -> Dict[str, Any]: resp = { @@ -207,7 +207,7 @@ def __init__( ) self.region = region_name self.account_id = account_id - self.arn = f"arn:aws:kinesis:{region_name}:{account_id}:stream/{stream_name}" + self.arn = f"arn:{get_partition(region_name)}:kinesis:{region_name}:{account_id}:stream/{stream_name}" self.shards: Dict[str, Shard] = {} self.tags: Dict[str, str] = {} self.status = "ACTIVE" diff --git a/moto/kinesisvideo/models.py b/moto/kinesisvideo/models.py index d93d69b66237..9b35d961ca2b 100644 --- a/moto/kinesisvideo/models.py +++ b/moto/kinesisvideo/models.py @@ -4,6 +4,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import utcnow from moto.moto_api._internal import mock_random as random +from moto.utilities.utils import get_partition from .exceptions import ResourceInUseException, ResourceNotFoundException @@ -30,7 +31,7 @@ def __init__( self.status = "ACTIVE" self.version = random.get_random_string(include_digits=False, lower_case=True) self.creation_time = utcnow() - stream_arn = f"arn:aws:kinesisvideo:{region_name}:{account_id}:stream/{stream_name}/1598784211076" + stream_arn = f"arn:{get_partition(region_name)}:kinesisvideo:{region_name}:{account_id}:stream/{stream_name}/1598784211076" self.data_endpoint_number = random.get_random_hex() self.arn = stream_arn diff --git a/moto/kms/models.py b/moto/kms/models.py index 8f8c50f32013..011233bc5ae3 100644 --- a/moto/kms/models.py +++ b/moto/kms/models.py @@ -11,6 +11,7 @@ from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ValidationException from .utils import ( @@ -84,7 +85,9 @@ def __init__( self.key_manager = "CUSTOMER" self.key_spec = key_spec or "SYMMETRIC_DEFAULT" self.private_key = generate_private_key(self.key_spec) - self.arn = f"arn:aws:kms:{region}:{account_id}:key/{self.id}" + self.arn = ( + f"arn:{get_partition(region)}:kms:{region}:{account_id}:key/{self.id}" + ) self.grants: Dict[str, Grant] = dict() diff --git a/moto/kms/responses.py b/moto/kms/responses.py index 4630fbead3b7..506a9404f5e9 100644 --- a/moto/kms/responses.py +++ b/moto/kms/responses.py @@ -6,6 +6,7 @@ from moto.core.responses import BaseResponse from moto.kms.utils import RESERVED_ALIASE_TARGET_KEY_IDS, RESERVED_ALIASES +from moto.utilities.utils import get_partition from .exceptions import ( AlreadyExistsException, @@ -43,7 +44,7 @@ def _display_arn(self, key_id: str) -> str: else: id_type = "key/" - return f"arn:aws:kms:{self.region}:{self.current_account}:{id_type}{key_id}" + return f"arn:{get_partition(self.region)}:kms:{self.region}:{self.current_account}:{id_type}{key_id}" def _validate_cmk_id(self, key_id: str) -> None: """Determine whether a CMK ID exists. @@ -278,7 +279,7 @@ def list_aliases(self) -> str: # TODO: add creation date and last updated in response_aliases response_aliases.append( { - "AliasArn": f"arn:aws:kms:{region}:{self.current_account}:{alias_name}", + "AliasArn": f"arn:{get_partition(region)}:kms:{region}:{self.current_account}:{alias_name}", "AliasName": alias_name, "TargetKeyId": target_key_id, } @@ -288,7 +289,7 @@ def list_aliases(self) -> str: a for a in response_aliases if a["AliasName"] == reserved_alias ] if not exsisting: - arn = f"arn:aws:kms:{region}:{self.current_account}:{reserved_alias}" + arn = f"arn:{get_partition(region)}:kms:{region}:{self.current_account}:{reserved_alias}" response_aliases.append( { "TargetKeyId": target_key_id, diff --git a/moto/logs/models.py b/moto/logs/models.py index 63d70027f639..04f31b22a65e 100644 --- a/moto/logs/models.py +++ b/moto/logs/models.py @@ -17,6 +17,7 @@ from moto.s3.models import MissingBucket, s3_backends from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .utils import PAGINATION_MODEL, EventMessageFilter @@ -34,7 +35,7 @@ def __init__( access_policy: Optional[str] = None, ): self.access_policy = access_policy - self.arn = f"arn:aws:logs:{region}:{account_id}:destination:{destination_name}" + self.arn = f"arn:{get_partition(region)}:logs:{region}:{account_id}:destination:{destination_name}" self.creation_time = int(unix_time_millis()) self.destination_name = destination_name self.role_arn = role_arn @@ -126,7 +127,7 @@ def __init__(self, log_group: "LogGroup", name: str): self.account_id = log_group.account_id self.region = log_group.region self.log_group = log_group - self.arn = f"arn:aws:logs:{self.region}:{self.account_id}:log-group:{log_group.name}:log-stream:{name}" + self.arn = f"arn:{get_partition(self.region)}:logs:{self.region}:{self.account_id}:log-group:{log_group.name}:log-stream:{name}" self.creation_time = int(unix_time_millis()) self.first_event_timestamp = None self.last_event_timestamp = None @@ -380,7 +381,9 @@ def __init__( self.name = name self.account_id = account_id self.region = region - self.arn = f"arn:aws:logs:{region}:{account_id}:log-group:{name}" + self.arn = ( + f"arn:{get_partition(region)}:logs:{region}:{account_id}:log-group:{name}" + ) self.creation_time = int(unix_time_millis()) self.streams: Dict[str, LogStream] = dict() # {name: LogStream} # AWS defaults to Never Expire for log group retention diff --git a/moto/mediaconnect/models.py b/moto/mediaconnect/models.py index 59b7ecf2bf01..bbb34e72cdcd 100644 --- a/moto/mediaconnect/models.py +++ b/moto/mediaconnect/models.py @@ -6,6 +6,7 @@ from moto.mediaconnect.exceptions import NotFoundException from moto.moto_api._internal import mock_random as random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition class Flow(BaseModel): @@ -24,7 +25,7 @@ def __init__(self, account_id: str, region_name: str, **kwargs: Any): ) self._previous_status: Optional[str] = None self.description = "A Moto test flow" - self.flow_arn = f"arn:aws:mediaconnect:{region_name}:{account_id}:flow:{self.id}:{self.name}" + self.flow_arn = f"arn:{get_partition(region_name)}:mediaconnect:{region_name}:{account_id}:flow:{self.id}:{self.name}" self.egress_ip = "127.0.0.1" if self.source and not self.sources: self.sources = [ @@ -77,7 +78,7 @@ def _add_source_details( ) -> None: if source: source["sourceArn"] = ( - f"arn:aws:mediaconnect:{self.region_name}:{self.account_id}:source" + f"arn:{get_partition(self.region_name)}:mediaconnect:{self.region_name}:{self.account_id}:source" f":{flow_id}:{source['name']}" ) if not source.get("entitlementArn"): @@ -88,7 +89,7 @@ def _add_entitlement_details( ) -> None: if entitlement: entitlement["entitlementArn"] = ( - f"arn:aws:mediaconnect:{self.region_name}" + f"arn:{get_partition(self.region_name)}:mediaconnect:{self.region_name}" f":{self.account_id}:entitlement:{entitlement_id}" f":{entitlement['name']}" ) @@ -102,7 +103,7 @@ def _create_flow_add_details(self, flow: Flow) -> None: output["listenerAddress"] = f"{index}.0.0.0" output_id = random.uuid4().hex arn = ( - f"arn:aws:mediaconnect:{self.region_name}" + f"arn:{get_partition(self.region_name)}:mediaconnect:{self.region_name}" f":{self.account_id}:output:{output_id}:{output['name']}" ) output["outputArn"] = arn @@ -286,7 +287,7 @@ def add_flow_sources( for source in sources: source_id = random.uuid4().hex name = source["name"] - arn = f"arn:aws:mediaconnect:{self.region_name}:{self.account_id}:source:{source_id}:{name}" + arn = f"arn:{get_partition(self.region_name)}:mediaconnect:{self.region_name}:{self.account_id}:source:{source_id}:{name}" source["sourceArn"] = arn flow.sources = sources return sources @@ -351,7 +352,7 @@ def grant_flow_entitlements( for entitlement in entitlements: entitlement_id = random.uuid4().hex name = entitlement["name"] - arn = f"arn:aws:mediaconnect:{self.region_name}:{self.account_id}:entitlement:{entitlement_id}:{name}" + arn = f"arn:{get_partition(self.region_name)}:mediaconnect:{self.region_name}:{self.account_id}:entitlement:{entitlement_id}:{name}" entitlement["entitlementArn"] = arn flow.entitlements += entitlements diff --git a/moto/mq/models.py b/moto/mq/models.py index 9f3afe1956ae..f0463e7cc89b 100644 --- a/moto/mq/models.py +++ b/moto/mq/models.py @@ -8,6 +8,7 @@ from moto.core.utils import unix_time from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .configuration import DEFAULT_CONFIGURATION_DATA from .exceptions import ( @@ -75,7 +76,7 @@ def __init__( engine_version: str, ): self.id = f"c-{mock_random.get_random_hex(6)}" - self.arn = f"arn:aws:mq:{region}:{account_id}:configuration:{self.id}" + self.arn = f"arn:{get_partition(region)}:mq:{region}:{account_id}:configuration:{self.id}" self.created = unix_time() self.name = name @@ -185,7 +186,9 @@ def __init__( ): self.name = name self.id = mock_random.get_random_hex(6) - self.arn = f"arn:aws:mq:{region}:{account_id}:broker:{self.id}" + self.arn = ( + f"arn:{get_partition(region)}:mq:{region}:{account_id}:broker:{self.id}" + ) self.state = "RUNNING" self.created = unix_time() diff --git a/moto/neptune/models.py b/moto/neptune/models.py index 0023cf7bde2c..a50979c04a8d 100644 --- a/moto/neptune/models.py +++ b/moto/neptune/models.py @@ -8,7 +8,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random as random -from moto.utilities.utils import load_resource +from moto.utilities.utils import get_partition, load_resource from .exceptions import DBClusterNotFoundError @@ -111,7 +111,7 @@ def __init__( @property def db_cluster_arn(self) -> str: - return f"arn:aws:rds:{self.region_name}:{self.account_id}:cluster:{self.db_cluster_identifier}" + return f"arn:{get_partition(self.region_name)}:rds:{self.region_name}:{self.account_id}:cluster:{self.db_cluster_identifier}" def get_tags(self) -> List[Dict[str, str]]: return self.tags diff --git a/moto/opensearch/models.py b/moto/opensearch/models.py index 1b58b218340d..5032e0adc359 100644 --- a/moto/opensearch/models.py +++ b/moto/opensearch/models.py @@ -3,6 +3,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .data import compatible_versions from .exceptions import EngineTypeNotFoundException, ResourceNotFoundException @@ -66,7 +67,9 @@ def __init__( ): self.domain_id = f"{account_id}/{domain_name}" self.domain_name = domain_name - self.arn = f"arn:aws:es:{region}:{account_id}:domain/{domain_name}" + self.arn = ( + f"arn:{get_partition(region)}:es:{region}:{account_id}:domain/{domain_name}" + ) self.engine_version = engine_version or "OpenSearch 2.5" self.cluster_config = cluster_config or {} self.ebs_options = ebs_options or {"EBSEnabled": False} diff --git a/moto/opsworks/models.py b/moto/opsworks/models.py index 913c1b492613..1add8b275e84 100644 --- a/moto/opsworks/models.py +++ b/moto/opsworks/models.py @@ -5,6 +5,7 @@ from moto.core.utils import utcnow from moto.ec2 import ec2_backends from moto.moto_api._internal import mock_random as random +from moto.utilities.utils import get_partition from .exceptions import ResourceNotFoundException, ValidationException @@ -362,7 +363,7 @@ def generate_hostname(self) -> str: @property def arn(self) -> str: - return f"arn:aws:opsworks:{self.region}:{self.account_number}:stack/{self.id}" + return f"arn:{get_partition(self.region)}:opsworks:{self.region}:{self.account_number}:stack/{self.id}" def to_dict(self) -> Dict[str, Any]: response = { diff --git a/moto/organizations/models.py b/moto/organizations/models.py index 080caedd6a62..7821fdc0c576 100644 --- a/moto/organizations/models.py +++ b/moto/organizations/models.py @@ -23,12 +23,13 @@ TargetNotFoundException, ) from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition from .utils import PAGINATION_MODEL class FakeOrganization(BaseModel): - def __init__(self, account_id: str, feature_set: str): + def __init__(self, account_id: str, region_name: str, feature_set: str): self.id = utils.make_random_org_id() self.root_id = utils.make_random_root_id() self.feature_set = feature_set @@ -40,14 +41,21 @@ def __init__(self, account_id: str, feature_set: str): # This field is deprecated in AWS, but we'll return it for old time's sake {"Type": "SERVICE_CONTROL_POLICY", "Status": "ENABLED"} ] + self.region = region_name @property def arn(self) -> str: - return utils.ORGANIZATION_ARN_FORMAT.format(self.master_account_id, self.id) + partition = get_partition(self.region) + return utils.ORGANIZATION_ARN_FORMAT.format( + partition, self.master_account_id, self.id + ) @property def master_account_arn(self) -> str: - return utils.MASTER_ACCOUNT_ARN_FORMAT.format(self.master_account_id, self.id) + partition = get_partition(self.region) + return utils.MASTER_ACCOUNT_ARN_FORMAT.format( + partition, self.master_account_id, self.id + ) def describe(self) -> Dict[str, Any]: return { @@ -66,6 +74,7 @@ def describe(self) -> Dict[str, Any]: class FakeAccount(BaseModel): def __init__(self, organization: FakeOrganization, **kwargs: Any): self.type = "ACCOUNT" + self.region = organization.region self.organization_id = organization.id self.master_account_id = organization.master_account_id self.create_account_status_id = utils.make_random_create_account_status_id() @@ -81,8 +90,9 @@ def __init__(self, organization: FakeOrganization, **kwargs: Any): @property def arn(self) -> str: + partition = get_partition(self.region) return utils.ACCOUNT_ARN_FORMAT.format( - self.master_account_id, self.organization_id, self.id + partition, self.master_account_id, self.organization_id, self.id ) @property @@ -118,6 +128,7 @@ def close(self) -> None: class FakeOrganizationalUnit(BaseModel): def __init__(self, organization: FakeOrganization, **kwargs: Any): self.type = "ORGANIZATIONAL_UNIT" + self.region = organization.region self.organization_id = organization.id self.master_account_id = organization.master_account_id self.id = utils.make_random_ou_id(organization.root_id) @@ -129,8 +140,9 @@ def __init__(self, organization: FakeOrganization, **kwargs: Any): @property def arn(self) -> str: + partition = get_partition(self.region) return self._arn_format.format( - self.master_account_id, self.organization_id, self.id + partition, self.master_account_id, self.organization_id, self.id ) def describe(self) -> Dict[str, Dict[str, Any]]: @@ -199,6 +211,7 @@ def __init__(self, organization: FakeOrganization, **kwargs: Any): self.type = kwargs.get("Type", "") self.id = utils.make_random_policy_id() self.aws_managed = False + self.region = organization.region self.organization_id = organization.id self.master_account_id = organization.master_account_id self.attachments: List[Any] = [] @@ -217,8 +230,9 @@ def __init__(self, organization: FakeOrganization, **kwargs: Any): @property def arn(self) -> str: + partition = get_partition(self.region) return self._arn_format.format( - self.master_account_id, self.organization_id, self.id + partition, self.master_account_id, self.organization_id, self.id ) def describe(self) -> Dict[str, Any]: @@ -375,8 +389,12 @@ def _get_root_by_id(self, root_id: str) -> FakeRoot: return root # type: ignore[return-value] - def create_organization(self, **kwargs: Any) -> Dict[str, Any]: - self.org = FakeOrganization(self.account_id, kwargs.get("FeatureSet") or "ALL") + def create_organization(self, region: str, **kwargs: Any) -> Dict[str, Any]: + self.org = FakeOrganization( + self.account_id, + region_name=region, + feature_set=kwargs.get("FeatureSet") or "ALL", + ) root_ou = FakeRoot(self.org) self.ou.append(root_ou) master_account = FakeAccount( diff --git a/moto/organizations/responses.py b/moto/organizations/responses.py index 1f970caed0a5..a6f2507653b1 100644 --- a/moto/organizations/responses.py +++ b/moto/organizations/responses.py @@ -26,7 +26,9 @@ def _get_param(self, param_name: str, if_none: Any = None) -> Any: def create_organization(self) -> str: return json.dumps( - self.organizations_backend.create_organization(**self.request_params) + self.organizations_backend.create_organization( + region=self.region, **self.request_params + ) ) def describe_organization(self) -> str: diff --git a/moto/organizations/utils.py b/moto/organizations/utils.py index b21d25bc0d97..903449c88771 100644 --- a/moto/organizations/utils.py +++ b/moto/organizations/utils.py @@ -6,14 +6,14 @@ MASTER_ACCOUNT_EMAIL = "master@example.com" DEFAULT_POLICY_ID = "p-FullAWSAccess" -ORGANIZATION_ARN_FORMAT = "arn:aws:organizations::{0}:organization/{1}" -MASTER_ACCOUNT_ARN_FORMAT = "arn:aws:organizations::{0}:account/{1}/{0}" -ACCOUNT_ARN_FORMAT = "arn:aws:organizations::{0}:account/{1}/{2}" -ROOT_ARN_FORMAT = "arn:aws:organizations::{0}:root/{1}/{2}" -OU_ARN_FORMAT = "arn:aws:organizations::{0}:ou/{1}/{2}" -SCP_ARN_FORMAT = "arn:aws:organizations::{0}:policy/{1}/service_control_policy/{2}" +ORGANIZATION_ARN_FORMAT = "arn:{0}:organizations::{1}:organization/{2}" +MASTER_ACCOUNT_ARN_FORMAT = "arn:{0}:organizations::{1}:account/{2}/{1}" +ACCOUNT_ARN_FORMAT = "arn:{0}:organizations::{1}:account/{2}/{3}" +ROOT_ARN_FORMAT = "arn:{0}:organizations::{1}:root/{2}/{3}" +OU_ARN_FORMAT = "arn:{0}:organizations::{1}:ou/{2}/{3}" +SCP_ARN_FORMAT = "arn:{0}:organizations::{1}:policy/{2}/service_control_policy/{3}" AI_POLICY_ARN_FORMAT = ( - "arn:aws:organizations::{0}:policy/{1}/aiservices_opt_out_policy/{2}" + "arn:{0}:organizations::{1}:policy/{2}/aiservices_opt_out_policy/{3}" ) CHARSET = string.ascii_lowercase + string.digits diff --git a/moto/panorama/utils.py b/moto/panorama/utils.py index d5c676d6323c..8118a4a243a5 100644 --- a/moto/panorama/utils.py +++ b/moto/panorama/utils.py @@ -3,6 +3,8 @@ from datetime import datetime from typing import Any +from moto.utilities.utils import get_partition + def deep_convert_datetime_to_isoformat(obj: Any) -> Any: if isinstance(obj, datetime): @@ -31,4 +33,4 @@ def generate_package_id(name: str) -> str: def arn_formatter(_type: str, _id: str, account_id: str, region_name: str) -> str: - return f"arn:aws:panorama:{region_name}:{account_id}:{_type}/{_id}" + return f"arn:{get_partition(region_name)}:panorama:{region_name}:{account_id}:{_type}/{_id}" diff --git a/moto/personalize/models.py b/moto/personalize/models.py index 8936fb296173..8f5edf08b997 100644 --- a/moto/personalize/models.py +++ b/moto/personalize/models.py @@ -3,6 +3,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.core.utils import unix_time +from moto.utilities.utils import get_partition from .exceptions import ResourceNotFoundException @@ -19,7 +20,7 @@ def __init__( self.name = name self.schema = schema self.domain = domain - self.arn = f"arn:aws:personalize:{region}:{account_id}:schema/{name}" + self.arn = f"arn:{get_partition(region)}:personalize:{region}:{account_id}:schema/{name}" self.created = unix_time() def to_dict(self, full: bool = True) -> Dict[str, Any]: diff --git a/moto/polly/utils.py b/moto/polly/utils.py index e946674b2d93..3c10a04b9ab7 100644 --- a/moto/polly/utils.py +++ b/moto/polly/utils.py @@ -1,2 +1,5 @@ +from moto.utilities.utils import get_partition + + def make_arn_for_lexicon(account_id: str, name: str, region_name: str) -> str: - return f"arn:aws:polly:{region_name}:{account_id}:lexicon/{name}" + return f"arn:{get_partition(region_name)}:polly:{region_name}:{account_id}:lexicon/{name}" diff --git a/moto/quicksight/models.py b/moto/quicksight/models.py index 76fd74e62b35..e7f0f8b980be 100644 --- a/moto/quicksight/models.py +++ b/moto/quicksight/models.py @@ -3,6 +3,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.moto_api._internal import mock_random as random +from moto.utilities.utils import get_partition from .exceptions import ResourceNotFoundException @@ -13,7 +14,7 @@ def _create_id(aws_account_id: str, namespace: str, _id: str) -> str: class QuicksightDataSet(BaseModel): def __init__(self, account_id: str, region: str, _id: str, name: str): - self.arn = f"arn:aws:quicksight:{region}:{account_id}:data-set/{_id}" + self.arn = f"arn:{get_partition(region)}:quicksight:{region}:{account_id}:data-set/{_id}" self._id = _id self.name = name self.region = region @@ -23,7 +24,7 @@ def to_json(self) -> Dict[str, Any]: return { "Arn": self.arn, "DataSetId": self._id, - "IngestionArn": f"arn:aws:quicksight:{self.region}:{self.account_id}:ingestion/tbd", + "IngestionArn": f"arn:{get_partition(self.region)}:quicksight:{self.region}:{self.account_id}:ingestion/tbd", } @@ -31,7 +32,7 @@ class QuicksightIngestion(BaseModel): def __init__( self, account_id: str, region: str, data_set_id: str, ingestion_id: str ): - self.arn = f"arn:aws:quicksight:{region}:{account_id}:data-set/{data_set_id}/ingestions/{ingestion_id}" + self.arn = f"arn:{get_partition(region)}:quicksight:{region}:{account_id}:data-set/{data_set_id}/ingestions/{ingestion_id}" self.ingestion_id = ingestion_id def to_json(self) -> Dict[str, Any]: @@ -46,9 +47,7 @@ class QuicksightMembership(BaseModel): def __init__(self, account_id: str, region: str, group: str, user: str): self.group = group self.user = user - self.arn = ( - f"arn:aws:quicksight:{region}:{account_id}:group/default/{group}/{user}" - ) + self.arn = f"arn:{get_partition(region)}:quicksight:{region}:{account_id}:group/default/{group}/{user}" def to_json(self) -> Dict[str, str]: return {"Arn": self.arn, "MemberName": self.user} @@ -63,9 +62,7 @@ def __init__( aws_account_id: str, namespace: str, ): - self.arn = ( - f"arn:aws:quicksight:{region}:{aws_account_id}:group/default/{group_name}" - ) + self.arn = f"arn:{get_partition(region)}:quicksight:{region}:{aws_account_id}:group/default/{group_name}" self.group_name = group_name self.description = description self.aws_account_id = aws_account_id @@ -110,7 +107,7 @@ def __init__( username: str, user_role: str, ): - self.arn = f"arn:aws:quicksight:{region}:{account_id}:user/default/{username}" + self.arn = f"arn:{get_partition(region)}:quicksight:{region}:{account_id}:user/default/{username}" self.email = email self.identity_type = identity_type self.username = username diff --git a/moto/ram/models.py b/moto/ram/models.py index 7499dd43e50c..6e06c108ee64 100644 --- a/moto/ram/models.py +++ b/moto/ram/models.py @@ -13,6 +13,7 @@ OperationNotPermittedException, UnknownResourceException, ) +from moto.utilities.utils import get_partition def random_resource_id(size: int) -> str: @@ -43,9 +44,7 @@ def __init__(self, account_id: str, region: str, **kwargs: Any): self.region = region self.allow_external_principals = kwargs.get("allowExternalPrincipals", True) - self.arn = ( - f"arn:aws:ram:{self.region}:{account_id}:resource-share/{random.uuid4()}" - ) + self.arn = f"arn:{get_partition(self.region)}:ram:{self.region}:{account_id}:resource-share/{random.uuid4()}" self.creation_time = utcnow() self.feature_set = "STANDARD" self.last_updated_time = utcnow() diff --git a/moto/rds/models.py b/moto/rds/models.py index 3eccad7f2c69..d2776be074c7 100644 --- a/moto/rds/models.py +++ b/moto/rds/models.py @@ -14,7 +14,7 @@ from moto.ec2.models import ec2_backends from moto.moto_api._internal import mock_random as random from moto.neptune.models import NeptuneBackend, neptune_backends -from moto.utilities.utils import load_resource +from moto.utilities.utils import get_partition, load_resource from .exceptions import ( DBClusterNotFoundError, @@ -160,7 +160,7 @@ def __init__(self, **kwargs: Any): self.network_type = kwargs.get("network_type") or "IPV4" self.status = "active" self.account_id = kwargs.get("account_id") - self.region_name = kwargs.get("region") + self.region_name = kwargs["region"] self.cluster_create_time = iso_8601_datetime_with_milliseconds() self.copy_tags_to_snapshot = kwargs.get("copy_tags_to_snapshot") if self.copy_tags_to_snapshot is None: @@ -259,7 +259,7 @@ def arn(self) -> str: @property def db_cluster_arn(self) -> str: - return f"arn:aws:rds:{self.region_name}:{self.account_id}:cluster:{self.db_cluster_identifier}" + return f"arn:{get_partition(self.region_name)}:rds:{self.region_name}:{self.account_id}:cluster:{self.db_cluster_identifier}" @property def master_user_password(self) -> str: @@ -510,7 +510,7 @@ def arn(self) -> str: @property def snapshot_arn(self) -> str: - return f"arn:aws:rds:{self.cluster.region_name}:{self.cluster.account_id}:cluster-snapshot:{self.snapshot_id}" + return f"arn:{get_partition(self.cluster.region_name)}:rds:{self.cluster.region_name}:{self.cluster.account_id}:cluster-snapshot:{self.snapshot_id}" def to_xml(self) -> str: template = Template( @@ -699,7 +699,7 @@ def arn(self) -> str: @property def db_instance_arn(self) -> str: - return f"arn:aws:rds:{self.region_name}:{self.account_id}:db:{self.db_instance_identifier}" + return f"arn:{get_partition(self.region_name)}:rds:{self.region_name}:{self.account_id}:db:{self.db_instance_identifier}" @property def physical_resource_id(self) -> Optional[str]: @@ -1148,7 +1148,7 @@ def arn(self) -> str: @property def snapshot_arn(self) -> str: - return f"arn:aws:rds:{self.database.region_name}:{self.database.account_id}:snapshot:{self.snapshot_id}" + return f"arn:{get_partition(self.database.region_name)}:rds:{self.database.region_name}:{self.database.account_id}:snapshot:{self.snapshot_id}" def to_xml(self) -> str: template = Template( @@ -1281,7 +1281,7 @@ def __init__(self, kwargs: Dict[str, Any]): @property def es_arn(self) -> str: - return f"arn:aws:rds:{self.region_name}:{self.customer_aws_id}:es:{self.subscription_name}" + return f"arn:{get_partition(self.region_name)}:rds:{self.region_name}:{self.customer_aws_id}:es:{self.subscription_name}" def to_xml(self) -> str: template = Template( @@ -1476,7 +1476,7 @@ def __init__( @property def sg_arn(self) -> str: - return f"arn:aws:rds:{self.region}:{self.account_id}:subgrp:{self.subnet_name}" + return f"arn:{get_partition(self.region)}:rds:{self.region}:{self.account_id}:subgrp:{self.subnet_name}" def to_xml(self) -> str: template = Template( @@ -1620,7 +1620,7 @@ def __init__( self.tags = tags self.region_name = region_name self.account_id = account_id - self.db_proxy_arn = f"arn:aws:rds:{self.region_name}:{self.account_id}:db-proxy:{self.db_proxy_name}" + self.db_proxy_arn = f"arn:{get_partition(self.region_name)}:rds:{self.region_name}:{self.account_id}:db-proxy:{self.db_proxy_name}" self.arn = self.db_proxy_arn ec2_backend = ec2_backends[self.account_id][self.region_name] subnets = ec2_backend.describe_subnets(subnet_ids=self.vpc_subnet_ids) @@ -3107,7 +3107,7 @@ def __init__( self.options: Dict[str, Any] = {} self.vpcId = "null" self.tags: List[Dict[str, str]] = [] - self.arn = f"arn:aws:rds:{region}:{account_id}:og:{name}" + self.arn = f"arn:{get_partition(region)}:rds:{region}:{account_id}:og:{name}" def to_json(self) -> str: template = Template( @@ -3182,7 +3182,7 @@ def __init__( self.family = family self.tags = tags self.parameters: Dict[str, Any] = defaultdict(dict) - self.arn = f"arn:aws:rds:{region}:{account_id}:pg:{name}" + self.arn = f"arn:{get_partition(region)}:rds:{region}:{account_id}:pg:{name}" def to_xml(self) -> str: template = Template( @@ -3266,7 +3266,7 @@ def __init__( self.description = description self.family = family self.parameters: Dict[str, Any] = defaultdict(dict) - self.arn = f"arn:aws:rds:{region}:{account_id}:cpg:{name}" + self.arn = f"arn:{get_partition(region)}:rds:{region}:{account_id}:cpg:{name}" def to_xml(self) -> str: template = Template( diff --git a/moto/redshift/models.py b/moto/redshift/models.py index a885b1145335..13530dedbd2f 100644 --- a/moto/redshift/models.py +++ b/moto/redshift/models.py @@ -11,6 +11,7 @@ from moto.ec2 import ec2_backends from moto.ec2.models.security_groups import SecurityGroup as EC2SecurityGroup from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition from .exceptions import ( ClusterAlreadyExistsFaultError, @@ -51,10 +52,7 @@ def resource_id(self) -> str: @property def arn(self) -> str: - return ( - f"arn:aws:redshift:{self.region}:{self.account_id}" - f":{self.resource_type}:{self.resource_id}" - ) + return f"arn:{get_partition(self.region)}:redshift:{self.region}:{self.account_id}:{self.resource_type}:{self.resource_id}" def create_tags(self, tags: List[Dict[str, str]]) -> List[Dict[str, str]]: new_keys = [tag_set["Key"] for tag_set in tags] diff --git a/moto/resiliencehub/models.py b/moto/resiliencehub/models.py index d6ec83ab868d..b74f22be1c6f 100644 --- a/moto/resiliencehub/models.py +++ b/moto/resiliencehub/models.py @@ -6,6 +6,7 @@ from moto.moto_api._internal import mock_random from moto.utilities.paginator import paginate from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import AppNotFound, AppVersionNotFound, ResiliencyPolicyNotFound @@ -51,7 +52,7 @@ def __init__( policy_arn: str, ): self.backend = backend - self.arn = f"arn:aws:resiliencehub:{backend.region_name}:{backend.account_id}:app/{mock_random.uuid4()}" + self.arn = f"arn:{get_partition(backend.region_name)}:resiliencehub:{backend.region_name}:{backend.account_id}:app/{mock_random.uuid4()}" self.assessment_schedule = assessment_schedule or "Disabled" self.compliance_status = "NotAssessed" self.description = description @@ -154,7 +155,7 @@ def __init__( policy_description: str, tier: str, ): - self.arn = f"arn:aws:resiliencehub:{backend.region_name}:{backend.account_id}:resiliency-policy/{mock_random.uuid4()}" + self.arn = f"arn:{get_partition(backend.region_name)}:resiliencehub:{backend.region_name}:{backend.account_id}:resiliency-policy/{mock_random.uuid4()}" self.backend = backend self.data_location_constraint = data_location_constraint self.creation_time = unix_time() diff --git a/moto/resourcegroupstaggingapi/models.py b/moto/resourcegroupstaggingapi/models.py index 07c08d087b39..3215b249d37c 100644 --- a/moto/resourcegroupstaggingapi/models.py +++ b/moto/resourcegroupstaggingapi/models.py @@ -24,6 +24,7 @@ from moto.sqs.models import SQSBackend, sqs_backends from moto.ssm.models import SimpleSystemManagerBackend, ssm_backends from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from moto.workspaces.models import WorkSpacesBackend, workspaces_backends # Left: EC2 ElastiCache RDS ELB CloudFront Lambda EMR Glacier Kinesis Redshift Route53 @@ -376,7 +377,7 @@ def format_tag_keys( continue yield { - "ResourceARN": f"arn:aws:elasticloadbalancing:{self.region_name}:{self.account_id}:loadbalancer/{elb.name}", + "ResourceARN": f"arn:{get_partition(self.region_name)}:elasticloadbalancing:{self.region_name}:{self.account_id}:loadbalancer/{elb.name}", "Tags": tags, } @@ -421,7 +422,7 @@ def format_tag_keys( ): if not resource_type_filters or "glue" in resource_type_filters: arns_starting_with = [ - f"arn:aws:glue:{self.region_name}:{self.account_id}:" + f"arn:{get_partition(self.region_name)}:glue:{self.region_name}:{self.account_id}:" ] else: arns_starting_with = [] @@ -429,7 +430,7 @@ def format_tag_keys( if resource_type.startswith("glue:"): glue_type = resource_type.split(":")[-1] arns_starting_with.append( - f"arn:aws:glue:{self.region_name}:{self.account_id}:{glue_type}" + f"arn:{get_partition(self.region_name)}:glue:{self.region_name}:{self.account_id}:{glue_type}" ) for glue_arn in self.glue_backend.tagger.tags.keys(): if any(glue_arn.startswith(arn) for arn in arns_starting_with): @@ -535,7 +536,7 @@ def format_tag_keys( ): # Skip if no tags, or invalid filter continue yield { - "ResourceARN": f"arn:aws:ssm:{self.region_name}:{self.account_id}:document/{doc_name}", + "ResourceARN": f"arn:{get_partition(self.region_name)}:ssm:{self.region_name}:{self.account_id}:document/{doc_name}", "Tags": tags, } @@ -551,7 +552,7 @@ def format_tag_keys( continue yield { - "ResourceARN": f"arn:aws:workspaces:{self.region_name}:{self.account_id}:workspace/{ws.workspace_id}", + "ResourceARN": f"arn:{get_partition(self.region_name)}:workspaces:{self.region_name}:{self.account_id}:workspace/{ws.workspace_id}", "Tags": tags, } @@ -567,7 +568,7 @@ def format_tag_keys( continue yield { - "ResourceARN": f"arn:aws:workspaces:{self.region_name}:{self.account_id}:directory/{wd.directory_id}", + "ResourceARN": f"arn:{get_partition(self.region_name)}:workspaces:{self.region_name}:{self.account_id}:directory/{wd.directory_id}", "Tags": tags, } @@ -583,7 +584,7 @@ def format_tag_keys( continue yield { - "ResourceARN": f"arn:aws:workspaces:{self.region_name}:{self.account_id}:workspaceimage/{wi.image_id}", + "ResourceARN": f"arn:{get_partition(self.region_name)}:workspaces:{self.region_name}:{self.account_id}:workspaceimage/{wi.image_id}", "Tags": tags, } diff --git a/moto/robomaker/models.py b/moto/robomaker/models.py index f1feacc9417e..bb51184df42e 100644 --- a/moto/robomaker/models.py +++ b/moto/robomaker/models.py @@ -3,6 +3,7 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel from moto.core.utils import unix_time +from moto.utilities.utils import get_partition class RobotApplication(BaseModel): @@ -23,7 +24,7 @@ def __init__( @property def arn(self) -> str: - return f"arn:aws:robomaker:{self.region}:{self.account_id}:robot-application/{self.name}/{self.created_on}" + return f"arn:{get_partition(self.region)}:robomaker:{self.region}:{self.account_id}:robot-application/{self.name}/{self.created_on}" def to_dict(self) -> Dict[str, Any]: return { diff --git a/moto/route53/models.py b/moto/route53/models.py index cdea39895cc6..34e477446eff 100644 --- a/moto/route53/models.py +++ b/moto/route53/models.py @@ -31,6 +31,7 @@ ResourceRecordAlreadyExists, ) from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition from .utils import PAGINATION_MODEL @@ -866,7 +867,9 @@ def get_health_check_status(self) -> None: @staticmethod def _validate_arn(region: str, arn: str) -> None: - match = re.match(rf"arn:aws:logs:{region}:\d{{12}}:log-group:.+", arn) + match = re.match( + rf"arn:{get_partition(region)}:logs:{region}:\d{{12}}:log-group:.+", arn + ) if not arn or not match: raise InvalidCloudWatchArn() diff --git a/moto/sagemaker/models.py b/moto/sagemaker/models.py index 8befdc28e61b..1857aff9aa16 100644 --- a/moto/sagemaker/models.py +++ b/moto/sagemaker/models.py @@ -11,6 +11,7 @@ from moto.core.common_models import BaseModel, CloudFormationModel from moto.sagemaker import validators from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition from .exceptions import ( AWSValidationException, @@ -2281,8 +2282,8 @@ def disassociate_trial_component( ) return { - "TrialComponentArn": f"arn:aws:sagemaker:{self.region_name}:{self.account_id}:experiment-trial-component/{trial_component_name}", - "TrialArn": f"arn:aws:sagemaker:{self.region_name}:{self.account_id}:experiment-trial/{trial_name}", + "TrialComponentArn": f"arn:{get_partition(self.region_name)}:sagemaker:{self.region_name}:{self.account_id}:experiment-trial-component/{trial_component_name}", + "TrialArn": f"arn:{get_partition(self.region_name)}:sagemaker:{self.region_name}:{self.account_id}:experiment-trial/{trial_name}", } def update_trial_component( diff --git a/moto/sagemaker/utils.py b/moto/sagemaker/utils.py index ae651eb1ceb2..0e62d8ea6e3f 100644 --- a/moto/sagemaker/utils.py +++ b/moto/sagemaker/utils.py @@ -3,6 +3,7 @@ from typing import Any, Dict from moto.s3.models import s3_backends +from moto.utilities.utils import get_partition from .exceptions import ValidationError @@ -50,7 +51,7 @@ def load_pipeline_definition_from_s3( def arn_formatter(_type: str, _id: str, account_id: str, region_name: str) -> str: - return f"arn:aws:sagemaker:{region_name}:{account_id}:{_type}/{_id}" + return f"arn:{get_partition(region_name)}:sagemaker:{region_name}:{account_id}:{_type}/{_id}" def validate_model_approval_status(model_approval_status: typing.Optional[str]) -> None: diff --git a/moto/scheduler/models.py b/moto/scheduler/models.py index f65e07bb14bd..626194c66389 100644 --- a/moto/scheduler/models.py +++ b/moto/scheduler/models.py @@ -6,6 +6,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import unix_time from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ScheduleExists, ScheduleGroupNotFound, ScheduleNotFound @@ -30,9 +31,7 @@ def __init__( self.name = name self.group_name = group_name self.description = description - self.arn = ( - f"arn:aws:scheduler:{region}:{account_id}:schedule/{group_name}/{name}" - ) + self.arn = f"arn:{get_partition(region)}:scheduler:{region}:{account_id}:schedule/{group_name}/{name}" self.schedule_expression = schedule_expression self.schedule_expression_timezone = schedule_expression_timezone self.flexible_time_window = flexible_time_window @@ -100,7 +99,7 @@ def update( class ScheduleGroup(BaseModel): def __init__(self, region: str, account_id: str, name: str): self.name = name - self.arn = f"arn:aws:scheduler:{region}:{account_id}:schedule-group/{name}" + self.arn = f"arn:{get_partition(region)}:scheduler:{region}:{account_id}:schedule-group/{name}" self.schedules: Dict[str, Schedule] = dict() self.created_on = None if self.name == "default" else unix_time() self.last_modified = None if self.name == "default" else unix_time() diff --git a/moto/secretsmanager/utils.py b/moto/secretsmanager/utils.py index 291781842920..d58c9d3caa13 100644 --- a/moto/secretsmanager/utils.py +++ b/moto/secretsmanager/utils.py @@ -2,6 +2,7 @@ import string from moto.moto_api._internal import mock_random as random +from moto.utilities.utils import get_partition def random_password( @@ -63,9 +64,7 @@ def random_password( def secret_arn(account_id: str, region: str, secret_id: str) -> str: id_string = "".join(random.choice(string.ascii_letters) for _ in range(6)) - return ( - f"arn:aws:secretsmanager:{region}:{account_id}:secret:{secret_id}-{id_string}" - ) + return f"arn:{get_partition(region)}:secretsmanager:{region}:{account_id}:secret:{secret_id}-{id_string}" def get_secret_name_from_partial_arn(partial_arn: str) -> str: diff --git a/moto/servicediscovery/models.py b/moto/servicediscovery/models.py index 825a25bce1bc..444c9a6f8447 100644 --- a/moto/servicediscovery/models.py +++ b/moto/servicediscovery/models.py @@ -6,6 +6,7 @@ from moto.core.utils import unix_time from moto.moto_api._internal import mock_random as random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ( ConflictingDomainExists, @@ -35,7 +36,7 @@ def __init__( vpc: Optional[str] = None, ): self.id = f"ns-{random_id(20)}" - self.arn = f"arn:aws:servicediscovery:{region}:{account_id}:namespace/{self.id}" + self.arn = f"arn:{get_partition(region)}:servicediscovery:{region}:{account_id}:namespace/{self.id}" self.name = name self.type = ns_type self.creator_request_id = creator_request_id @@ -78,7 +79,7 @@ def __init__( service_type: str, ): self.id = f"srv-{random_id(8)}" - self.arn = f"arn:aws:servicediscovery:{region}:{account_id}:service/{self.id}" + self.arn = f"arn:{get_partition(region)}:servicediscovery:{region}:{account_id}:service/{self.id}" self.name = name self.namespace_id = namespace_id self.description = description diff --git a/moto/signer/models.py b/moto/signer/models.py index 4a85d0f53043..2c46b07bd08f 100644 --- a/moto/signer/models.py +++ b/moto/signer/models.py @@ -4,6 +4,7 @@ from moto.core.common_models import BaseModel from moto.moto_api._internal import mock_random from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition class SigningProfile(BaseModel): @@ -24,7 +25,7 @@ def __init__( self.backend = backend self.status = "Active" - self.arn = f"arn:aws:signer:{backend.region_name}:{backend.account_id}:/signing-profiles/{name}" + self.arn = f"arn:{get_partition(backend.region_name)}:signer:{backend.region_name}:{backend.account_id}:/signing-profiles/{name}" self.profile_version = mock_random.get_random_hex(10) self.profile_version_arn = f"{self.arn}/{self.profile_version}" self.signing_material = signing_material diff --git a/moto/sns/models.py b/moto/sns/models.py index a3459de589b0..4ca029d35965 100644 --- a/moto/sns/models.py +++ b/moto/sns/models.py @@ -16,6 +16,7 @@ from moto.sqs import sqs_backends from moto.sqs.exceptions import MissingParameter from moto.utilities.arns import parse_arn +from moto.utilities.utils import get_partition from .exceptions import ( BatchEntryIdsNotDistinct, @@ -325,7 +326,7 @@ def __init__( self.name = name self.platform = platform self.attributes = attributes - self.arn = f"arn:aws:sns:{region}:{account_id}:app/{platform}/{name}" + self.arn = f"arn:{get_partition(region)}:sns:{region}:{account_id}:app/{platform}/{name}" class PlatformEndpoint(BaseModel): @@ -344,7 +345,7 @@ def __init__( self.token = token self.attributes = attributes self.id = mock_random.uuid4() - self.arn = f"arn:aws:sns:{region}:{account_id}:endpoint/{self.application.platform}/{self.application.name}/{self.id}" + self.arn = f"arn:{get_partition(region)}:sns:{region}:{account_id}:endpoint/{self.application.platform}/{self.application.name}/{self.id}" self.messages: Dict[str, str] = OrderedDict() self.__fixup_attributes() diff --git a/moto/sns/utils.py b/moto/sns/utils.py index fb6c0ed53b56..e5764d213a33 100644 --- a/moto/sns/utils.py +++ b/moto/sns/utils.py @@ -3,12 +3,13 @@ from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union from moto.moto_api._internal import mock_random +from moto.utilities.utils import get_partition E164_REGEX = re.compile(r"^\+?[1-9]\d{1,14}$") def make_arn_for_topic(account_id: str, name: str, region_name: str) -> str: - return f"arn:aws:sns:{region_name}:{account_id}:{name}" + return f"arn:{get_partition(region_name)}:sns:{region_name}:{account_id}:{name}" def make_arn_for_subscription(topic_arn: str) -> str: diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 4facfb228a08..2d4deefcf24d 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -20,7 +20,7 @@ unix_time_millis, ) from moto.moto_api._internal import mock_random as random -from moto.utilities.utils import md5_hash +from moto.utilities.utils import get_partition, md5_hash from .constants import MAXIMUM_VISIBILITY_TIMEOUT from .exceptions import ( @@ -278,7 +278,7 @@ def __init__(self, name: str, region: str, account_id: str, **kwargs: Any): now = unix_time() self.created_timestamp = now - self.queue_arn = f"arn:aws:sqs:{region}:{account_id}:{name}" + self.queue_arn = f"arn:{get_partition(region)}:sqs:{region}:{account_id}:{name}" self.dead_letter_queue: Optional["Queue"] = None self.fifo_queue = False diff --git a/moto/ssm/utils.py b/moto/ssm/utils.py index b5dc590e1115..b05ae20fd512 100644 --- a/moto/ssm/utils.py +++ b/moto/ssm/utils.py @@ -1,10 +1,12 @@ from typing import Any, Dict, List +from moto.utilities.utils import get_partition + def parameter_arn(account_id: str, region: str, parameter_name: str) -> str: if parameter_name[0] == "/": parameter_name = parameter_name[1:] - return f"arn:aws:ssm:{region}:{account_id}:parameter/{parameter_name}" + return f"arn:{get_partition(region)}:ssm:{region}:{account_id}:parameter/{parameter_name}" def convert_to_tree(parameters: List[Dict[str, Any]]) -> Dict[str, Any]: diff --git a/moto/stepfunctions/models.py b/moto/stepfunctions/models.py index d6610053237b..5c450714286b 100644 --- a/moto/stepfunctions/models.py +++ b/moto/stepfunctions/models.py @@ -11,6 +11,7 @@ from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.moto_api._internal import mock_random from moto.utilities.paginator import paginate +from moto.utilities.utils import get_partition from .exceptions import ( ExecutionAlreadyExists, @@ -494,13 +495,13 @@ class StepFunctionBackend(BaseBackend): "\u009f", ] accepted_role_arn_format = re.compile( - "arn:aws:iam::(?P[0-9]{12}):role/.+" + r"arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):iam::(?P[0-9]{12}):role/.+" ) accepted_mchn_arn_format = re.compile( - "arn:aws:states:[-0-9a-zA-Z]+:(?P[0-9]{12}):stateMachine:.+" + r"arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):states:[-0-9a-zA-Z]+:(?P[0-9]{12}):stateMachine:.+" ) accepted_exec_arn_format = re.compile( - "arn:aws:states:[-0-9a-zA-Z]+:(?P[0-9]{12}):execution:.+" + r"arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b):states:[-0-9a-zA-Z]+:(?P[0-9]{12}):execution:.+" ) def __init__(self, region_name: str, account_id: str): @@ -517,7 +518,7 @@ def create_state_machine( ) -> StateMachine: self._validate_name(name) self._validate_role_arn(roleArn) - arn = f"arn:aws:states:{self.region_name}:{self.account_id}:stateMachine:{name}" + arn = f"arn:{get_partition(self.region_name)}:states:{self.region_name}:{self.account_id}:stateMachine:{name}" try: return self.describe_state_machine(arn) except StateMachineDoesNotExist: diff --git a/moto/sts/models.py b/moto/sts/models.py index 5fbb9cfb1fa9..09dc88f5d337 100644 --- a/moto/sts/models.py +++ b/moto/sts/models.py @@ -7,17 +7,14 @@ from moto.core.base_backend import BackendDict, BaseBackend from moto.core.common_models import BaseModel -from moto.core.utils import ( - get_partition_from_region, - iso_8601_datetime_with_milliseconds, - utcnow, -) +from moto.core.utils import iso_8601_datetime_with_milliseconds, utcnow from moto.iam.models import AccessKey, iam_backends from moto.sts.utils import ( DEFAULT_STS_SESSION_DURATION, random_assumed_role_id, random_session_token, ) +from moto.utilities.utils import get_partition class Token(BaseModel): @@ -72,7 +69,7 @@ def user_id(self) -> str: @property def arn(self) -> str: - partition = get_partition_from_region(self.region_name) + partition = get_partition(self.region_name) return f"arn:{partition}:sts::{self.account_id}:assumed-role/{self.role_arn.split('/')[-1]}/{self.session_name}" @@ -188,7 +185,7 @@ def get_caller_identity( return user.id, user.arn, user.account_id # Default values in case the request does not use valid credentials generated by moto - partition = get_partition_from_region(region) + partition = get_partition(region) user_id = "AKIAIOSFODNN7EXAMPLE" arn = f"arn:{partition}:sts::{self.account_id}:user/moto" return user_id, arn, self.account_id diff --git a/moto/swf/models/domain.py b/moto/swf/models/domain.py index 01c9011ad204..642a5f2cbd7a 100644 --- a/moto/swf/models/domain.py +++ b/moto/swf/models/domain.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional from moto.core.common_models import BaseModel +from moto.utilities.utils import get_partition from ..exceptions import ( SWFUnknownResourceFault, @@ -51,7 +52,7 @@ def to_short_dict(self) -> Dict[str, str]: if self.description: hsh["description"] = self.description hsh["arn"] = ( - f"arn:aws:swf:{self.region_name}:{self.account_id}:/domain/{self.name}" + f"arn:{get_partition(self.region_name)}:swf:{self.region_name}:{self.account_id}:/domain/{self.name}" ) return hsh diff --git a/moto/timestreamwrite/models.py b/moto/timestreamwrite/models.py index 695bf8c7389a..a761cc369d26 100644 --- a/moto/timestreamwrite/models.py +++ b/moto/timestreamwrite/models.py @@ -4,6 +4,7 @@ from moto.core.common_models import BaseModel from moto.core.utils import unix_time from moto.utilities.tagging_service import TaggingService +from moto.utilities.utils import get_partition from .exceptions import ResourceNotFound @@ -37,7 +38,7 @@ def __init__( ] } self.records: List[Dict[str, Any]] = [] - self.arn = f"arn:aws:timestream:{self.region_name}:{account_id}:database/{self.db_name}/table/{self.name}" + self.arn = f"arn:{get_partition(self.region_name)}:timestream:{self.region_name}:{account_id}:database/{self.db_name}/table/{self.name}" def update( self, @@ -74,11 +75,10 @@ def __init__( self.region_name = region_name self.name = database_name self.kms_key_id = ( - kms_key_id or f"arn:aws:kms:{region_name}:{account_id}:key/default_key" - ) - self.arn = ( - f"arn:aws:timestream:{self.region_name}:{account_id}:database/{self.name}" + kms_key_id + or f"arn:{get_partition(region_name)}:kms:{region_name}:{account_id}:key/default_key" ) + self.arn = f"arn:{get_partition(self.region_name)}:timestream:{self.region_name}:{account_id}:database/{self.name}" self.created_on = unix_time() self.updated_on = unix_time() self.tables: Dict[str, TimestreamTable] = dict() diff --git a/moto/utilities/utils.py b/moto/utilities/utils.py index a7caffb4534e..5c889eea320a 100644 --- a/moto/utilities/utils.py +++ b/moto/utilities/utils.py @@ -4,6 +4,21 @@ from typing import Any, Dict, Iterator, List, MutableMapping, Optional, Tuple, TypeVar +def get_partition(region: str) -> str: + valid_matches = [ + # (region prefix, aws partition) + ("cn-", "aws-cn"), + ("us-gov-", "aws-us-gov"), + ("us-iso-", "aws-iso"), + ("us-isob-", "aws-iso-b"), + ] + + for prefix, partition in valid_matches: + if region.startswith(prefix): + return partition + return "aws" + + def str2bool(v: Any) -> Optional[bool]: if v in ("yes", True, "true", "True", "TRUE", "t", "1"): return True diff --git a/tests/test_awslambda/test_lambda.py b/tests/test_awslambda/test_lambda.py index 3bcffa387c0c..cc61de8fd44f 100644 --- a/tests/test_awslambda/test_lambda.py +++ b/tests/test_awslambda/test_lambda.py @@ -45,6 +45,30 @@ def test_lambda_regions(region): resp = client.list_functions() assert resp["ResponseMetadata"]["HTTPStatusCode"] == 200 + function_name = "moto_test_" + str(uuid4())[0:6] + function = client.create_function( + FunctionName=function_name, + Runtime=PYTHON_VERSION, + Role=get_role_name(), + Handler="lambda_function.lambda_handler", + Code={"ZipFile": get_test_zip_file1()}, + ) + if region == "us-west-2": + assert ( + function["FunctionArn"] + == f"arn:aws:lambda:{region}:{ACCOUNT_ID}:function:{function_name}" + ) + if region == "cn-northwest-1": + assert ( + function["FunctionArn"] + == f"arn:aws-cn:lambda:{region}:{ACCOUNT_ID}:function:{function_name}" + ) + if region == "us-isob-east-1": + assert ( + function["FunctionArn"] + == f"arn:aws-iso-b:lambda:{region}:{ACCOUNT_ID}:function:{function_name}" + ) + @pytest.mark.aws_verified @lambda_aws_verified diff --git a/tests/test_kms/test_kms_policy_enforcement.py b/tests/test_kms/test_kms_policy_enforcement.py index 9f77f11bf4da..908dfcd5caa0 100644 --- a/tests/test_kms/test_kms_policy_enforcement.py +++ b/tests/test_kms/test_kms_policy_enforcement.py @@ -122,7 +122,7 @@ def create_key(self, policy): with mock.patch.object(rsa, "generate_private_key", return_value=""): return Key( account_id=None, - region=None, + region="us-east-1", description=None, key_spec=None, key_usage=None, diff --git a/tests/test_organizations/organizations_test_utils.py b/tests/test_organizations/organizations_test_utils.py index 3c92fb1a3ccc..7c5a3e0a92c2 100644 --- a/tests/test_organizations/organizations_test_utils.py +++ b/tests/test_organizations/organizations_test_utils.py @@ -36,7 +36,7 @@ def test_make_random_policy_id(): assert re.match(utils.POLICY_ID_REGEX, policy_id) -def validate_organization(response): +def validate_organization(response, partition="aws"): org = response["Organization"] assert sorted(org.keys()) == [ "Arn", @@ -50,10 +50,14 @@ def validate_organization(response): assert re.match(utils.ORG_ID_REGEX, org["Id"]) assert org["MasterAccountId"] == DEFAULT_ACCOUNT_ID assert org["MasterAccountArn"] == ( - utils.MASTER_ACCOUNT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"]) + utils.MASTER_ACCOUNT_ARN_FORMAT.format( + partition, org["MasterAccountId"], org["Id"] + ) ) assert org["Arn"] == ( - utils.ORGANIZATION_ARN_FORMAT.format(org["MasterAccountId"], org["Id"]) + utils.ORGANIZATION_ARN_FORMAT.format( + partition, org["MasterAccountId"], org["Id"] + ) ) assert org["MasterAccountEmail"] == utils.MASTER_ACCOUNT_EMAIL assert org["FeatureSet"] in ["ALL", "CONSOLIDATED_BILLING"] @@ -68,7 +72,9 @@ def validate_roots(org, response): root = response["Roots"][0] assert re.match(utils.ROOT_ID_REGEX, root["Id"]) assert root["Arn"] == ( - utils.ROOT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], root["Id"]) + utils.ROOT_ARN_FORMAT.format( + "aws", org["MasterAccountId"], org["Id"], root["Id"] + ) ) assert isinstance(root["Name"], str) assert root["PolicyTypes"] == [] @@ -79,7 +85,7 @@ def validate_organizational_unit(org, response): ou = response["OrganizationalUnit"] assert re.match(utils.OU_ID_REGEX, ou["Id"]) assert ou["Arn"] == ( - utils.OU_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], ou["Id"]) + utils.OU_ARN_FORMAT.format("aws", org["MasterAccountId"], org["Id"], ou["Id"]) ) assert isinstance(ou["Name"], str) @@ -97,7 +103,7 @@ def validate_account(org, account): assert re.match(utils.ACCOUNT_ID_REGEX, account["Id"]) assert account["Arn"] == ( utils.ACCOUNT_ARN_FORMAT.format( - org["MasterAccountId"], org["Id"], account["Id"] + "aws", org["MasterAccountId"], org["Id"], account["Id"] ) ) assert re.match(utils.EMAIL_REGEX, account["Email"]) @@ -128,7 +134,9 @@ def validate_policy_summary(org, summary): assert isinstance(summary, dict) assert re.match(utils.POLICY_ID_REGEX, summary["Id"]) assert summary["Arn"] == ( - utils.SCP_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], summary["Id"]) + utils.SCP_ARN_FORMAT.format( + "aws", org["MasterAccountId"], org["Id"], summary["Id"] + ) ) assert isinstance(summary["Name"], str) assert isinstance(summary["Description"], str) diff --git a/tests/test_organizations/test_organizations_boto3.py b/tests/test_organizations/test_organizations_boto3.py index 942b7c341f2b..9fa3d567d1d6 100644 --- a/tests/test_organizations/test_organizations_boto3.py +++ b/tests/test_organizations/test_organizations_boto3.py @@ -31,17 +31,26 @@ @mock_aws -def test_create_organization(): - client = boto3.client("organizations", region_name="us-east-1") +@pytest.mark.parametrize( + "region,partition", + [("us-east-1", "aws"), ("cn-north-1", "aws-cn"), ("us-isob-east-1", "aws-iso-b")], +) +def test_create_organization(region, partition): + client = boto3.client("organizations", region_name=region) response = client.create_organization(FeatureSet="ALL") - validate_organization(response) - assert response["Organization"]["FeatureSet"] == "ALL" + validate_organization(response, partition=partition) + organization = response["Organization"] + assert organization["FeatureSet"] == "ALL" response = client.list_accounts() assert len(response["Accounts"]) == 1 assert response["Accounts"][0]["Name"] == "master" assert response["Accounts"][0]["Id"] == ACCOUNT_ID assert response["Accounts"][0]["Email"] == utils.MASTER_ACCOUNT_EMAIL + assert ( + response["Accounts"][0]["Arn"] + == f"arn:{partition}:organizations::{ACCOUNT_ID}:account/{organization['Id']}/{ACCOUNT_ID}" + ) response = client.list_policies(Filter="SERVICE_CONTROL_POLICY") assert len(response["Policies"]) == 1 @@ -1248,17 +1257,29 @@ def test_tag_resource_organization_organizational_unit(): @mock_aws -def test_tag_resource_policy(): - client = boto3.client("organizations", region_name="us-east-1") +@pytest.mark.parametrize( + "policy_type", ["AISERVICES_OPT_OUT_POLICY", "SERVICE_CONTROL_POLICY"] +) +@pytest.mark.parametrize( + "region,partition", + [("us-east-1", "aws"), ("cn-north-1", "aws-cn"), ("us-isob-east-1", "aws-iso-b")], +) +def test_tag_resource_policy(policy_type, region, partition): + client = boto3.client("organizations", region_name=region) client.create_organization(FeatureSet="ALL") _ = client.list_roots()["Roots"][0]["Id"] - resource_id = client.create_policy( + policy = client.create_policy( Content=json.dumps(policy_doc01), Description="A dummy service control policy", Name="MockServiceControlPolicy", - Type="SERVICE_CONTROL_POLICY", - )["Policy"]["PolicySummary"]["Id"] + Type=policy_type, + )["Policy"]["PolicySummary"] + assert policy["Arn"].startswith( + f"arn:{partition}:organizations::{ACCOUNT_ID}:policy/" + ) + + resource_id = policy["Id"] client.tag_resource(ResourceId=resource_id, Tags=[{"Key": "key", "Value": "value"}]) @@ -1309,7 +1330,7 @@ def test_tag_resource_errors(): def test__get_resource_for_tagging_existing_root(): - org = FakeOrganization(ACCOUNT_ID, "ALL") + org = FakeOrganization(ACCOUNT_ID, region_name="us-east-1", feature_set="ALL") root = FakeRoot(org) org_backend = OrganizationsBackend(region_name="N/A", account_id="N/A") @@ -1329,7 +1350,7 @@ def test__get_resource_for_tagging_existing_non_root(): def test__get_resource_for_tagging_existing_ou(): - org = FakeOrganization(ACCOUNT_ID, "ALL") + org = FakeOrganization(ACCOUNT_ID, region_name="us-east-1", feature_set="ALL") ou = FakeOrganizationalUnit(org) org_backend = OrganizationsBackend(region_name="N/A", account_id="N/A") @@ -1349,7 +1370,7 @@ def test__get_resource_for_tagging_non_existing_ou(): def test__get_resource_for_tagging_existing_account(): - org = FakeOrganization(ACCOUNT_ID, "ALL") + org = FakeOrganization(ACCOUNT_ID, region_name="us-east-1", feature_set="ALL") org_backend = OrganizationsBackend(region_name="N/A", account_id="N/A") account = FakeAccount(org, AccountName="test", Email="test@test.test") @@ -1369,7 +1390,7 @@ def test__get_resource_for_tagging_non_existing_account(): def test__get_resource_for_tagging_existing_policy(): - org = FakeOrganization(ACCOUNT_ID, "ALL") + org = FakeOrganization(ACCOUNT_ID, region_name="us-east-1", feature_set="ALL") org_backend = OrganizationsBackend(region_name="N/A", account_id="N/A") policy = FakePolicy(org, Type="SERVICE_CONTROL_POLICY") @@ -1969,26 +1990,33 @@ def test_deregister_delegated_administrator_erros(): @mock_aws -def test_enable_policy_type(): +@pytest.mark.parametrize( + "policy_type", ["AISERVICES_OPT_OUT_POLICY", "SERVICE_CONTROL_POLICY"] +) +@pytest.mark.parametrize( + "region,partition", + [("us-east-1", "aws"), ("cn-north-1", "aws-cn"), ("us-isob-east-1", "aws-iso-b")], +) +def test_enable_policy_type(policy_type, region, partition): # given - client = boto3.client("organizations", region_name="us-east-1") + client = boto3.client("organizations", region_name=region) org = client.create_organization(FeatureSet="ALL")["Organization"] root_id = client.list_roots()["Roots"][0]["Id"] # when - response = client.enable_policy_type( - RootId=root_id, PolicyType="AISERVICES_OPT_OUT_POLICY" - ) + response = client.enable_policy_type(RootId=root_id, PolicyType=policy_type) # then root = response["Root"] assert root["Id"] == root_id assert root["Arn"] == ( - utils.ROOT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], root_id) + utils.ROOT_ARN_FORMAT.format( + partition, org["MasterAccountId"], org["Id"], root_id + ) ) assert root["Name"] == "Root" assert sorted(root["PolicyTypes"], key=lambda x: x["Type"]) == ( - [{"Type": "AISERVICES_OPT_OUT_POLICY", "Status": "ENABLED"}] + [{"Type": policy_type, "Status": "ENABLED"}] ) @@ -2062,7 +2090,7 @@ def test_disable_policy_type(): root = response["Root"] assert root["Id"] == root_id assert root["Arn"] == ( - utils.ROOT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], root_id) + utils.ROOT_ARN_FORMAT.format("aws", org["MasterAccountId"], org["Id"], root_id) ) assert root["Name"] == "Root" assert root["PolicyTypes"] == [] @@ -2154,7 +2182,7 @@ def test_aiservices_opt_out_policy(): assert re.match(utils.POLICY_ID_REGEX, summary["Id"]) assert summary["Arn"] == ( utils.AI_POLICY_ARN_FORMAT.format( - org["MasterAccountId"], org["Id"], summary["Id"] + "aws", org["MasterAccountId"], org["Id"], summary["Id"] ) ) assert summary["Name"] == "ai-opt-out" diff --git a/tests/test_stepfunctions/test_stepfunctions.py b/tests/test_stepfunctions/test_stepfunctions.py index f7e758331618..3cf112aa5127 100644 --- a/tests/test_stepfunctions/test_stepfunctions.py +++ b/tests/test_stepfunctions/test_stepfunctions.py @@ -851,6 +851,25 @@ def test_stepfunction_regions(test_region): resp = client.list_state_machines() assert resp["ResponseMetadata"]["HTTPStatusCode"] == 200 + response = client.create_state_machine( + name="name", definition=str(simple_definition), roleArn=_get_default_role() + ) + if test_region == "us-west-2": + assert ( + response["stateMachineArn"] + == f"arn:aws:states:{test_region}:{ACCOUNT_ID}:stateMachine:name" + ) + if test_region == "cn-northwest-1": + assert ( + response["stateMachineArn"] + == f"arn:aws-cn:states:{test_region}:{ACCOUNT_ID}:stateMachine:name" + ) + if test_region == "us-isob-east-1": + assert ( + response["stateMachineArn"] + == f"arn:aws-iso-b:states:{test_region}:{ACCOUNT_ID}:stateMachine:name" + ) + @mock_aws @mock.patch.dict(os.environ, {"SF_EXECUTION_HISTORY_TYPE": "FAILURE"}) diff --git a/tests/test_sts/test_sts.py b/tests/test_sts/test_sts.py index 4e5f3f570644..07e4828f10e9 100644 --- a/tests/test_sts/test_sts.py +++ b/tests/test_sts/test_sts.py @@ -67,7 +67,8 @@ def test_get_federation_token_boto3(): @freeze_time("2012-01-01 12:00:00") @mock_aws @pytest.mark.parametrize( - "region,partition", [("us-east-1", "aws"), ("cn-north-1", "aws-cn")] + "region,partition", + [("us-east-1", "aws"), ("cn-north-1", "aws-cn"), ("us-isob-east-1", "aws-iso-b")], ) def test_assume_role(region, partition): client = boto3.client("sts", region_name=region) @@ -738,3 +739,10 @@ def test_sts_regions(region): client = boto3.client("sts", region_name=region) resp = client.get_caller_identity() assert resp["ResponseMetadata"]["HTTPStatusCode"] == 200 + + if region == "us-west-2": + assert resp["Arn"] == f"arn:aws:sts::{ACCOUNT_ID}:user/moto" + if region == "cn-northwest-1": + assert resp["Arn"] == f"arn:aws-cn:sts::{ACCOUNT_ID}:user/moto" + if region == "us-isob-east-1": + assert resp["Arn"] == f"arn:aws-iso-b:sts::{ACCOUNT_ID}:user/moto"