Mastering AWS Security Specialty - Post 1: Deep Dive into IAM – Core of AWS Security


What Is IAM and Why It Matters

AWS Identity and Access Management is at the core of AWS security. It determines who can access what, how, and under what conditions.

Note: IAM protects AWS APIs only.

AWS IAM is your initial defense layer. Misconfiguration can result in overly permissioned access—or worse, exposed data.


IAM Identities

IdentityDescriptionWhen to UseExample
UserRepresents an individual or a serviceLong-term identity, used for console or programmatic accessDevelopers, CI/CD tools
GroupA collection of usersApply same policies to multiple usersDevelopers group with S3 access
RoleTemporary credentialsUsed by AWS services, users, applications, external identitiesEC2 to access S3, cross-account access
Federated UserExternal identity (AD, Google, etc.) authenticated via STSDon’t want to manage IAM users.SSO with Okta or AD Federation
Service-linked RolePredefined role linked to AWS serviceAllows AWS service to manage resources on your behalfAWS Elastic Beanstalk role, Auto scaling.
AWS Account Root UserFull access identity created during account setupOnly for billing or account recoveryNever use for daily tasks

IAM Policies

An IAM policy is a JSON document that must follow a strictly defined format.

Primary Elements of policy:

  • Principal : Who is making the request. It is an Identity that sends the request, such as user, role, AWS service, or some special entity.

  • Action : What they want to do. It defines what the Principal wants to do, such as reading an object in S3.

  • Resource: What they want to access. It is the logical entity in the account. Any AWS service that is the subject/target of the request.


IAM Policy Filters

Elements like Principal/NotPrincipal, Action/NotAction, Resource/NotResource can serve as filters.

