← Back to Blog

Implementing Zero Trust Architecture on AWS

5 min read

Traditional network security assumes that traffic inside the perimeter is trusted. Zero trust eliminates that assumption — every request is verified regardless of where it originates. AWS provides the building blocks to implement zero trust, but assembling them correctly requires understanding how identity, network, and data controls interact.

Identity-Centric Access

Zero trust starts with identity. On AWS, this means eliminating implicit trust based on network location and requiring verified identity for every API call.

Eliminating Long-Lived Credentials

import boto3
import json

def enforce_credential_hygiene():
    """Audit and enforce short-lived credential usage"""

    iam = boto3.client('iam')
    findings = []

    # Find all users with long-lived access keys
    paginator = iam.get_paginator('list_users')
    for page in paginator.paginate():
        for user in page['Users']:
            keys = iam.list_access_keys(UserName=user['UserName'])
            for key in keys['AccessKeyMetadata']:
                age_days = (datetime.now(key['CreateDate'].tzinfo) - key['CreateDate']).days
                if age_days > 90:
                    findings.append({
                        'user': user['UserName'],
                        'key_id': key['AccessKeyId'],
                        'age_days': age_days,
                        'recommendation': 'Migrate to IAM role with temporary credentials'
                    })

    # Check for users without MFA
    for page in paginator.paginate():
        for user in page['Users']:
            mfa_devices = iam.list_mfa_devices(UserName=user['UserName'])
            if not mfa_devices['MFADevices']:
                findings.append({
                    'user': user['UserName'],
                    'issue': 'No MFA device configured',
                    'recommendation': 'Enforce MFA via IAM policy condition'
                })

    return findings

Zero trust credential principles:

  • Use IAM roles everywhere — EC2 instance profiles, ECS task roles, Lambda execution roles. No access keys.
  • Enforce MFA — require aws:MultiFactorAuthPresent condition on all human-interactive sessions
  • Shorten session duration — reduce MaxSessionDuration on roles from the default 1 hour to 15-30 minutes for sensitive operations
  • Rotate remaining keys — for the rare cases where keys are unavoidable, enforce 90-day rotation

Microsegmentation with Security Groups

Security groups act as per-instance firewalls. In a zero trust model, every workload gets its own security group with the minimum required connectivity.

Application-Tier Segmentation

Resources:
  # Web tier can only receive traffic from the ALB
  WebTierSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Web tier - ALB ingress only
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 8080
          ToPort: 8080
          SourceSecurityGroupId: !Ref ALBSecurityGroup

  # App tier can only receive traffic from the web tier
  AppTierSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: App tier - web tier ingress only
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 8443
          ToPort: 8443
          SourceSecurityGroupId: !Ref WebTierSecurityGroup

  # Database tier can only receive traffic from the app tier
  DatabaseSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Database tier - app tier ingress only
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 5432
          ToPort: 5432
          SourceSecurityGroupId: !Ref AppTierSecurityGroup
      # Explicitly deny all other ingress (default behavior)
      # No egress rules needed for RDS

The key insight: security groups reference other security groups, not CIDR blocks. This means access follows identity (which group a resource belongs to), not network location.

Continuous Verification with IAM Conditions

Zero trust requires that every request is evaluated in context. IAM conditions let you enforce checks on every API call.

Context-Aware IAM Policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowWithContinuousVerification",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "dynamodb:GetItem",
        "dynamodb:PutItem"
      ],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        },
        "NumericLessThan": {
          "aws:MultiFactorAuthAge": "3600"
        },
        "IpAddress": {
          "aws:SourceIp": ["10.0.0.0/8", "172.16.0.0/12"]
        },
        "StringEquals": {
          "aws:RequestedRegion": ["us-east-1", "us-east-2"]
        },
        "DateGreaterThan": {
          "aws:CurrentTime": "2025-01-01T08:00:00Z"
        },
        "DateLessThan": {
          "aws:CurrentTime": "2025-12-31T20:00:00Z"
        }
      }
    }
  ]
}

This single policy enforces:

  • MFA is active and was authenticated within the last hour
  • Request originates from a private network (not the public internet)
  • Request targets an approved region (prevents data exfiltration to foreign regions)
  • Request occurs during business hours (limits off-hours abuse of compromised credentials)

Session Policies for Blast Radius Reduction

When a role is assumed, you can pass a session policy that further restricts what the temporary credentials can do — even if the role itself has broader permissions.

import boto3

sts = boto3.client('sts')

def assume_scoped_role(role_arn, task_bucket, task_prefix):
    """Assume a role with session policy scoped to a specific S3 prefix"""

    session_policy = {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": ["s3:GetObject", "s3:PutObject"],
                "Resource": f"arn:aws:s3:::{task_bucket}/{task_prefix}/*"
            }
        ]
    }

    response = sts.assume_role(
        RoleArn=role_arn,
        RoleSessionName='scoped-data-processing',
        Policy=json.dumps(session_policy),
        DurationSeconds=900  # 15 minutes
    )

    return boto3.Session(
        aws_access_key_id=response['Credentials']['AccessKeyId'],
        aws_secret_access_key=response['Credentials']['SecretAccessKey'],
        aws_session_token=response['Credentials']['SessionToken']
    )

The effective permissions are the intersection of the role's policies and the session policy. Even if the role has s3:* on *, the session can only access one specific prefix for 15 minutes.

AWS Verified Access

AWS Verified Access replaces VPNs for internal application access. It evaluates identity and device trust on every connection, not just at session establishment.

Key capabilities:

  • Identity trust providers — integrates with AWS Identity Center, Okta, CrowdStrike, and other IdPs
  • Device posture checks — verify endpoint security status before granting access
  • Per-application policies — each internal application gets its own access policy
  • No VPN required — users connect directly to applications through Verified Access endpoints

Implementing Zero Trust with AccessLens

Zero trust on AWS depends entirely on correct IAM configuration. A single overpermissive role, a missing MFA condition, or a wildcard resource grant can undermine your entire zero trust architecture.

AccessLens helps enforce zero trust by providing:

  • Continuous IAM verification that identifies policies missing MFA, source IP, or region conditions
  • Blast radius analysis that maps the effective permissions of every role and session
  • Trust relationship visualization that reveals implicit trust paths across accounts
  • Privilege escalation detection that finds roles capable of bypassing your zero trust controls

Zero trust is not a product — it is a continuous process of verification. AccessLens provides the IAM visibility foundation that makes zero trust enforceable across your AWS organization.

Build zero trust on a solid foundation with AccessLens and verify that your IAM controls actually enforce the trust model you designed.

Ready to secure your AWS environment?

Get comprehensive IAM visibility across all your AWS accounts in minutes.