Skip to content

Latest commit

 

History

History
376 lines (285 loc) · 19.9 KB

File metadata and controls

376 lines (285 loc) · 19.9 KB

How IAM Access Analyzer Works

This document covers the internal mechanics of IAM Access Analyzer: how policies are evaluated, what resources are analyzed, what types of findings are produced, and how the finding lifecycle is managed.


Table of Contents

  1. Architecture Overview
  2. The Zelkova Automated Reasoning Engine
  3. Zone of Trust
  4. Supported Resource Types
  5. Finding Types
  6. How Findings Are Generated and Updated
  7. Finding Lifecycle and States
  8. Archive Rules
  9. Limitations and Edge Cases

Architecture Overview

IAM Access Analyzer is a regional, event-driven service. Each analyzer is scoped to a specific AWS region and a specific zone of trust (either a single account or an entire AWS Organization). You can have multiple analyzers per region — for example, one for external access analysis and one for unused access analysis.

When you create an analyzer, it performs an initial scan of all supported resource types within the zone of trust. After the initial scan, the analyzer subscribes to AWS CloudTrail events and resource configuration changes. When a policy or configuration changes, Access Analyzer re-evaluates the affected resource within minutes.

┌─────────────────────────────────────────────────────────────────┐
│                        AWS Account / Org                        │
│                                                                 │
│   Resource Policies          IAM Entity Policies                │
│   (S3, KMS, Lambda…)         (Roles, Users)                     │
│          │                          │                           │
│          └──────────┬───────────────┘                           │
│                     ▼                                           │
│         ┌─────────────────────┐                                 │
│         │  IAM Access Analyzer│◄── CloudTrail Events            │
│         │  (Zelkova Engine)   │◄── Config Change Events         │
│         └─────────┬───────────┘                                 │
│                   │                                             │
│          ┌────────┴────────┐                                    │
│          ▼                 ▼                                    │
│      Findings          Unused Access                            │
│      (External)        Findings                                 │
│          │                 │                                    │
│          └────────┬────────┘                                    │
│                   ▼                                             │
│            EventBridge → Security Hub / Slack / Jira            │
└─────────────────────────────────────────────────────────────────┘

The Zelkova Automated Reasoning Engine

What Is Automated Reasoning?

Most cloud security tools use heuristic analysis: they pattern-match known bad configurations (e.g., "this S3 bucket has Principal: *") and flag them. Heuristics are fast but produce both false positives (flagging safe configurations) and false negatives (missing complex unsafe configurations).