example policy:

    {
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSpecificPrincipalAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:user/SpecificUser"
      },
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::example-bucket"
    },
    {
      "Sid": "DenyAllExceptSpecificPrincipals",
      "Effect": "Deny",
      "NotPrincipal": {
        "AWS": "arn:aws:iam::111122223333:user/SpecificUser"
      },
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::example-bucket/*"
    },
    {
      "Sid": "AllowExceptSpecificActions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:role/SpecificRole"
      },
      "NotAction": [
        "s3:DeleteObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::example-bucket/*"
    },
    {
      "Sid": "DenySpecificResources",
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:user/SpecificUser"
      },
      "Action": "s3:*",
      "NotResource": "arn:aws:s3:::example-bucket/specific-folder/*"
    }
  ]
}

IAM Policy Conditions

Conditions refine permissions by specifying when a policy statement is applicable.

Key Components:

  • Condition Keys: Predefined or AWS-specific keys (e.g., aws:SourceIp, s3:Prefix).

  • Condition Operators: Logical operators to compare values (e.g., StringEquals, IpAddress).

  • Condition Values: The value(s) against which the condition key is evaluated

Condition Types

1. Global Condition Keys

These keys are common across all AWS services.

  • Examples:

    • aws:SourceIp: Restrict access based on the IP address.

    • aws:UserAgent: Restrict access based on the user agent of the client.

    • aws:RequestTag: Control access based on request tags.

    • aws:MultiFactorAuthPresent: Check if MFA is used.

2. Service-Specific Condition Keys

Each AWS service has its own condition keys. Below are examples from popular services:

  • S3 (Amazon Simple Storage Service):

    • s3:Prefix: Control access to objects with a specific prefix.

    • s3:x-amz-acl: Restrict actions based on the ACL used in the request.

    • s3:RequestObjectTagKeys: Control access based on object tags in the request.

  • EC2 (Elastic Compute Cloud):

    • ec2:Region: Restrict actions to a specific region.

    • ec2:InstanceType: Control actions based on instance type.

  • KMS (Key Management Service):

    • kms:EncryptionContext:Key: Restrict access based on encryption context keys.

    • kms:ViaService: Control access based on the service that is using the key.

  • IAM (Identity and Access Management):

    • iam:PolicyARN: Restrict actions based on attached policy ARNs.

    • iam:ResourceTag: Control access based on resource tags.

  • CloudWatch:

    • cloudwatch:Namespace: Restrict actions to specific namespaces.

    • cloudwatch:ResourceTag: Control actions based on tags.

3. Common Operators

  • StringEquals: Checks if the string matches exactly.

  • StringLike: Checks if the string matches a pattern (wildcards supported).

  • IpAddress: Checks if the IP address is in specific ranges.

  • NumericEquals: Checks if a numeric value matches.

  • DateEquals: Checks if a date matches.

  • Bool: Checks if a value is true or false.


IAM Policy Types

How a policy behaves is determined by what it is attached to. We can attach a policies to different entities as below, and they are named accordingly.

1. Identity-based:

  • Grant permissions to identities, attached to user, group, or role. As it attached to a Principal so there is no Principal element in policy.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::app-logs/audit.log"
        },
        {
            "Effect": "Deny",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::app-logs/*"
        }
    ]
}

2. Resource-based:

  • Defined on the resource (e.g., S3 bucket policy, Lambda permission). Supports cross-account access. Only certain services support resource-based policies (S3, SNS, SQS, Lambda, etc.)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789:role/app-auditors"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::app-log/audit.log"
        }
    ]
}

Note: All resources NOT supports Resource-based policies refer the table for details

3. Permission Boundaries:

  • Limit max permissions regardless of attached policies. Important for delegated access.

    Delegate admin role to developers but cap their power using permissions boundaries

Policy

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*"
  }]
}

Boundary

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LimitToSpecificServices",
            "Effect": "Allow",
            "Action": [
                "s3:*",                 // Allows S3 actions
                "ec2:Describe*",        // Allows describing EC2 resources
                "lambda:InvokeFunction" // Allows invoking AWS Lambda
            ],
            "Resource": "*"
        },
        {
            "Sid": "DenySensitiveActions",
            "Effect": "Deny",
            "Action": [
                "iam:*",             // Deny IAM actions
                "ec2:Terminate*"     // Deny EC2 termination
            ],
            "Resource": "*"
        }
    ]
}

4. Session Policy:

  • Attached to STS temporary session to restrict permissions during a role/session. Used during AssumeRole. They do not limit what the identity (who is using a role) can do, but they put self-imposed restraints on the permissions.

A role that has full access to all S3 buckets

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

However, you want to ensure that during the session, this user can only access a specific S3 bucket (example-bucket) and only perform read operations (GetObject).

Session-policy-example.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowReadAccessToSpecificBucket",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket/*"
      ]
    },
    {
      "Sid": "DenyAllOtherS3Actions",
      "Effect": "Deny",
      "Action": "s3:*",
      "Resource": "*"
    }
  ]
}

Apply the Session Policy:

aws sts assume-role \
    --role-arn "arn:aws:iam::123456789012:role/FullAccessRole" \
    --role-session-name "RestrictedSession" \
    --policy file://session-policy-example.json

5. Service Control Policies (SCPs):

Org-level permission filter. It sets permission boundaries for accounts. Note: Cannot grant permissions, only restrict.

An operation is denied if it does not explicitly allowed.

We can use 2 approaches to define the policy -

Allow Listing will restrict all except allowed in policy.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

Deny listing will allow except explicitly denied.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        },
        {
            "Effect": "Deny",
            "Action": "iam:*",
            "Resource": "*"
        }
    ]
}

6. Inline Policies:

Attached to a single identity (User, Group, Role). Use when the policy is unique and shouldn’t be reused. When we delete the identity, the policy is deleted with it.

7. Managed Policies:

Managed policies are separate permission resources that we can attach to multiple identities and manage in a central place.

  1. AWS Managed: Created by AWS for most common use-cases. (e.g., AmazonS3FullAccess)

  2. Customer Managed: You define it (recommended for control). When multiple identities need same access create your own in IAM Policy.


Permissions Boundaries vs SCPs

FeaturePermissions BoundarySCP
Applies toIAM User/RoleAWS Account/OU
LimitsMax permissionsAll IAM permissions
Use CaseDelegation, controlMulti-account governance

IAM Policy Evaluation Logic

  • Explicit Deny > Allow > Implicit Deny

    • If there is a Deny, then denied.

    • If there is no Allow, then denied.

  • Policies from all sources (user, group, role) are merged

Denies override all allows.

Policy evaluation logic


Types of IAM Roles

Role TypePurposeHow/When to UseExample
Service RoleGrant AWS services permissionsUse with EC2, Lambda, ECS, etc.EC2 to write logs to CloudWatch
Cross-account RoleShare access between AWS accountsUsed in centralized logging, multi-account strategyAdmin role in Shared Services account
Federated RoleUsed by external identities via STSIntegrate corporate directorySAML or OIDC federation
Role for ApplicationsTemporary credentials for appsUse with mobile/web appsCognito + IAM role
Service-linked RoleRequired by AWS servicesAutomatically createdAWS Config or Elastic Beanstalk roles

IAM Security Best Practices

  • Enable MFA for all users

  • Use roles instead of long-term credentials

  • Implement least privilege access

  • Enable Access Analyzer to spot unintended access

  • Tag identities for better management and automation


Summary & What’s Next

IAM is foundational. You now understand:

  • Different IAM entities

  • Policy types and their roles

  • Evaluation logic and best practices

Exam Tips:

TopicThings to Remember
Policy EvaluationExplicit Deny > Allow > Implicit Deny
MFA PoliciesYou can require MFA via conditions in policy
FederationKnow difference between SAML, OIDC, and IAM Identity Center
SCPDoes NOT grant permissions, only restricts
Access AnalyzerExam focuses on detecting unwanted access
IAM RolesRequire trust policy and are assumed using STS
IAM User KeysRotate regularly and avoid long-term usage
Service-linked RolesAuto-created by AWS services – don’t modify manually
Session DurationCan control using sts:DurationSeconds in trust policy
Principal of Least PrivilegeAlways enforce minimum required access

Coming Up:
Next, we’ll dive into AWS CloudTrail — your forensic lens into AWS.
Stay tuned for more in the "Mastering AWS Security Specialty" series!


To understand big picture of AWS Security Services, check “Choosing the Right AWS Security Services: A Solution Architect's Guide

0
Subscribe to my newsletter

Read articles from Suman Thallapelly directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Suman Thallapelly
Suman Thallapelly

Hey there! I’m a seasoned Solution Architect with a strong track record of designing and implementing enterprise-grade solutions. I’m passionate about leveraging technology to solve complex business challenges, guiding organizations through digital transformations, and optimizing cloud and enterprise architectures. My journey has been driven by a deep curiosity for emerging technologies and a commitment to continuous learning. On this space, I share insights on cloud computing, enterprise technologies, and modern software architecture. Whether it's deep dives into cloud-native solutions, best practices for scalable systems, or lessons from real-world implementations, my goal is to make complex topics approachable and actionable. I believe in fostering a culture of knowledge-sharing and collaboration to help professionals navigate the evolving tech landscape. Beyond work, I love exploring new frameworks, experimenting with side projects, and engaging with the tech community. Writing is my way of giving back—breaking down intricate concepts, sharing practical solutions, and sparking meaningful discussions. Let’s connect, exchange ideas, and keep pushing the boundaries of innovation together!