SecurityArchitecture

Zero-Trust Networking on AWS with IAM Identity Center and SCPs

NT

Naveen Teja

3/2/2026

Zero-Trust Networking on AWS with IAM Identity Center and SCPs

Traditional perimeter-based security assumes everything inside the network is trusted. In a modern cloud environment where developers work remotely, third-party contractors access systems, and microservices communicate across accounts, this model is fundamentally broken. Zero-trust security operates on the principle of 'never trust, always verify' — every request must be authenticated and authorized regardless of its origin.

On AWS, zero-trust is implemented through a layered combination of controls. IAM Identity Center (formerly SSO) provides centralized, federated identity management — developers authenticate via your corporate IdP (Okta, Azure AD) and receive time-limited role credentials. Service Control Policies (SCPs) at the AWS Organizations level act as a guardrail that cannot be overridden even by account administrators, preventing actions like disabling CloudTrail or creating IAM users with console access.

The most powerful SCP patterns include: denying all actions outside approved regions (data sovereignty), requiring MFA for sensitive operations like deleting S3 buckets, and blocking root account usage entirely. Combined with VPC Security Groups enforcing least-privilege network access, this creates a true zero-trust posture. The SCP below implements a deny-list that prevents resource creation outside pre-approved AWS regions, which is a critical compliance requirement for GDPR and data residency.

zero-trust-scp.tf
# SCP: Deny actions outside approved regions
resource "aws_organizations_policy" "region_restriction" {
  name        = "RestrictToApprovedRegions"
  description = "Deny all resource creation outside us-east-1 and ap-south-1"
  type        = "SERVICE_CONTROL_POLICY"

  content = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "DenyOutsideApprovedRegions"
        Effect = "Deny"
        NotAction = [
          "iam:*",
          "organizations:*",
          "support:*",
          "sts:*"
        ]
        Resource = "*"
        Condition = {
          StringNotEquals = {
            "aws:RequestedRegion" = ["us-east-1", "ap-south-1"]
          }
        }
      },
      {
        Sid    = "DenyRootAccountActions"
        Effect = "Deny"
        Action = "*"
        Resource = "*"
        Condition = {
          StringLike = {
            "aws:PrincipalArn" = "arn:aws:iam::*:root"
          }
        }
      }
    ]
  })
}

resource "aws_organizations_policy_attachment" "region_restriction" {
  policy_id = aws_organizations_policy.region_restriction.id
  target_id = aws_organizations_organizational_unit.workloads.id
}