AWS data perimeter architecture SOC 2 is the CC6 story we actually want an examiner to sample: not a screenshot of a bucket policy, but org-level guardrails that bound identity, resource, and network so a stolen key or a confused-deputy call cannot walk customer data out of the Organization. SOC 2 does not name “SCP + RCP + VPC endpoint policies.” Trust Services Criteria CC6 still asks whether access is restricted to authorized users and whether the system prevents unauthorized use. A data perimeter is how we implement that on AWS without claiming any certification we do not hold.
We deliver this as production policy, not a whitepaper. Mid-market SaaS estates usually have SCPs that deny a few services, bucket policies that grew organically, and no resource control policies. The blast radius is still “any principal that can assume a role in this account.”
AWS Data Perimeter Architecture SOC 2: Three Controls
AWS documents the perimeter as three objectives. We map each to a policy type the examiner can pull from AWS Organizations and VPC configuration — see Establish permissions guardrails using data perimeters.
| Objective | Applied on | Policy | Typical condition keys |
|---|---|---|---|
| Only trusted identities access our resources | Resources | RCP | aws:PrincipalOrgID, aws:PrincipalIsAWSService |
| Only trusted identities use our network | Network | VPC endpoint policy | aws:PrincipalOrgID |
| Our identities access only trusted resources | Identities | SCP | aws:ResourceOrgID |
| Our identities operate only from expected networks | Identities | SCP | aws:SourceVpc, aws:SourceIp, aws:VpceOrgID |
| Our resources accept traffic only from expected networks | Resources | RCP | aws:SourceVpc, aws:VpceOrgID |
| Our network reaches only trusted resources | Network | VPC endpoint policy | aws:ResourceOrgID |
SCPs bound what principals in the account may do. RCPs bound what the resource will accept, including principals that are not in the account (a contractor AWS account, a compromised SaaS integration, a copied access key used from the public internet). VPC endpoint policies bound what that ENI path is allowed to talk to. One layer is not a perimeter. Three layers is the architecture we ship.
We do not tell a client this is an examination opinion. We tell them it is the preventive control set that backs CC6 logical-access narratives, next to the detective stack in GuardDuty and Security Hub evidence.
SCP: Identities Stay Inside Trusted Resources and Networks
The resource-perimeter SCP we attach at the org or OU is a deny that fires unless the target resource is in the Organization (or an explicit exception). The shape AWS publishes is the one we start from:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyResourceOutsideOrg",
"Effect": "Deny",
"Action": [
"s3:*",
"kms:*",
"secretsmanager:*",
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath"
],
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {
"aws:ResourceOrgID": "${aws:PrincipalOrgID}"
},
"BoolIfExists": {
"aws:ViaAWSService": "false"
}
}
}
]
}
aws:ViaAWSService is not decoration. CloudTrail, Config, and Backup write into your buckets using service principals and forward-access sessions. A naive ResourceOrgID deny without that exception breaks logging on day one — which is worse for an examination than having no SCP.
Network-perimeter SCPs use aws:SourceVpc / aws:VpceOrgID so IAM users and long-lived keys cannot call S3 from a coffee shop even if the IAM policy allows it. That is the CC6 “access from unauthorized locations” conversation without inventing a zero-trust product.
Exceptions are tagged and ticketed. We do not punch NotAction holes for “the data team needs Snowflake” without a named external resource ARN in the VPC endpoint policy. SCP deny + endpoint allow is how AWS recommends handling third-party resources you actually intend.
RCP: Resources Refuse Untrusted Principals
Resource control policies are the layer most mid-market orgs still skip. An S3 bucket policy that allows Principal: * with a confused StringEquals is still a resource that will honor a principal outside the Organization if someone attaches a wide identity-based policy later. An RCP sets the ceiling on the resource, the same way an SCP sets the ceiling on the identity.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RCPTrustedIdentities",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:*",
"sqs:*",
"kms:*",
"secretsmanager:*"
],
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {
"aws:PrincipalOrgID": "o-xxxxxxxxxx"
},
"BoolIfExists": {
"aws:PrincipalIsAWSService": "false"
}
}
}
]
}
Service-linked roles and AWS service principals need aws:PrincipalIsAWSService (and, where required, aws:SourceOrgID) or you will break ELB logs, Config snapshots, and CloudFront origin access. We keep a regression account: attach the RCP to a sandbox OU first, run the application test pack, then promote. RCPs do not apply to every AWS service. We only claim coverage for the services that support RCPs and we list the exceptions in the control narrative.
VPC Endpoint Policies: The Network Does Not Become a Confused Deputy
Interface and gateway endpoints without a policy default to “any principal, any resource in the service.” That is how a workload in a locked-down VPC still copies an object to a bucket in an attacker account — the call never left AWS, so a 0.0.0.0/0 SG story never fired.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EndpointTrustedOrgOnly",
"Effect": "Allow",
"Principal": "*",
"Action": "*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-xxxxxxxxxx"
}
}
},
{
"Sid": "EndpointTrustedResources",
"Effect": "Allow",
"Principal": "*",
"Action": "*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceOrgID": "o-xxxxxxxxxx"
}
}
}
]
}
We pair this with the NAT reduction work in VPC endpoints vs NAT Gateway — the same endpoints that cut data-processing charges become the enforcement point. Private DNS on, default route still via NAT for true internet, S3/DynamoDB via gateway endpoints. The CC6 narrative is: customer data plane API calls to S3, KMS, and Secrets Manager cannot target resources outside the Organization from this VPC.
What Examiners Actually Sample
We do not hand over a 40-page policy dump. We hand over:
- Organizations policy attachments (SCP + RCP) with version history.
- A one-page mapping: CC6.1 / CC6.6 / CC6.7 → perimeter objective → policy ARN → exception list.
- A failed-access test: attempt
aws s3 cpto a bucket outside the org from an app role; CloudTrailAccessDeniedis the artifact. - Endpoint policy snapshots for the data-plane services in scope.
That sits on the same foundation as SOC 2-ready AWS architecture and Control Tower guardrails. Permission boundaries (delegated administration) stay underneath so app teams can mint roles without minting an org-admin hole in the perimeter.
Rutagon is not a SOC 2 issuer and we do not sell a GRC logo. We build the AWS control plane your existing examiner can sample. That is the security automation layer — preventive policy, not a spreadsheet of screenshots.
Discuss a data-perimeter diagnostic: 907-841-8407 or contact@rutagon.com.
Talk to us about AWS data perimeter architecture →
Frequently Asked Questions
Does a data perimeter replace bucket policies and IAM roles?
No. Identity-based policies still grant the least privilege the workload needs. Bucket policies still encode object-level exceptions. SCP, RCP, and endpoint policies are ceilings. If the ceiling and the grant disagree, deny wins. That is the point of a blast-radius control.
Will an RCP break AWS service writes into our buckets?
It will if you deny all non-org principals and forget aws:PrincipalIsAWSService / aws:SourceOrgID. CloudTrail, Config, Backup, and ELB need those exceptions. We regression-test service-linked write paths in a sandbox OU before attaching the RCP to production OUs.
Does a data perimeter replace a SOC 2 examination?
No. A data perimeter is an architecture that supports CC6 logical-access criteria. An examination is performed by a licensed firm against your full control set. We implement and evidence the AWS guardrails; we do not issue a report.
Why not only SCPs?
SCPs do not constrain a principal that is not in your Organization. A resource policy that allows the world, or an identity in another account you once trusted, bypasses the SCP. RCPs close that side. Endpoint policies close the network side. All three are required for the perimeter AWS describes.
How do we allow one approved SaaS export bucket?
Exempt the specific actions in the SCP with NotAction or a conditioned exception, and explicitly allow only that resource ARN on the S3 gateway endpoint policy. A global Resource: * exception is how the perimeter dies. Named ARNs are how it stays reviewable next examination window.