IAM Access Analyzer uses automated reasoning — specifically, a technique from formal verification called satisfiability modulo theories (SMT). The Zelkova engine (named after a genus of trees, following AWS's tradition of internal codenames) translates IAM policy documents into mathematical logical formulas and then determines, with mathematical certainty, whether a given principal outside the zone of trust can satisfy the conditions required to access the resource.

What Zelkova Evaluates

Zelkova considers the full policy evaluation logic defined by AWS:

  1. Identity-based policies (inline and managed) attached to the calling principal
  2. Resource-based policies on the resource being accessed
  3. Service control policies (SCPs) in the organizational hierarchy (for org-level analyzers)
  4. Permission boundaries on the calling principal
  5. Session policies (for assumed-role sessions)
  6. IAM condition keys — including aws:SourceAccount, aws:SourceArn, aws:PrincipalOrgID, aws:RequestedRegion, aws:ViaAWSService, etc.

This means Access Analyzer correctly understands nuanced configurations like:

{
  "Effect": "Allow",
  "Principal": "*",
  "Action": "s3:GetObject",
  "Condition": {
    "StringEquals": {
      "aws:PrincipalOrgID": "o-exampleorgid"
    }
  }
}

The above is a resource policy that grants access to * but with a condition restricting it to principals in your AWS Organization. Zelkova evaluates this and correctly does not generate an external access finding, because no principal outside the org can satisfy the condition.

Provable Security

The key guarantee is: when Access Analyzer reports no finding, it is a mathematical proof that no external principal can access the resource under the current policies. This is stronger than any heuristic tool can claim.

When Access Analyzer does report a finding, it includes the specific principals and conditions under which access is possible, enabling precise triage.

Limitations of Automated Reasoning Here

Zelkova operates on the static policy text. It cannot:

  • Predict run-time behavior of applications using the credentials.
  • Evaluate IP-based conditions against dynamic IP ranges (it models aws:SourceIp conditions but marks findings as conditional rather than definitively external).
  • Evaluate VPC endpoint conditions without knowledge of the endpoint's policy.

Zone of Trust

The zone of trust is the set of principals considered "internal." Any access from outside this boundary triggers a finding.

Analyzer Type Zone of Trust
ACCOUNT The single AWS account where the analyzer is created
ORGANIZATION All accounts within the AWS Organization
ACCOUNT_UNUSED_ACCESS The single AWS account (for unused access findings)
ORGANIZATION_UNUSED_ACCESS All accounts in the AWS Organization

Practical Implications

  • An ACCOUNT analyzer will flag cross-account access from your own sibling AWS accounts. This generates significant noise in environments with legitimate cross-account access patterns. For most enterprises, an ORGANIZATION analyzer is correct.
  • With an ORGANIZATION analyzer, access granted to arn:aws:iam::111122223333:role/DataPipelineRole (another account in your org) is considered internal and does not generate a finding.
  • Access granted to arn:aws:iam::999999999999:root (an account outside your org) always generates a finding.
  • Access granted to Principal: "*" always generates a finding even with an org-level analyzer, because * includes principals outside the org. The correct pattern for org-wide access is the aws:PrincipalOrgID condition key.

Supported Resource Types

Access Analyzer supports two categories of analysis. Not all resource types support both.

External Access Analysis — Supported Resource Types

Resource Type IAM Resource Type String What Is Analyzed
S3 Buckets AWS::S3::Bucket Bucket policy, bucket ACL, access points, multi-region access points
S3 Access Points AWS::S3::AccessPoint Access point policy
S3 Multi-Region Access Points AWS::S3::MultiRegionAccessPoint MRAP policy
IAM Roles AWS::IAM::Role Role trust policy (who can assume the role)
KMS Keys AWS::KMS::Key Key policy
Lambda Functions AWS::Lambda::Function Function resource-based policy
Lambda Layers AWS::Lambda::LayerVersion Layer permission policy
SQS Queues AWS::SQS::Queue Queue policy
SNS Topics AWS::SNS::Topic Topic policy
Secrets Manager Secrets AWS::SecretsManager::Secret Secret resource policy
EFS File Systems AWS::EFS::FileSystem File system policy
DynamoDB Streams AWS::DynamoDB::Stream Resource policy on a DynamoDB stream
DynamoDB Tables AWS::DynamoDB::Table Resource policy on a DynamoDB table
ECR Repositories AWS::ECR::Repository Repository policy
IAM Identity Center Instances AWS::SSO::Instance Permission set policies

Unused Access Analysis — Supported Resource Types

Unused access analysis operates on IAM entities rather than resource-level policies:

Entity Type What Is Analyzed
IAM Roles Whether the role has been assumed within the lookback window
IAM Users Whether the user has accessed the console or used access keys
IAM Access Keys Whether each access key (up to 2 per user) has been used
IAM Role Permissions Which services and actions within attached policies have been used (via CloudTrail data)

Finding Types

External Access Findings

Generated when a resource policy allows access from a principal outside the zone of trust. Each finding includes:

  • Resource ARN — the specific resource with external access.
  • Resource type — e.g., AWS::S3::Bucket.
  • Principal — the external principal granted access (an AWS account ID, IAM ARN, AWS service, federated identity, or *).
  • Action — the specific IAM actions the external principal can perform.
  • Condition — any IAM conditions that apply (e.g., aws:SourceIp). If conditions exist, the finding is marked as conditional access rather than unrestricted access.
  • Is public — boolean indicating whether the resource is publicly accessible (i.e., accessible by any unauthenticated internet user).

Example finding (JSON):

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "analyzedAt": "2025-10-15T14:32:00Z",
  "createdAt": "2025-10-15T14:32:00Z",
  "updatedAt": "2025-10-15T14:32:00Z",
  "status": "ACTIVE",
  "resourceType": "AWS::S3::Bucket",
  "resource": "arn:aws:s3:::my-data-bucket",
  "resourceOwnerAccount": "123456789012",
  "findingType": "ExternalAccess",
  "principal": {
    "AWS": "arn:aws:iam::999999999999:root"
  },
  "action": ["s3:GetObject", "s3:ListBucket"],
  "isPublic": false,
  "condition": {}
}

