AWS Partitions
Floci serves every AWS partition, not only the commercial one. A partition is the second
segment of every ARN (arn:aws-cn:...), the DNS suffix of every endpoint
(amazonaws.com.cn), and the set of services and regions AWS publishes there. Floci reads
all of it from AWS's own partition metadata (botocore's partitions.json and
endpoints.json, vendored as aws/partitions.json and refreshed with make aws-data-sync,
which also regenerates the AWS managed-policy catalog).
| Partition | DNS suffix | Regions | Example |
|---|---|---|---|
aws |
amazonaws.com |
34 published (17 opt-in) | us-east-1 |
aws-cn |
amazonaws.com.cn |
cn-north-1, cn-northwest-1 |
cn-north-1 |
aws-us-gov |
amazonaws.com |
us-gov-east-1, us-gov-west-1 |
us-gov-west-1 |
aws-iso |
c2s.ic.gov |
us-iso-east-1, us-iso-west-1 |
us-iso-east-1 |
aws-iso-b |
sc2s.sgov.gov |
us-isob-east-1, us-isob-west-1 |
us-isob-east-1 |
aws-iso-e |
cloud.adc-e.uk |
eu-isoe-west-1 |
eu-isoe-west-1 |
aws-iso-f |
csp.hci.ic.gov |
us-isof-east-1, us-isof-south-1 |
us-isof-south-1 |
aws-eusc |
amazonaws.eu |
eusc-de-east-1 |
eusc-de-east-1 |
Which partition a deployment serves
The deployment's partition is derived from FLOCI_DEFAULT_REGION: cn-north-1 means
aws-cn, us-gov-west-1 means aws-us-gov, and so on. Set FLOCI_PARTITIONS_ID
(floci.partitions.id) to name it explicitly; startup refuses a value that is not a
published partition or that contradicts a recognised default region, and logs one line
naming the partition it settled on:
A default region the vendored data does not know only warns. AWS launches regions faster
than the data is refreshed, and botocore's region-shape rules (cn-*, us-gov-*, ...)
still place it; anything else falls back to aws, which is what the AWS SDKs do too.
Running a China, GovCloud, ISO or EUSC deployment
Start Floci with a default region in the partition, then point clients at it with a region in the same partition and an endpoint override:
docker run --rm -p 4566:4566 \
-e FLOCI_DEFAULT_REGION=cn-north-1 \
floci/floci:latest
AWS_DEFAULT_REGION=cn-north-1 bin/awslocal sts get-caller-identity
# "Arn": "arn:aws-cn:iam::000000000000:root"
With the AWS CLI directly, pass --region cn-north-1 --endpoint-url http://localhost:4566; with
an SDK, set the region and the endpoint override on the client. The override replaces the
partition's real host (amazonaws.com.cn here) for transport only: the SDK still signs for the
region you gave it, and that signing region is what places each request in its partition (see
below). If clients reach Floci on another host or port than http://localhost:4566, set
FLOCI_BASE_URL to match, or URLs Floci returns, such as SQS queue URLs and pre-signed URLs,
keep pointing at the default. FLOCI_HOSTNAME is enough when only the host differs: it replaces
the host and keeps the port.
Which partition a request belongs to
Each request's partition comes from the region in its SigV4 credential scope, exactly as
LocalStack and moto do it. A client signing cn-north-1 is a China client even when Floci
was started with us-east-1, so one process can serve several partitions at once. Requests
without a credential, and background work (pollers, schedulers, startup hooks), use the
deployment's partition.
JSON 1.1 service dispatch uses the region selected for the request, including a presigned
X-Amz-Credential query scope when the request filter accepts it. An applicable
Authorization header takes precedence over query credentials; requests without an admitted
credential scope use the configured default region. Authorization and execution therefore use
the same regional namespace.
The scope region of a global service is its signing region, not a place to put regional
resources: China IAM always signs cn-north-1 even from Ningxia, GovCloud IAM signs
us-gov-west-1. Floci uses it to pick the partition and nothing else. The
<partition>-global pseudo-regions the SDKs accept (aws-global, aws-cn-global, ...)
resolve to their partition as well; aws-eusc publishes none. AWS never signs with one (the SDKs
map each to a real signing region), so a scope that names one is served as the partition's
implicit global region: a request signed aws-cn-global is a cn-northwest-1 request, and no
ARN or storage namespace carries the pseudo-region.
A scope region that no partition publishes or admits by its region pattern, such as
polygondwanaland-west-1, is refused with a 400: an S3-signed request gets S3's
AuthorizationHeaderMalformed ("the region '...' is wrong"), every other service gets
InvalidSignatureException. On AWS such a request never resolves a host; moto
(MOTO_ALLOW_NONEXISTENT_REGION) and LocalStack (ALLOW_NONSTANDARD_REGIONS) refuse it too.
The pattern rule is the AWS SDKs' own, so a region AWS launches after the vendored data was
refreshed (eu-south-9, say) is still served; it is looser than S3's LocationConstraint enum,
which stays published-only. Set FLOCI_PARTITIONS_ALLOW_UNKNOWN_REGIONS=true
(floci.partitions.allow-unknown-regions) to serve custom labels with their own namespaces.
Such a label belongs to the deployment's partition. ARNs minted through Floci's shared region
resolver use that partition too; services that build their ARNs directly still fall back to
aws for a label no partition publishes.
A region label containing : is always refused because the colon separates ARN fields and
storage identities. This also applies to FLOCI_DEFAULT_REGION; Floci refuses to start with
a colon in that setting. Existing stored namespaces are not migrated or deleted by this check.
What changes per partition
- ARNs: regional resources carry the partition of their region (
arn:aws-cn:sqs:cn-north-1:...); regionless resources (IAM, S3, STS, CloudFront, Route 53, Organizations) carry the request's partition. - DescribeRegions: the request's partition's regions, with the partition's endpoints.
As on AWS, a commercial deployment lists the 17 regions that need no opt-in by default and
all 34 with
AllRegions=true, where opt-in regions reportnot-opted-in. - Hostnames: AWS-shaped hosts in responses (an HTTP API's
ApiEndpoint, a bucket'sRegionalDomainNameandWebsiteURL, Cognito and EKS OIDC issuers, EC2 public DNS names) use the DNS suffix of their region's partition, so acn-north-1API answers<id>.execute-api.cn-north-1.amazonaws.com.cn.DualStackDomainNameis only returned where S3 publishes a dual-stack endpoint. - Hostname recognition: every published region id and DNS suffix, in every partition, is recognised in an S3 virtual-host, execute-api, ECR image or CloudFront origin hostname.
- S3 CreateBucket: as on AWS, the
us-east-1endpoint takes anyLocationConstraintbut its own, and every other regional endpoint requires a constraint naming exactly its region (IllegalLocationConstraintExceptionotherwise). A China or GovCloud client must send the constraint, which the AWS SDKs do;GetBucketLocationstill answers an empty constraint only forus-east-1, in every partition. - AWS Sign-In: the cross-device login redirect is accepted on the Sign-In host of the
deployment's partition (
<region>.signin.amazonaws.cnin China,<region>.signin.amazonaws-us-gov.comin GovCloud), read from botocore'ssigninendpoint ruleset intoaws/partitions.json, and on Floci's own endpoint. The device-authorization client ids are the same literal in every partition, as the Sign-In model spells them. - Hosted zones and console URLs: load balancer and S3 website hosted zone ids come from a
per-region table (
aws/region-facts.json, generated from the Terraform provider and the CDK, which transcribe the AWS General Reference, and from the General Reference itself and the China and GovCloud user guides); Network load balancers have their own zone, distinct from the Application/Classic one. The CloudFront hosted zone is published forawsandaws-cn; the SAML sign-on URL for five partitions. The console link in a CodePipeline approval notification uses the console host of the pipeline's partition (console.amazonaws.cnin China,console.amazonaws-us-gov.comin GovCloud), as the China and GovCloud user guides state it; the path after the host is the commercial console's. A generated CloudFront distribution domain name ends incloudfront.cnin China, as the China guide names the default CloudFront domain, unlessfloci.services.cloudfront.domain-suffixis set. A regional API Gateway custom domain reports the regional hosted zone the AWS General Reference publishes for its region. The ISO and EUSC regions have no load balancer hosted zones, and only the two ISO-F regions have an S3 website zone; where a table has no row the field is omitted rather than guessed. The one exception is API Gateway, whose response always carries a zone: a region with no row reports a placeholder, listed under the open questions below. AnEDGEAPI Gateway REST API or custom domain is refused outside the commercial partition (BadRequestException): GovCloud, EUSC and ISO have no CloudFront, and China has no edge-optimized API Gateway (China API Gateway). A Lambda function URL is refused in GovCloud and China (InvalidParameterValueExceptiononCreateFunctionUrlConfig), where the GovCloud and China guides list function URLs as not available. A Cognito user pool custom domain (CustomDomainConfig) is refused in GovCloud and EUSC (InvalidParameterException), where the GovCloud and EUSC guides list custom domains as not available; prefix domains work there. - VPC endpoint service names: interface endpoints (as
DescribeVpcEndpointServiceslists them) arecom.amazonaws.<region>.<service>everywhere, except the (region, service) pairs the CDK lists for China, ISO and EUSC, which reverse the DNS suffix (cn.com.amazonaws.cn-north-1.lambda). GovCloud keepscom.amazonaws. Gateway endpoints and their AWS-managed prefix lists (S3, DynamoDB) arecom.amazonaws.<region>.<service>in every partition. S3 offers both kinds: where the two names agree it is one service carrying both types, and in China it is listed twice, the gatewaycom.amazonaws.cn-north-1.s3and the interfacecn.com.amazonaws.cn-north-1.s3. - Lambda runtime images pull from ECR Public (
public.ecr.aws), which exists only in the commercial partition; pointFLOCI_SERVICES_LAMBDA_ECR_BASE_URIat a mirror elsewhere. - WAF
CLOUDFRONTscope: available only where CloudFront exists (aws,aws-cn), and its resources live in the partition's implicit global region (cn-northwest-1in China).
What does not change
- Service principals are
<service>.amazonaws.comin every partition; that is the rule the AWS CDK applies today, and everything Floci emits (generated trust policies, CloudTrail'seventSource, service-linked role paths) uses it. The older per-partition forms the CDK retired (elasticmapreduce.amazonaws.com.cn,logs.<region>.amazonaws.com.cn,config.c2s.ic.gov) are still accepted wherever Floci matches a principal against a policy, such as a role's trust policy, so a policy written in either form works; matching stays exact and case-sensitive.CreateServiceLinkedRolegiven a legacy form creates the same role as the universal one: its name, path and trust policy all use<service>.amazonaws.com. - XML namespaces and the S3 canned-ACL group URIs (
http://acs.amazonaws.com/groups/...) are identifiers, not hosts. - AWS managed policy ARNs keep the literal
awsaccount slot:arn:aws-cn:iam::aws:policy/AdministratorAccess. The catalog Floci bundles is the commercial one; every other partition's is derived from it on first use, with the partition in every ARN (what AWS's own SAM translator does) and the partition's DNS suffix in the region-bearingkms:ViaServicehosts (s3.*.amazonaws.com.cn). Service principals and service-linked role paths are the same in every partition and are left alone. Whether AWS's China or GovCloud documents differ in content beyond that is an open question below.
Partition-absent services
AWS publishes which services exist in each partition (CloudFront is not in GovCloud, Lightsail
is not in China). On AWS a request for an absent service never reaches an API: the SDK
fails to resolve the host and reports an UnknownHostException. Floci serves every enabled
service in every partition by default.
Set FLOCI_PARTITIONS_STRICT=true (floci.partitions.strict) to mirror AWS instead. A request
whose SigV4 signing name the request's partition does not publish is refused with a 404
UnknownOperationException whose message names the service and the partition; Floci cannot
fail DNS, so this is the same shape the unknown-service guard uses. The check reads the vendored
service list, matching the signing name directly or through the endpoint prefixes it covers
(ecr signs for api.ecr, bedrock for bedrock-runtime), so a China ECR client is served
while a GovCloud CloudFront client is refused. Only a service the data lists in some other
partition is refused: endpoints.json omits the newer services that ship an endpoint ruleset
alone (FIS, MWAA, S3 Tables), and those are served everywhere.
A partition also offers a service when that service's endpoint ruleset names the partition in a
branch with its own endpoint, even where endpoints.json leaves it out: IAM, Route 53, Budgets and
Cost Explorer in aws-eusc (iam.eusc-de-east-1.amazonaws.eu), IAM and Cost Explorer in
aws-iso-e. The vendored data records these under servicesFromRulesets. The execute-api
signing name is never refused: API Gateway's invoke endpoints and its WebSocket management API
(apigatewaymanagementapi) sign with it as well as Connect Participant, and endpoints.json lists
the API Gateway side nowhere, so the data cannot say where the name is served.
STS is regionalized everywhere and its global host sts.amazonaws.com exists only in aws, so
IAM's GetAccountSummary reports GlobalEndpointTokenVersion only there.
An IAM resource (user, group, role, policy, instance profile, OIDC provider) is created in the
request's partition and keeps it: a rename signed for another partition does not move it. On AWS
an account belongs to one partition, but one Floci process serves them all, so anything derived
from a stored resource follows that resource. A role's sessions (assumed-role) and the OIDC
provider its web-identity trust policy names take the stored role's partition, whichever partition
the request's RoleArn names, so AssumeRole and a later GetCallerIdentity agree whatever region
each call is signed for. The credential report is kept per partition, so its root row always
names the caller's. ARNs with nothing stored
behind them, the root fallback of GetCallerIdentity and federated-user, take the request's
partition.
How it is tested
- The partition rules themselves (partition and region lookup, ARN minting, hostnames, service principals, managed-policy rewriting, STS) have unit tests over all eight partitions.
- Through the emulator, IAM ARNs run in all eight partitions, and a smoke test creates one
resource per service in every non-commercial partition that publishes the service and checks
its ARN or host. It covers every service that mints ARNs or hosts; the few without a case are
listed with the reason in
src/test/resources/partition/smoke-exemptions.tsv, and a new service needs a case there or a recorded exemption. Most other partition-dependent behaviour (EC2 regions and DNS names, hosted zones, VPC endpoint names, Lambda layers, Step Functions integration ids, strict mode) is tested in one or two partitions, nearly always China. - End to end, the nightly Partition Compatibility workflow runs the Java SDK compatibility
suite against a Floci deployed with
FLOCI_DEFAULT_REGION=cn-north-1, with the SDK clients signing forcn-north-1, so the SDK's own China partition handling has to round-trip. Its list of known failures,.github/ci/compat-partition-allowlist-cn-north-1.txt, is empty, so any failure fails the run. No other partition, and no other compatibility suite (the Python, Go, Node and AWS CLI suites, CDK, Terraform, OpenTofu), runs outside the commercial partition.
Known gaps
- One process serving several partitions shares global state. S3 bucket names are one
namespace, and
ListBucketslists buckets created from every partition; IAM, Organizations, Route 53, CloudFront and the IAM Identity Center instance keep one set of resources per account, whichever partition a request is signed for. AWS keeps them per partition. A deployment that serves one partition is unaffected. For the same reason, STSAssumeRole, EKS Pod Identity and EKS add-ons accept a role ARN from any partition and resolve it to the account's role of that path and name; the session is named with the role's own ARN. - AWS managed policies are the commercial catalog in every partition, with their ARNs and regional hosts rewritten; AWS publishes no per-partition list.
- Client tooling that computes partition values itself (CDK bootstrap and
AWS::Partition, Terraform'saws_partition, SAM) is not tested outside the commercial partition, and neither is any partition but China end to end.
Open questions
These values have no published source Floci can cite, so it does not guess them; they keep the commercial value or Floci's own base host until sourced:
- the STS web-identity audience outside the commercial partition;
- the EKS Pod Identity token audience (
pods.eks.amazonaws.com) outside the commercial partition; - the Lambda function-URL host in the ISO and EUSC partitions (function URLs are refused in GovCloud and China, where the partition guides list them as not available);
- whether AWS managed policy documents differ in content in China or GovCloud;
- the API Gateway regional hosted zone in the regions the General Reference does not list (China,
ISO, EUSC and
ap-southeast-6): a custom domain there reportsZ2FDTNDATAQYL2, a placeholder that is no AWS zone, so a Route 53 alias built from it resolves to nothing on AWS; - the availability-zone id prefix of the ISO and EUSC regions: zone ids there keep the whole region
(
us-iso-east-1-az1), where the other partitions get AWS's short prefix (use1-az1,usgw1-az1,cnn1-az1); - S3
LocationConstraintenum values and Route 53 hosted zones for the ISO and EUSC regions; - the management console host in the ISO and EUSC partitions, where a CodePipeline approval
notification keeps linking to the commercial
console.aws.amazon.com; - the SAML sign-on URL in
aws-iso-e,aws-iso-fandaws-eusc, where assertions keep being checked against the commercialhttps://signin.aws.amazon.com/saml; - the exact error AWS WAF returns for the
CLOUDFRONTscope in a partition without CloudFront (GovCloud, the ISO partitions): Floci refuses it withWAFInvalidParameterExceptionand its own message.
Related
- Environment Variables:
FLOCI_DEFAULT_REGION,FLOCI_PARTITIONS_ID,FLOCI_PARTITIONS_STRICT,FLOCI_PARTITIONS_ALLOW_UNKNOWN_REGIONS - Multi-Account Isolation: the account half of the credential scope