Unused Access Findings

Generated when IAM entities or their permissions have not been used within the configured lookback window (7 to 180 days, default 90 days).

Unused access finding subtypes:

Subtype Description
UNUSED_PERMISSION A specific IAM action or service in the entity's policy has never been used within the lookback window.
UNUSED_IAM_ROLE The IAM role has not been assumed at all within the lookback window.
UNUSED_IAM_USER_ACCESS_KEY An IAM user access key has not been used within the lookback window.
UNUSED_IAM_USER_PASSWORD An IAM user has not signed into the console within the lookback window.

Example unused access finding:

{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "findingType": "UnusedAccess",
  "resourceType": "AWS::IAM::Role",
  "resource": "arn:aws:iam::123456789012:role/OldBatchProcessingRole",
  "unusedAccess": {
    "unusedPermissionsInfo": {
      "lastAccessed": "2025-07-01T00:00:00Z",
      "serviceNamespace": "ec2"
    },
    "unusedIamRoleInfo": null
  }
}

Policy Validation Findings (Not Analyzer Findings)

The ValidatePolicy API is a separate capability that checks a policy document against AWS policy grammar and security best practices. It does not require an analyzer to be configured. Validation findings use severity levels:

Severity Meaning
ERROR Policy contains a syntax error and will be rejected by IAM.
SECURITY_WARNING Policy grants overly broad permissions (e.g., iam:*, Resource: *).
WARNING Policy uses deprecated features or patterns.
SUGGESTION Minor improvements available.

How Findings Are Generated and Updated

Initial Scan

When an analyzer is created, it scans all supported resources in the region. For an organization-level analyzer, this covers all accounts in the organization. The initial scan can take from minutes to hours depending on the size of the environment.

Event-Driven Updates

After the initial scan, Access Analyzer subscribes to:

  • CloudTrail management events — any Put*, Create*, Update*, Delete*, Attach*, Detach*, Set* API calls that could change resource policies or IAM entity configurations.
  • AWS Config configuration change events — for resource types monitored by AWS Config.

When a relevant event is detected, the affected resource is re-analyzed. Finding updates propagate to EventBridge within minutes.

Periodic Re-scans

In addition to event-driven updates, Access Analyzer performs periodic re-scans of all resources. This catches scenarios where a policy change does not emit a CloudTrail event (rare but possible with some older APIs) or where eventual consistency means the initial event-driven analysis saw stale state.

Finding Updates

If a resource policy changes in a way that removes the external access:

  • The finding status transitions to RESOLVED.
  • The finding is retained in the console and API for audit history.

If a resource policy changes in a way that modifies (but does not remove) the external access:

  • The existing finding is updated in place (same finding ID) with the new details.

Finding Lifecycle and States

                     ┌─────────┐
         Created ──► │ ACTIVE  │
                     └────┬────┘
                          │
              ┌───────────┴──────────┐
              │                      │
        Manual archive         Archive rule
        or policy fix          matches finding
              │                      │
              ▼                      ▼
        ┌──────────┐           ┌──────────┐
        │ RESOLVED │           │ ARCHIVED │
        └──────────┘           └────┬─────┘
                                    │
                              Policy re-opens
                              the access
                                    │
                                    ▼
                               ┌─────────┐
                               │ ACTIVE  │
                               └─────────┘
State Description
ACTIVE The finding is current and the external access or unused access exists. Requires attention.
ARCHIVED The finding has been suppressed — either manually or via an archive rule. The underlying access may still exist. Archived findings do not appear in the default filtered view.
RESOLVED The access has been removed. Access Analyzer confirmed the resource policy no longer grants the flagged access. Finding is retained for audit history.

Important: Archiving a finding does NOT remove the underlying access. It suppresses the alert. Only modifying the resource policy or removing the IAM entity resolves the underlying issue.


Archive Rules

Archive rules automatically archive findings that match specified filter criteria. They are used to suppress findings for known-good, intentional cross-account or cross-org access so that the active findings list represents only genuine issues requiring attention.

When to Use Archive Rules

  • A trusted partner account that legitimately reads from your S3 bucket (contractual obligation, data sharing agreement).
  • An AWS service principal (logs.amazonaws.com, delivery.logs.amazonaws.com) that writes to S3 for logging.
  • A specific cross-account role assumption that is part of your organization's support model.

Archive Rule Filter Criteria

Archive rules support filtering on:

Filter Field Example Values
principal.AWS arn:aws:iam::999999999999:role/PartnerReadRole
principal.Federated cognito-identity.amazonaws.com
principal.Service delivery.logs.amazonaws.com
resourceType AWS::S3::Bucket
resource arn:aws:s3:::my-logging-bucket
isPublic true or false
error Any error code
status ACTIVE, ARCHIVED, RESOLVED

Filters support eq (equals), neq (not equals), contains, and exists operators.

Creating an Archive Rule (CLI)

aws accessanalyzer create-archive-rule \
  --analyzer-name org-analyzer \
  --rule-name partner-s3-read-access \
  --filter '{
    "principal.AWS": {
      "eq": ["arn:aws:iam::999999999999:role/PartnerReadRole"]
    },
    "resourceType": {
      "eq": ["AWS::S3::Bucket"]
    }
  }' \
  --region us-east-1

Archive Rule Best Practices

  1. Be specific. Scope rules as narrowly as possible — use both principal.AWS and resource filters together, not just principal.AWS.
  2. Document every archive rule. Add a comment or tag to the analyzer with the business justification, owner, and review date for each archive rule.
  3. Review archive rules quarterly. Access patterns change; archived findings for decommissioned partner integrations become dangerously invisible.
  4. Do not archive findings for isPublic: true unless the resource is intentionally public (e.g., a static website bucket). Even then, document the justification explicitly.
  5. Use separate archive rules for separate justifications. Avoid building a single rule that suppresses broad categories of findings.

Archive Rules vs. Access Preview

Archive rules are for ongoing suppression of known-good access patterns. Access Preview (a separate Access Analyzer feature) is for pre-deployment validation — modeling what findings would look like if a proposed policy were applied. Use Access Preview in deployment pipelines; use archive rules for post-deployment noise reduction.


Limitations and Edge Cases

Limitation Detail
Regional scope Each analyzer is regional. You need analyzers in every region where you have resources, or use the AWS Security Hub integration to aggregate findings.
IAM evaluation order Zelkova evaluates the same logic as IAM's authorization engine. Explicit Deny always wins; implicit Deny (no matching Allow) is handled correctly.
VPC endpoint conditions aws:SourceVpc and aws:SourceVpce conditions are partially supported. Findings may be marked as conditional rather than definitively resolved.
Service-linked roles Service-linked roles are analyzed for their trust policies but are not included in unused access analysis.
New services Support for new resource types and condition keys is added over time. Check the AWS documentation for the current list of supported resources and condition keys.
CloudTrail dependency for unused access Unused access analysis requires CloudTrail to be enabled in the account. If CloudTrail was recently enabled, the lookback window data may be incomplete.
Cross-region resource policies Analysis is per-region. An S3 bucket in us-west-2 is analyzed by the us-west-2 analyzer, not the us-east-1 analyzer.
Propagation delay Finding updates can take up to 30 minutes after a policy change in complex organizational environments due to event processing pipelines.