1. Introduction to AWS Identity and Access Management

Arindam BaidyaArindam Baidya
43 min read

Table of contents

AWS Identity and Access Management (IAM) are responsible for securing cloud access, or manage permissions for your organization’s users and applications.

Why AWS IAM Matters

AWS IAM is the foundational service for controlling secure access to AWS resources. With IAM, you can:

  • Create and manage users, groups, and roles

  • Define fine-grained permissions using policies

  • Implement robust access control for applications, services, and end users

Think of IAM as your roadmap to secure and compliant cloud operations.

What You’ll Learn

In this lesson, we will:

  1. Understand the core concepts of IAM (users, groups, roles, policies)

  2. Explore IAM best practices for least-privilege access

  3. Walk through hands-on labs to configure real-world scenarios

  4. Discover advanced features like managed policies, identity providers, and cross-account access

Whether you’re new or have some IAM experience, we’ll start with fundamentals and gradually move into advanced topics.

Note

Ensure you have an active AWS account with administrative privileges to follow along with the labs.

IAM Key Components

Resource TypeDescriptionCommon Use Case
UserAn individual identityGrant CLI or console access to an employee
GroupA collection of IAM usersApply shared permissions to multiple users
RoleA set of permissions assumed by entitiesEnable cross-account access or service permissions
PolicyA JSON document defining permissionsAttach to users, groups, or roles to allow or deny actions

IAM Overview

AWS Identity and Access Management (IAM) is the cornerstone of security and access control in the AWS Cloud. With IAM, you can centrally manage permissions, enforce the principle of least privilege, and govern how your users and applications authenticate and authorize with AWS services.

What You’ll Learn

  • IAM Users: Create dedicated accounts for individuals to access AWS via Management Console, CLI, or SDKs.

  • AWS CLI & SDKs: Automate IAM operations and integrate AWS services into your applications.

  • IAM Groups: Simplify permission management by grouping users and attaching policies.

  • IAM Roles: Grant short-term permissions to AWS resources without storing long-term credentials.

  • Identity Policies: Define JSON-based permissions and attach them to users, groups, or roles.

  • Resource-Based Policies: Attach permissions directly to AWS resources (e.g., S3 buckets, SQS queues).

  • Session Policies: Scope down permissions for a single session to enforce tighter control.

  • Permission Boundaries: Limit the maximum permissions an IAM entity can acquire, enforcing least-privilege.

The image is a slide titled "IAM Overview" with a list of topics related to Identity and Access Management, including IAM Users, AWS CLI and SDK, IAM Groups, IAM Roles, Identity Policy, Resource Based Policy, Session Policy, and Permission Boundary.

Key IAM Components

ComponentDescriptionCommon Use Case
IAM UsersLong-term credentials for individual identityTeam members accessing the AWS Console or CLI
IAM GroupsCollections of users for bulk permission managementGranting developers access to specific AWS services
IAM RolesTemporary credentials assumed by AWS services or federated usersEC2 instances needing S3 read/write access
Identity PoliciesJSON documents specifying “Allow” or “Deny” actionsAttaching S3-read policy to a developer group
Resource PoliciesPermissions attached directly to AWS resources (bucket, queue, etc)S3 bucket policy to allow CloudFront distribution
Session PoliciesInline policies passed in a role or user sessionLimiting an API call to only a particular DynamoDB table
Permission BoundariesMaximum permissions an IAM entity can obtainEnsuring contractors cannot escalate privileges

Note

Use permission boundaries to enforce least-privilege at scale. They act as an upper-limit guardrail, even if an identity has broader permissions via attached policies.

AWS Account

To start using AWS resources and services, you must first create an AWS account. AWS operates on a pay-as-you-go model—there are no upfront costs, and you only pay for what you use at the end of each billing cycle. Many organizations leverage multiple accounts for isolation, billing, and security, then consolidate costs using AWS Organizations.

Why Create an AWS Account?

  • Instant access to cloud services (compute, storage, databases, and more)

  • Flexible, pay-as-you-go pricing with no long-term commitments

  • Strong isolation between development, testing, and production environments

  • Consolidated billing across multiple accounts for streamlined cost management

  • Secure cross-account resource sharing and access control

Key Benefits of AWS Accounts

BenefitDescriptionExample
Access to AWS ServicesOnboard to cloud resources instantlyLaunch an EC2 instance in minutes
Pay-as-you-go PricingNo upfront fees; only pay for what you consumeMonthly cost based on compute hours
Account IsolationSeparate environments for different teams or projectsDedicated Dev, Test, and Prod accounts
Consolidated BillingAggregate charges across accounts in a single invoiceManage all costs via AWS Organizations
Cross-Account Resource SharingSecurely share resources with other AWS accountsGrant S3 bucket access to another account

The image outlines five benefits of creating an AWS account, including access to cloud resources, a pay-as-you-go model, account communication, consolidated billing, and creating accounts for different departments.

Demo: Creating an AWS Account

Follow these steps to register and activate your AWS account:

  1. Open your web browser and navigate to https://aws.amazon.com.

  2. Click Create an AWS Account.

  3. Enter a valid email address and choose a strong password.

  4. Specify an account name (alias) to identify your AWS account.

  5. Complete the registration form with contact details, payment information, and identity verification.

  6. After receiving confirmation, sign in as the root user using your registered email.

Warning

Avoid using the root user for daily operations. Create IAM users with the least privilege necessary and manage permissions through AWS IAM.

The image is a guide for creating an AWS account, featuring a simple illustration of a person with a "Demo" sign and instructions to visit the AWS website and enter an email address to create a password.

Demo Creating AWS Account

Here, you’ll learn how to set up a brand-new AWS account for your HR team. We’ll cover:

  • Creating and verifying a root user

  • Signing in for the first time

  • Accessing the AWS Management Console


Step 1: Navigate to the AWS Homepage

  1. Open your browser and go to https://aws.amazon.com.

  2. In the top-right corner, click Create an AWS Account.

The image shows an AWS signup page where users can enter their root email address and account name to create a new AWS account. There is also an option to sign in to an existing account.

Note

Ensure you’re using a secure and private network when creating your AWS root account.


Step 2: Provide Root User Email and Account Name

On the signup form:

  • Under Root user, enter the email address that HR will manage:

      HR@company1.com
    
  • Under Account name, choose a clear identifier:

      HR
    
  • Click Verify email address.
    You’ll receive a one-time code—enter it to confirm your email.


Step 3: Sign In as the Root User

  1. Return to https://aws.amazon.com and click Sign In.

  2. Select Root user (since no IAM users exist yet).

  3. Enter the same email you used during signup, then click Next.

The image shows an AWS sign-in page with options for root and IAM user login, alongside a promotional section for AWS Skill Builder offering access to over 500 free digital courses.


Step 4: Authenticate and Access the Console

  1. Enter your chosen password at the prompt.

  2. Click Sign In.

  3. You’ll land on the AWS Management Console as the root user.

Warning

Your root user has full account access. Avoid using these credentials for everyday tasks. After setup, create an IAM admin user and assign least-privilege permissions.


AWS Account Setup Overview

User TypeDescriptionBest Practice
Root userFull access to all AWS resourcesUse only for billing, support, and setup tasks
IAM userPermission-scoped user accountsAssign roles and policies for daily operations

IAM Users

In this lesson, you’ll learn how to set up IAM users and grant them access to AWS services. An IAM user can interact with AWS through the Management Console, AWS CLI, or SDKs, based on the permissions you attach.

Why IAM User Permissions Matter

Note

By default, a newly created IAM user has no permissions. You must attach policies to grant access.

AWS Services and CLI Examples

ServiceDescriptionCLI Example
Amazon EC2Virtual machines in the cloudaws ec2 describe-instances
Amazon RDSManaged relational databasesaws rds describe-db-instances
Amazon EKSKubernetes clustersaws eks list-clusters
AWS LambdaServerless compute for codeaws lambda list-functions
Amazon DynamoDBFast NoSQL databaseaws dynamodb list-tables
Amazon S3Object storage for filesaws s3 ls s3://your-bucket
Elastic Load Balancing (ELB)Distribute incoming trafficaws elb describe-load-balancers
Amazon Route 53Scalable DNS serviceaws route53 list-hosted-zones
Amazon VPCIsolated virtual networksaws ec2 describe-vpcs
Amazon SNSPub/Sub messaging and notificationsaws sns list-topics

Methods to Attach IAM Policies

You can grant AWS permissions by attaching policies to:

  • IAM Users: Directly attach policies to the user.

  • IAM Groups: Assign users to groups; they inherit group policies.

  • IAM Roles: Allow users or services to assume roles with temporary credentials.

Creating an IAM User

1. Using the AWS Management Console

  1. Sign in to the AWS Management Console.

  2. Navigate to IAM > Users > Add users.

  3. Enter a User name and select the access type:

    • Programmatic access (for AWS CLI/SDK).

    • AWS Management Console access (for web console).

  4. Click Next: Permissions and choose how to assign permissions:

    • Add user to group

    • Attach existing policies directly

    • Copy permissions from existing user

  5. Review and create the user. Download or copy the Access Key ID and Secret Access Key.

2. Using the AWS CLI

Create an IAM user:

aws iam create-user --user-name alice

Generate access keys for programmatic access:

aws iam create-access-key --user-name alice

Attach a policy (e.g., AmazonS3ReadOnlyAccess):

aws iam attach-user-policy \
  --user-name alice \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

Warning

Store your Access Key ID and Secret Access Key securely. Treat them like password credentials.

Demo Create IAM User

In this tutorial, you’ll learn how to create a new IAM user in AWS, verify console access, and configure AWS CLI credentials using AWS CloudShell. We’ll use john as our example user.

Prerequisites

You must be signed in to the AWS Management Console with an account or IAM user that has administrator privileges.


1. Access the IAM Console

  1. Sign in to the AWS Management Console.

  2. In the search bar, type IAM and select Identity and Access Management.

  3. On the IAM dashboard, review any security recommendations (e.g., enabling MFA).

The image shows an AWS Identity and Access Management (IAM) dashboard with security recommendations, including adding multi-factor authentication (MFA) for the root user and the current user. It also mentions an extended deadline for updating access permissions.

  1. In the left navigation pane, click Users to view existing IAM users.

2. Create a New IAM User

  1. Click Add users.

  2. Enter john as the User name.

  3. Under Select AWS access type, choose one or both of the following:

Access TypeDescription
AWS Management Console accessEnables web console sign-in
Programmatic accessGenerates access keys for CLI/SDK interaction

The image shows an AWS IAM user creation page where user details are being specified, including a username field filled with "john."

  1. For Console password, select Custom password and enter your desired password.

The image shows a section of the AWS IAM console where a user is setting a console password, with options for autogenerated or custom passwords and password requirements.

  1. Enable Require password reset to force john to set a new password at first sign-in.

The image shows an AWS IAM console screen for setting user permissions, with options to add a user to a group, copy permissions, or attach policies directly.

  1. On the Set permissions page, assign policies or skip this step to configure permissions later.

  2. Click Next until you reach the Review page, verify all settings, then click Create user.

  3. Choose Return to users.

The image shows an AWS IAM user creation page, displaying user details and permissions summary for a user named "john."


3. Test the Console Sign-In

  1. Open a private/incognito browser window.

  2. Navigate to https://aws.amazon.com and click Sign In.

  3. Select IAM user, enter your AWS account ID, then click Next.

  4. Provide Username: john and the initial password you set.

The image shows an AWS IAM console with a notification indicating a user was created successfully. It lists three users: amin, john, and kodekloud, along with their details.

  1. You’ll be prompted to change the password:

The image shows an AWS sign-in page for IAM users, with fields for account ID, username, and password, alongside an advertisement for AWS Training and Certification.

  1. Enter the old password, choose a new one, and confirm.

The image shows an AWS password change page where a user is prompted to enter their old password, new password, and confirm the new password. There is a button labeled "Confirm password change."

After confirmation, you will be signed in as john.


4. Configure AWS CLI for the New User

Next, we’ll set up AWS CLI credentials in CloudShell for the john profile.

  1. From the AWS Console, open CloudShell.

  2. Verify your current identity (should show your admin user, e.g., kodekloud):

aws sts get-caller-identity
{
  "UserId": "AIDAZFD2ZUTSVCJWCHYKF",
  "Account": "629470240221",
  "Arn": "arn:aws:iam::629470240221:user/kodekloud"
}
  1. Create access keys for john:

    • In IAM Console, go to Users > john.

    • Select the Security credentials tab.

    • Under Access keys, click Create access key.

    • For Use case, pick Command line interface and proceed.

    • Copy the Access key ID and Secret access key.

The image shows an AWS IAM console screen where an access key has been created. It includes a notification about the access key and best practices for managing it.

Warning

Keep the secret access key confidential. Do not commit it to version control or share it.

  1. Back in CloudShell, configure a dedicated profile:
aws configure --profile john

When prompted, enter:

  • AWS Access Key ID: <paste access key ID>

  • AWS Secret Access Key: <paste secret key>

  • Default region name: us-west-2 (or your preferred region)

  • Default output format: (leave blank or choose json)

  1. Validate the john profile:
aws sts get-caller-identity --profile john
{
  "UserId": "AIDAZFD2ZUTS3DCUVP",
  "Account": "629470240221",
  "Arn": "arn:aws:iam::629470240221:user/john"
}

You have now successfully created an IAM user, tested console sign-in, and configured AWS CLI access for john.

AWS CLI and SDK

In this lesson, you’ll learn how to streamline your AWS workflows using the AWS Command Line Interface (CLI) and AWS SDKs. We’ll cover:

  1. Creating an IAM user with console and programmatic access

  2. Configuring the AWS CLI on your local machine

  3. Integrating AWS SDKs within your applications

  4. Organizing permissions using IAM groups

For more details, refer to the AWS CLI User Guide and the AWS SDKs & Tools.


1. IAM User with Access Keys

To enable both console and programmatic access, create an IAM user (e.g., John) and generate an Access Key ID and Secret Access Key. These credentials allow John to authenticate with AWS services via CLI or SDKs.

The image is a diagram illustrating IAM user access keys, showing how a user named John accesses AWS services through the AWS Management Console, CLI, and SDK using specific credentials.

John can now:

  • Execute AWS CLI commands

  • Use AWS SDKs in applications to call AWS service APIs

Warning

Keep your Access Key ID and Secret Access Key secure. Never commit them to version control or expose them in client-side code.


2. Configuring the AWS CLI

Install the AWS CLI, then run:

aws configure

You’ll be prompted for:

  • AWS Access Key ID

  • AWS Secret Access Key

  • Default region name (e.g., us-east-1)

  • Default output format (e.g., json)

Example:

$ aws configure
AWS Access Key ID [None]: AKIAS7790KQGK63WUK6T5
AWS Secret Access Key [None]: kkQEiBjSKrDkWBLO9G/JJKQWIOKL/CpHjMGyoiJWW
Default region name [None]: us-east-1
Default output format [None]: json

Note

Credentials and configuration are stored in:

  • ~/.aws/credentials

  • ~/.aws/config

These files are used by both AWS CLI and AWS SDKs.

Now, any AWS CLI command you execute uses John’s credentials, targets the specified region, and returns JSON output by default.


3. Using AWS SDKs in Applications

AWS SDKs enable you to interact with AWS services programmatically. Below is a high-level flow for a browser-based app using the AWS SDK for JavaScript:

The image is a diagram illustrating the interaction between a browser script using the Amazon SDK for JavaScript, Amazon Polly, and Amazon Cognito, showing the flow of requests and responses.

  1. The browser script initializes the AWS SDK with temporary credentials (often retrieved via Amazon Cognito).

  2. It calls an AWS service API (for example, Polly’s SynthesizeSpeech).

  3. AWS processes the request and returns a response, which the application then handles and renders.

Example: AWS SDK for JavaScript (v3)

import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity";
import { PollyClient, SynthesizeSpeechCommand } from "@aws-sdk/client-polly";


const REGION = "us-east-1";
const IDENTITY_POOL_ID = "us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";


// Initialize credentials
const credentials = fromCognitoIdentityPool({
  client: new CognitoIdentityClient({ region: REGION }),
  identityPoolId: IDENTITY_POOL_ID,
});


// Create Polly client
const polly = new PollyClient({ region: REGION, credentials });


async function synthesizeText(text) {
  const command = new SynthesizeSpeechCommand({
    OutputFormat: "mp3",
    Text: text,
    VoiceId: "Joanna",
  });
  const response = await polly.send(command);
  // Process response.AudioStream
}

4. Managing Permissions with IAM Groups

IAM groups simplify permission management by allowing you to assign policies to multiple users at once. Follow these best practices:

Best PracticeDescriptionExample
Descriptive NamesUse clear, role-based group namesDevelopers, DataScientists, Admins
Granular PoliciesAttach least-privilege policies to groupsAmazonS3ReadOnlyAccess
Role SimilarityGroup users with similar responsibilitiesMarketing, Engineering, Finance

The image is a diagram illustrating the concept of IAM (Identity and Access Management) Groups, highlighting aspects like simplifying user management, using descriptive names, grouping similar roles, and applying policies.

Demo: Creating an IAM Group

  1. Sign in to the AWS Management Console and open the IAM console.

  2. In the navigation pane, choose User groupsCreate group.

  3. Enter a group name (e.g., MarketingTeam).

  4. Attach one or more policies to grant required permissions.

  5. Add existing users (like John) to the group.

Once created, every user in the group inherits the attached policies automatically.

Demo IAM Groups

In this tutorial, you'll learn how to create IAM groups in the AWS Management Console, attach policies, and add existing users. We’ll set up two groups:

  • HR: Grants access to a specific S3 bucket.

  • IT: Provides full administrative privileges.

Best Practice

Always follow the principle of least privilege when assigning permissions. Create custom policies scoped to the resources your team actually needs.

Prerequisites

  • An AWS account with sufficient privileges to manage IAM resources.

  • Existing IAM users (e.g., John, Sarah).

Step 1: Open the IAM Console

  1. Sign in to the AWS Management Console.

  2. Navigate to Services > Security, Identity, & Compliance > IAM.

  3. In the left pane, select User groups.

You should see a list of your current IAM user groups (if any).


Step 2: Create the “HR” Group

  1. Click Create group.

  2. Enter HR as the Group name.

  3. Under Add users to group, select John.

  4. In Attach managed policies, click Create policy, then paste the JSON below:

     {
       "Version": "2012-10-17",
       "Statement": [
         {
           "Sid": "HRPolicy",
           "Effect": "Allow",
           "Action": "s3:*",
           "Resource": [
             "arn:aws:s3:::company1-hr-bucket",
             "arn:aws:s3:::company1-hr-bucket/*"
           ]
         }
       ]
     }
    
  5. Review the policy, give it a name like HRPolicy, and attach it to the group.

  6. Click Create group to finalize.

The image shows the AWS Identity and Access Management (IAM) console, specifically the "User groups" section, where an "HR" user group has been created with one user and defined permissions.


Step 3: Create the “IT” Group

  1. Click Create group again.

  2. Enter IT as the Group name.

  3. Select Sarah under Add users to group.

  4. In Attach managed policies, search for and select AdministratorAccess.

  5. Click Create group.

The IT group will now have full AWS administrative access.

The image shows the AWS Identity and Access Management (IAM) console, displaying user groups with two groups named "HR" and "IT," each having one user and defined permissions.


Summary of IAM Groups

GroupUserPolicyAccess Scope
HRJohnHRPolicycompany1-hr-bucket S3 bucket
ITSarahAdministratorAccessFull AWS services and resource control

Warning

Review and regularly audit your IAM policies to ensure compliance and security.

IAM Policies and Permissions

In AWS, IAM policies and permissions control who can perform which actions on which resources. Applying the Principle of Least Privilege—granting only the access needed to perform a task—helps secure your environment.

Principle of Least Privilege

Grant users and roles only the permissions they require. In this example, Sarah creates three groups:

  • Admins (Bob and Susan): full management rights across AWS services.

  • Developers: access limited to a specific Sales folder.

  • Test (Kathy and Alan): no access to the Sales folder.

The image illustrates a diagram for implementing the Principle of Least Privilege, showing different user groups (Admins, Developers, Test) and their access permissions to AWS Services and a Sales Folder.

Note

Applying least privilege minimizes the blast radius if credentials are compromised.

Defining Permissions

A permission is a fine-grained control that authorizes an action on an AWS resource. Common permission examples:

  • ec2:StartInstances – start an EC2 instance

  • s3:GetObject – download an object from an S3 bucket

  • sqs:CreateQueue – create a new SQS queue

  • sns:DeleteTopic – delete an SNS topic

A policy is a collection of one or more permissions.

What Is an IAM Policy?

An IAM policy is a JSON document that defines:

  • Who (user, group, role) can perform

  • What actions on

  • Which resources

IAM policies give you granular control over access.

The image explains IAM policies, highlighting their role in managing access and permissions in AWS, defining permissions for identities or resources, specifying accessible resources and operations, and providing fine-grained access control.

Policy Types

IAM policies fall into two primary categories:

Policy TypeAttachment PointUse Case
Identity-based policyUsers, groups, rolesGrant permissions to IAM identities
Resource-based policyAWS resources (e.g., S3, Lambda)Attach policies directly to resources themselves

The image categorizes IAM policies into "Identity Policies" and "Resource-Based Policies," with examples like Role, Group, User, S3, and Lambda.

You can attach an identity-based policy to a group of developers or assign a role to an EC2 instance so your applications inherit those permissions.

Identity-based Policy Example

Below is a sample JSON identity policy with two statements:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": [
        "arn:aws:s3:::<bucket-name>"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:StartInstances"
      ],
      "Resource": [
        "arn:aws:ec2:<region>:<account-id>:instance/<instance-id>"
      ]
    }
  ]
}
  • The first statement allows all S3 actions on a specific bucket.

  • The second statement allows starting a particular EC2 instance.

Warning

Use wildcard (*) actions sparingly. Overly broad permissions increase security risks.

Demo: Creating an Identity Policy

Follow these steps in the AWS Management Console to create and attach an identity-based policy to a group:

  1. Sign in to the IAM console.

  2. Navigate to Policies > Create policy.

  3. Use the JSON editor to paste your policy document.

  4. Review and Create policy.

  5. Attach the new policy to your IAM group.

The image is a slide titled "Create Identity Policy" with an illustration of a person pointing to a "Demo" sign. It includes instructions for creating identity-based policies for IAM groups on AWS.

Demo Identity Policy

No, you’ll see how to create a custom IAM identity policy in AWS, attach it to a user group, and then refine its permissions using both the Visual editor and the JSON editor. By the end, you’ll have a policy that grants S3 read access, full EC2 permissions, and explicitly denies the ability to stop EC2 instances.


1. Create a Developers Group

  1. In the AWS Management Console, navigate to IAMUser groups.

  2. Click Create group, name it Developers, and add the user John to the group.

  3. Skip attaching any policies for now and finish the wizard.

The image shows an AWS Identity and Access Management (IAM) console screen where users can be added to a group, with a list of users and their details such as groups, last activity, and creation time.

Once created, you’ll see Developers listed without any permissions:

The image shows an AWS IAM (Identity and Access Management) console with a list of user groups, including "Developers" and "HR," along with their user counts and creation times. A notification indicates that the "Developers" user group was created.


2. Create a Custom Policy

  1. In the IAM sidebar, select Policies.

  2. Click Create policy.

The image shows the AWS Identity and Access Management (IAM) console, specifically the Policies section, listing various customer-managed policies with options to filter, create, and manage them.

2.1 Grant S3 Read Access

  • Under Service, choose S3.

  • In Actions, expand Read and check GetObject.

  • Under ResourcesAdd ARN, enter:

    • Bucket: company1-sales

    • Object: *
      The console will build the ARN for you.

The image shows an AWS IAM policy creation interface for S3, where actions and access levels can be specified. Options include listing, reading, writing, permissions management, and tagging.

The image shows a dialog box in the AWS IAM console for specifying ARNs, with fields for resource bucket and object names, and an ARN being entered.

2.2 Grant EC2 Full Access

  • Click Add permissionsEC2.

  • Select All EC2 actions under Actions.

  • Leave the resource set to * for all instances.

Warning

Using * for resources grants full access to all EC2 instances. In production, scope this down by specifying ARNs for specific instances or regions.

The image shows an Amazon Web Services (AWS) IAM policy creation interface, specifically for setting permissions related to EC2 actions. It includes options to allow or deny actions, with categories like List, Read, Write, Permissions management, and Tagging.

The image shows an AWS IAM policy creation interface, highlighting a warning about using the wildcard '*' for resource permissions, suggesting that specifying ARNs can improve security.

2.3 Review, Name, and Create

  1. Click Next until you reach Review policy.

  2. Set Name to Developers_Policy and add an optional description.

  3. Click Create policy.

The image shows a web page from the AWS IAM console where a user is creating a policy named "Developers_Policy." The page includes fields for policy details and an optional description.


3. Attach Policy to the Developers Group

  1. Return to IAMUser groups.

  2. Select Developers.

  3. Under the Permissions tab, click Attach policies.

  4. Search for and select Developers_Policy, then click Attach policy.

Once attached, you can click the JSON icon to inspect the policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    },
    {
      "Sid": "VisualEditor1",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::company1-sales/*"
    }
  ]
}

4. Edit the Policy

Click Edit policy on the Permissions tab to open the policy editor. You can switch between the Visual editor and the JSON tab.

4.1 Rename Statement IDs

Replace autogenerated Sid values with clear identifiers:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAllEC2Actions",
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    },
    {
      "Sid": "AllowS3GetObject",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::company1-sales/*"
    }
  ]
}

4.2 Deny Stopping EC2 Instances

Add a statement to prevent developers from stopping instances:

{
  "Sid": "DenyStopInstances",
  "Effect": "Deny",
  "Action": "ec2:StopInstances",
  "Resource": "*"
}

4.3 Final Policy JSON

Combine all statements into your final policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAllEC2Actions",
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    },
    {
      "Sid": "AllowS3GetObject",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::company1-sales/*"
    },
    {
      "Sid": "DenyStopInstances",
      "Effect": "Deny",
      "Action": "ec2:StopInstances",
      "Resource": "*"
    }
  ]
}
SidEffectActionResource
AllowAllEC2ActionsAllowec2:**
AllowS3GetObjectAllows3:GetObjectarn:aws:s3:::company1-sales/*
DenyStopInstancesDenyec2:StopInstances*

Click Save changes to apply the updated policy.

The image shows an AWS IAM policy editor screen, detailing permissions for S3 and EC2 services with options to allow or deny actions. There is a button to save changes at the bottom.

IAM Resource Based Policy

Now, we’ll explore how IAM resource-based policies work in AWS, focusing on S3 bucket policies. Resource-based policies are attached directly to resources—such as S3 buckets—to specify which AWS principals can perform actions on them.

Key Components of a Resource-Based Policy

ElementDescription
VersionDefines the policy language version (e.g., 2012-10-17).
StatementContains one or more permission statements.
PrincipalSpecifies the AWS entity (user, role, account, or group) to which the policy applies.
EffectIndicates whether to Allow or Deny specified actions.
ActionLists AWS operations (for example, s3:DeleteObject).
ResourceDefines the ARN(s) of the target resource(s).

Example: Explicit Deny in an S3 Bucket Policy

The following policy blocks the accounting group from deleting objects or the bucket itself in the accounting1 S3 bucket:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": {
        "AWS": "arn:aws:iam::123456789:group/accounting"
      },
      "Action": [
        "s3:DeleteBucket",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::accounting1",
        "arn:aws:s3:::accounting1/*"
      ]
    }
  ]
}

Warning

Explicit denies always override any allows. Ensure you review all policies for unintended deny statements.

IAM Policy Evaluation Logic

When multiple statements or policies apply to a request, AWS evaluates them in this order:

OrderEvaluation StepOutcome
1Explicit Deny presentRequest is denied immediately.
2Explicit Allow (no Deny)Request is granted.
3Neither Deny nor AllowRequest is implicitly denied.

The image is a flowchart explaining how IAM policies are evaluated, showing decision paths based on explicit deny, allow, and implicit deny outcomes.

Note

Implicit denies occur when no policy explicitly allows an action. You must explicitly allow all required operations.

Creating and Attaching Your S3 Bucket Policy

Follow these steps to apply a resource-based policy to an S3 bucket:

  1. Sign in to the AWS Management Console.

  2. Open the IAM service and choose Policies.

  3. Click Create policy, then select JSON.

  4. Paste your policy document and review.

  5. Attach the policy to the target S3 bucket under the Permissions tab.

Note

Make sure you have the necessary IAM permissions to create and attach policies. Failure to do so will result in authorization errors.

Demo Resource Based Policy

Now, we’ll walk through attaching a resource-based policy to an existing S3 bucket in your AWS account. You’ll learn how to use the Policy Generator, customize the JSON, and apply it to grant fine-grained access.

1. Navigate to the S3 Console

  1. Open the AWS Management Console and go to S3.

  2. Click Buckets and use the filter to find company1-sales.

The image shows an AWS S3 Management Console with an account snapshot displaying total storage, object count, and average object size. It also lists a bucket named "company1-sales" in the US West (Oregon) region.

  1. Select company1-sales and switch to the Permissions tab.

  2. Scroll to Bucket policy and click Edit.

  3. At the top of the editor, choose Policy Generator instead of writing raw JSON.

2. Generate a Bucket Policy

In the Policy Generator form:

FieldValue
EffectAllow
Principalarn:aws:iam::629470242021:user/john
ServiceS3
ActionsAll Actions (s3:*)
Resourcearn:aws:s3:::company1-sales

Click Add Statement, then Generate Policy.

The image shows a screenshot of the AWS Policy Generator interface, where a user is configuring an S3 Bucket Policy by selecting actions and specifying permissions.

3. Review and Customize the JSON

The generator outputs a JSON policy similar to this:

{
  "Id": "Policy1696277356902",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1696277354841",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::629470242021:user/john"
        ]
      },
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::company1-sales"
    }
  ]
}

Customize the Statement ID

Replace the auto-generated SID with something meaningful, for example JohnFullAccessToCompany1SalesBucket:

{
  "Id": "Policy1696277356902",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "JohnFullAccessToCompany1SalesBucket",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::629470242021:user/john"
      },
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::company1-sales"
    }
  ]
}

Note

By default, this policy grants permissions only on the bucket itself. To allow object-level actions (e.g., GetObject, PutObject), add the ARN arn:aws:s3:::company1-sales/* to the Resource array.

4. Apply the Policy

  1. Copy the finalized JSON.

  2. Paste it into the Bucket policy editor.

  3. Click Save changes.

You’ve now successfully attached a resource-based policy that grants the IAM user john full control over the company1-sales bucket.


Policy Statement Elements

ElementDescriptionExample
SidUnique identifier for the statementJohnFullAccessToCompany1SalesBucket
EffectAllow or Deny the actionAllow
PrincipalThe IAM user, role, or servicearn:aws:iam::629470242021:user/john
ActionThe S3 operations permitteds3:*
ResourceThe bucket or object ARNsarn:aws:s3:::company1-sales<br>arn:aws:s3:::company1-sales/*

IAM Permission Boundaries

Now, you’ll learn how to enforce the principle of least privilege for new IAM users—such as interns—by using permission boundaries. This lets you assign them to existing groups (e.g., Accounting and Dev) without granting any permissions beyond what you intend.

The image shows a diagram with two groups, "Accounting Group" and "Dev Group," each containing a red bucket icon linked to a checklist icon. The text at the top reads, "Manager Request: We are hiring interns."

Currently, both the Accounting Group and the Dev Group have rights to specific S3 buckets. If you simply add interns to these groups:

  • Accounting interns could view or modify confidential financial data.

  • Dev interns could access or change log files in S3.

To prevent over-permissioning, apply a permission boundary that caps the maximum actions an intern can perform—even if their group policies allow more.

What Is a Permission Boundary?

A permission boundary is an advanced IAM feature that specifies the upper limit of permissions an identity (user or role) can have. No matter how many permissions you attach via identity-based or group policies, the boundary ensures the principal cannot exceed its scope.

The image explains the concept of a "Permission Boundary" in IAM, highlighting its role in setting maximum permissions, preventing unintended access, restricting IAM policies, and controlling permission scope for users and roles.

Note

Permission boundaries do not grant permissions by themselves. They only restrict the maximum permissions that an IAM principal can utilize.

Step-by-Step: Create and Attach a Permission Boundary

Follow these steps in the AWS Management Console:

StepConsole NavigationAction
1IAM DashboardClick PoliciesCreate policy
2JSON tabPaste the boundary policy definition (see below)
3Review policyName it InternBoundaryPolicy and create
4Users → Select UserUnder Permissions pick Add permissions boundary and attach the new policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::example-log-bucket"
      ]
    }
  ]
}

The image is a tutorial slide titled "Create Permission Boundary," showing a stick figure labeled "Demo" and instructions for creating a permission boundary on AWS.

Warning

Even if an intern’s group policy grants broader access, they cannot exceed the actions allowed by their permission boundary.

Assigning Interns to Groups

Once the boundary is in place:

  1. Attach the InternBoundaryPolicy as a permissions boundary to each intern’s IAM user.

  2. Add the intern to the relevant group (Accounting or Dev).

  3. The intern inherits group permissions, but all actions are capped by the boundary.

Benefits of Using Permission Boundaries

BenefitDescription
Enforce Least PrivilegeLimits every principal to only the actions you explicitly allow
Granular ControlApplies max-permission caps even when multiple policies overlap
Risk MitigationPrevents accidental or malicious privilege escalation

Demo Permission Boundaries

Now, we’ll demonstrate how to enforce the principle of least privilege in AWS IAM by using permission boundaries. You’ll learn how to restrict a new user’s effective permissions so that they can only list S3 buckets without gaining full access.

1. Identify the Target S3 Bucket

First, open the Amazon S3 Management Console. Filter your buckets by the prefix “Company1” and locate company1-logs, which stores daily logs used by your development team.

The image shows an AWS S3 Management Console with a list of buckets named "company1-hr," "company1-logs," and "company1-sales," all located in the US West (Oregon) region and marked as not public.

2. Review Customer-Managed Policies

Next, navigate to the IAM console and filter customer-managed policies by “company1.” You should see:

The image shows the AWS Identity and Access Management (IAM) console, displaying a list of customer-managed policies filtered by "company1," including "Company1-Logs-Policy" and "Company1_List_S3_Buckets."

Policy NamePurposeKey Actions
Company1-Logs-PolicyFull S3 access to company1-logss3:ListBucket, s3:GetObject, s3:PutObject, s3:DeleteObject
Company1_List_S3_BucketsRead-only listing of all S3 bucketss3:ListAllMyBuckets, s3:GetBucketLocation

3. Inspect the Full-Access Logs Policy

Click on Company1-Logs-Policy to view its JSON document. This policy grants any principal full control over the company1-logs bucket.

The image shows an AWS Identity and Access Management (IAM) console screen, displaying a customer-managed policy with full access permissions for the S3 service.

Currently, this policy is attached to the Developers group. All members—like John—inherit full S3 permissions on company1-logs.


4. Scenario: Hiring a New Intern

We’ve hired an intern, Sara, but we want to limit her permissions to bucket listing only. Without adjustments, adding her to the Developers group would grant full S3 access.

  1. In the IAM console, click Create User.

  2. Enter Sara-intern as the username.

  3. Enable AWS Management Console access, generate a password, and require a reset on first login.

  4. Add Sara-intern to the Developers group and complete the user creation.

The image shows the AWS Management Console interface for creating a new IAM user, with a username "Sara-intern" being specified.

Note

By default, Sara inherits every permission granted to the Developers group. We need a permissions boundary to cap her maximum privileges.


5. Apply the Permissions Boundary

To restrict Sara’s permissions:

  1. Open Sara-intern’s user summary and go to the Permissions tab.

  2. Click Set permissions boundary.

  3. Select Company1_List_S3_Buckets and save.

The image shows an AWS IAM Management Console screen where a user is setting a permissions boundary for "Sara-intern." Two customer-managed policies are listed: "Company1_List_S3_Buckets" and "Company1-Logs-Policy."

Warning

A permissions boundary only defines the maximum rights a user can have. The user’s effective permissions are the intersection of their group policies and the boundary. Always validate by testing in a non-production account.

With Company1_List_S3_Buckets as Sara’s boundary, she can list bucket names (s3:ListAllMyBuckets) but cannot read, write, or delete any objects. This enforces least privilege for new users.

IAM Roles

AWS Identity and Access Management (IAM) roles enable secure, temporary access to AWS resources without embedding long-term credentials. By defining fine-grained permissions and trust relationships, you can enforce the principle of least privilege and reduce exposure risk.

ComponentDescriptionExample
RoleAn identity with attached permissions and a trust policyS3AccessRole
Permissions PolicyA JSON document specifying allowed or denied actionsAmazonS3ReadOnlyAccess
Trust PolicyDefines which principals (services, users, or accounts) can assume the roleEC2 service: ec2.amazonaws.com
Temporary TokensShort-lived credentials issued by AWS STSAccessKeyId, SecretAccessKey, SessionToken

The image explains IAM roles, highlighting their use for access control, adherence to the principle of least privilege, creation of temporary credentials, and establishment of trust relationships.

How IAM Roles Enhance Security

Instead of hard-coding long-term AWS keys:

  1. A principal (user or service) calls sts:AssumeRole.

  2. AWS returns temporary credentials.

  3. The principal uses these credentials to access resources.

  4. Credentials expire automatically, minimizing the blast radius.

Note

Always follow the principle of least privilege. Grant only the permissions required for the task.

Role Assumption Flow

The image illustrates a process for increasing security using IAM roles, showing the flow from an IAM user assuming a role, applying a policy, accessing an S3 role, and obtaining temporary keys.

Roles can be assumed not only by IAM users but also by AWS services such as EC2, Lambda, and ECS. The permissions come from attached policies, while the trust policy specifies who can assume the role.

AWS Components Interaction

The image is a diagram illustrating the relationship between AWS components: EC2 Service, S3 Bucket, IAM Role, IAM Policy, and IAM User. It shows how these components interact with each other in an AWS IAM Role setup.


Demo: Create an IAM Role for EC2 to Access S3

Follow these steps in the AWS Management Console or use the AWS CLI commands shown.

Console Steps

  1. Open the IAM console
    https://console.aws.amazon.com/iam

  2. Create a new role

    • In the navigation pane, choose RolesCreate role.

    • Under Select trusted entity, choose AWS service, then EC2, and click Next.

  3. Attach permissions

    • Search for AmazonS3ReadOnlyAccess (or attach your custom policy).

    • Select it and click Next.

  4. Name and create

    • Enter Role name: S3AccessRole

    • Review settings and click Create role.

  5. Attach the role to an existing EC2 instance

    • Open the EC2 console, select your instance.

    • Choose ActionsSecurityModify IAM role.

    • Select S3AccessRole and click Save.

AWS CLI Alternative

First, create a trust policy file (trust-policy.json):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "ec2.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}

Then run:

# Create the role
aws iam create-role \
  --role-name S3AccessRole \
  --assume-role-policy-document file://trust-policy.json


# Attach the AmazonS3ReadOnlyAccess policy
aws iam attach-role-policy \
  --role-name S3AccessRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

Verify from the EC2 Instance

SSH into your EC2 instance and confirm the role is in effect:

# Check the caller identity (should show the assumed role ARN)
aws sts get-caller-identity


# List S3 buckets or contents to verify permissions
aws s3 ls s3://your-bucket-name

If you see the bucket contents, the role is correctly configured—no long-term keys required.

Demo Creating IAM Role

In this step-by-step guide, you'll learn how to create an AWS Identity and Access Management (IAM) role that grants an Amazon EC2 instance permission to read objects from an S3 bucket named company1-logs. By leveraging IAM roles, you avoid hardcoding credentials on your server and follow AWS best practices for secure access management.

Prerequisites

  • An AWS account with administrative privileges

  • A running EC2 instance

  • An existing S3 bucket named company1-logs

Step 1: Create the IAM Role

  1. Open the IAM console, select Roles, then click Create role.

  2. On Select trusted entity, choose AWS service.

  3. Under Use cases for other AWS services, select EC2.

  4. Click Next to move to the permissions page.

  5. In Permissions, search for company1 and select the Company1 logs policy which grants s3:GetObject access to the company1-logs bucket.

  6. Click Next, then enter a Role name (e.g., Company1-Logs-Role) and an optional description.

  7. Review the Trust relationship to ensure EC2 can assume this role. It should resemble:

     {
       "Version": "2012-10-17",
       "Statement": [
         {
           "Effect": "Allow",
           "Action": ["sts:AssumeRole"],
           "Principal": {"Service": ["ec2.amazonaws.com"]}
         }
       ]
     }
    
  8. (Optional) Add tags to categorize your role, then click Create role.

Note

You’ve successfully created an IAM role that EC2 instances can assume to access S3 resources securely.

Step 2: Attach the IAM Role to Your EC2 Instance

  1. Go to the EC2 console, select Instances, and choose your running instance.

  2. From the Actions menu, select Security > Modify IAM role.

  3. In the IAM role dropdown, pick Company1-Logs-Role.

    The image shows an AWS console interface for modifying an IAM role attached to an EC2 instance. It includes a dropdown to select an IAM role and a warning about removing existing roles.

  4. Click Update IAM role to apply the change.

Warning

If your EC2 instance already has an IAM role attached, updating it will replace the existing role and associated permissions. Ensure this change aligns with your security policies.

Your EC2 instance now inherits the permissions defined in Company1-Logs-Role, allowing it to securely read log files from the company1-logs bucket without embedded credentials.

IAM Session Policies

In this lesson, we’ll explore how to grant an IAM user temporary upload access to an S3 bucket by using session policies. Our user currently has a policy allowing only the s3:GetObject action, but now needs permission to upload files (s3:PutObject). We’ll create a session policy, attach the upload permissions to it, and generate temporary credentials that enforce both the user’s existing rights and the new session policy.

The image illustrates a process for allowing temporary uploads to an S3 bucket, involving an IAM user, a policy for S3:GetObject, and temporary keys with a session policy for S3:PutObject.

What Are Session Policies?

Session policies are inline JSON policies you pass when you assume a role. They:

  • Define the maximum permissions an IAM principal can have during a session

  • Are temporary and apply only for the session’s duration

  • Further restrict permissions granted by identity or resource policies

  • Enable fine-grained, scenario-specific access control

The image explains session policies, highlighting their role in defining maximum permissions for IAM users, their temporary nature, and their use in conjunction with IAM roles for granular access control.

Note

Session policies never grant more permissions than allowed by the user’s identity or resource policies. They only tighten the scope for the session.

Demo: Granting Temporary Upload Access

In this demo, we will:

  1. Identify an IAM user with read-only S3 access

  2. Create a session policy granting s3:PutObject

  3. Assume a role with that session policy to obtain temporary credentials

  4. Verify the ability to upload objects to the bucket

First, sign in to the AWS Management Console, navigate to IAM, and begin creating the session policy.

The image is a slide titled "Create Session Policies" with a graphic of a person pointing to a "Demo" sign, and instructions for allowing S3 read-only access to upload files to an S3 bucket.

1. Create the Session Policy JSON

Save the following JSON as session-policy.json. Replace YOUR_BUCKET_NAME with your actual bucket name.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
    }
  ]
}

2. Assume the Role with Session Policy

Use the AWS CLI to assume the role and apply your session policy:

aws sts assume-role \
  --role-arn arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME \
  --role-session-name uploadSession \
  --policy file://session-policy.json \
  --duration-seconds 3600

This returns temporary credentials:

{
  "Credentials": {
    "AccessKeyId": "ASIAXXXX...",
    "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY",
    "SessionToken": "IQoJb3JpZ2luX2VjEO3//////////wEaCXVzLWVhc3QtMSJGMEQCH3...",
    "Expiration": "2023-08-01T12:34:56Z"
  }
}

3. Export Temporary Credentials

export AWS_ACCESS_KEY_ID="ASIAXXXX..."
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY"
export AWS_SESSION_TOKEN="IQoJb3JpZ2luX2VjEO3//////////wEaCXVzLWVhc3QtMSJGMEQCH3..."

Warning

These credentials are temporary. Do not commit them to source control or share them publicly.

4. Verify Upload Capability

Now try uploading a file:

echo "Hello, S3!" > test.txt
aws s3 cp test.txt s3://YOUR_BUCKET_NAME/

If successful, you’ve confirmed that the session policy is working as expected.

Policy Comparison

Policy TypeScopeDurationPurpose
Identity PolicyUser or RolePermanentGrants base permissions
Session PolicySTS SessionTemporaryRestricts permissions during a session

Demo Session Policies

Now, you’ll grant the IAM user John temporary file-upload permissions to the S3 bucket company1-hr using an AWS STS session policy and a dedicated IAM role. By the end, John will be able to upload objects for a limited time without altering his long-term permissions.

Prerequisites

  • AWS CLI installed and configured for user John

  • Bucket company1-hr already exists in account 629470240201

  • Basic familiarity with IAM, STS, and S3 permissions


Step 1: Verify Current AWS Identity

Confirm you’re authenticated as John:

aws sts get-caller-identity

Expected output:

{
  "UserId": "AIDAZFDZUTSTSYQ6QFLS",
  "Account": "629470240201",
  "Arn": "arn:aws:iam::629470240201:user/john"
}

Step 2: List Bucket Contents and Test Upload

Check existing objects and verify that upload is currently denied:

aws s3 ls s3://company1-hr
aws s3 cp new-file.txt s3://company1-hr
# fatal error: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

Step 3: Define the Session Policy

Create a JSON policy that allows listing, reading, and uploading:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "s3:ListBucket",
      "s3:GetObject",
      "s3:PutObject"
    ],
    "Resource": [
      "arn:aws:s3:::company1-hr",
      "arn:aws:s3:::company1-hr/*"
    ]
  }]
}
ActionDescription
s3:ListBucketList the bucket’s objects
s3:GetObjectDownload or read bucket objects
s3:PutObjectUpload new objects to the bucket

Note

Save this policy as SessionPolicy-UploadFile.json and upload it as a customer-managed policy named SessionPolicy-UploadFile.


Step 4: Create and Configure the IAM Role

  1. In the IAM console or via AWS CLI, create a role JohnUploadRole.

  2. Attach the SessionPolicy-UploadFile policy to this role.

Update the role’s trust policy so that John can assume it:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::629470240201:user/john"
    },
    "Action": "sts:AssumeRole"
  }]
}

Warning

Ensure the trust relationship is properly updated—otherwise, John will not be able to assume the role.


Step 5: Assume the Role and Export Temporary Credentials

Have John run the following to get short-lived credentials:

aws sts assume-role \
  --role-arn arn:aws:iam::629470240201:role/JohnUploadRole \
  --role-session-name JohnUploadSession

Sample response:

{
  "Credentials": {
    "AccessKeyId": "ASIAFD2ZUTS3J3PIX55",
    "SecretAccessKey": "iqhGcv6Lp3Y4wUgmIiRiRHhS4KinLURta92SW5V",
    "SessionToken": "IQoJb3JpZ2luX2VjE/////////WwECAa...",
    "Expiration": "2023-10-08T21:53:20Z"
  }
}

Export these values to the environment:

export AWS_ACCESS_KEY_ID="ASIAFD2ZUTS3J3PIX55"
export AWS_SECRET_ACCESS_KEY="iqhGcv6Lp3Y4wUgmIiRiRHhS4KinLURta92SW5V"
export AWS_SESSION_TOKEN="IQoJb3JpZ2luX2VjE/////////WwECAa..."

Step 6: Verify Upload Succeeds

With the new session credentials, repeat the list and upload:

aws s3 ls s3://company1-hr
aws s3 cp new-file.txt s3://company1-hr
aws s3 ls s3://company1-hr
# 2023-10-08 17:45:42      7 Test.txt
# 2023-10-08 20:55:38      3 new-file.txt

The file new-file.txt is now uploaded. These permissions automatically expire when the session token’s Expiration time is reached.

Auditing with CloudTrail

In this lesson, you’ll learn how to track and audit S3 access using AWS CloudTrail. When an IAM user performs actions—like deleting an object in an S3 bucket—you need to know who did it, when it happened, and exactly which operation was called. AWS CloudTrail records all API calls to your AWS resources, making this audit process straightforward.

Note

Make sure CloudTrail is enabled across all regions before you begin so that no API activity goes unrecorded.

Why Audit S3 Access?

By analyzing CloudTrail logs, you can:

FeatureDescription
API call loggingCapture every AWS API request, whether from users, services, or resources.
Action auditingReview who performed which operations on your resources.
API call trackingFilter logs by IAM users, resources, or specific event names.
Security event detectionIdentify both successful and failed login attempts.

The image is an infographic about "CloudTrail and User Access Audit," highlighting four key functions: logging API calls, auditing actions, tracking API calls, and detecting login attempts and security threats.

Demo: Use CloudTrail to Audit User Access

Follow these steps to search the event history in the CloudTrail console:

  1. Sign in to the AWS Management Console and open CloudTrail.

  2. In the sidebar, select Event history.

  3. Use the filter bar to narrow down by Event name, Username, or Resource name.

  4. Click an individual event to view details such as the request time, source IP, and whether the request succeeded or failed.

Demo CloudTrail

In this lesson, you’ll explore the AWS CloudTrail console to audit API calls by inspecting event history. By the end, you’ll know how to navigate events, read their details, and extract key metadata.

Viewing Event History

  1. Sign in to the AWS Management Console and open CloudTrail.

  2. In the left navigation pane, select Event history.

You’ll see a searchable list of API events with the following details:

ColumnDescription
Event nameThe API action (for example, RunInstances)
TimeTimestamp when the action occurred
UsernameIAM user or role that made the request
Event sourceAWS service endpoint (e.g., ec2.amazonaws.com)
ResourcesAffected resource types and identifiers

Select an event (for example, RunInstances) to view its full record.

Event Summary

The Summary pane displays metadata for the selected event:

  • Timestamp: When the API call occurred

  • User identity: IAM user or role and access key

  • Service: The AWS service that received the call

  • Source IP: Originating IP address

  • Region: AWS region of the operation

  • Resources count: Number of resources referenced by the event

Below is a truncated JSON snippet of a RunInstances event:

{
  "eventVersion": "1.08",
  "userIdentity": {
    "type": "IAMUser",
    "principalId": "AIDAZFDZ2ZUTSWJCHYKF",
    "arn": "arn:aws:iam::629470242021:user/kodekloud",
    "accountId": "629470242021",
    "accessKeyId": "ASIAZFDZ2ZUTSYABGGX",
    "userName": "kodekloud",
    "sessionContext": {
      "sessionIssuer": {},
      "webIdFederationData": {},
      "attributes": {
        "creationDate": "2023-10-08T17:21:45Z",
        "mfaAuthenticated": "false"
      }
    }
  },
  "eventTime": "2023-10-08T17:50:24Z",
  "eventSource": "ec2.amazonaws.com",
  "eventName": "RunInstances"
}

Note

The console shows the last 90 days of event history by default. For long-term retention, create a CloudTrail trail to deliver logs to an S3 bucket.

Request Parameters and Response Elements

Scrolling down shows the inputs you passed to the API and AWS’s response. The example below illustrates:

  • AMI ID and instance configuration

  • Key pair, security group, and tags

  • Network interfaces and instance state

{
  "awsRegion": "us-east-2",
  "sourceIPAddress": "70.175.135.47",
  "userAgent": "AWS Internal",
  "requestParameters": {
    "instancesSet": {
      "items": [
        {
          "imageId": "ami-036f5574583e16426",
          "minCount": 1,
          "maxCount": 1,
          "keyName": "Ohio-Key"
        }
      ]
    }
  },
  "responseElements": {
    "instancesSet": {
      "items": [
        {
          "instanceId": "i-0123456789abcdef0",
          "instanceType": "t3.micro",
          "placement": {
            "availabilityZone": "us-east-2b"
          },
          "state": {
            "code": 0,
            "name": "pending"
          },
          "privateIpAddress": "172.31.29.166",
          "dnsName": "ip-172-31-29-166.us-east-2.compute.internal",
          "keyName": "Ohio-Key",
          "groupSet": {
            "items": [
              {
                "groupId": "sg-00ca240f71292feb2",
                "groupName": "Webserver_SG"
              }
            ]
          },
          "tagSet": {
            "items": [
              {
                "key": "Name",
                "value": "Server1"
              }
            ]
          },
          "networkInterfaceSet": {
            "items": [
              {
                "networkInterfaceId": "eni-0892be3483f983663",
                "subnetId": "subnet-d07cb873ce0ee06",
                "vpcId": "vpc-0fd1744d0f9c0fe7a",
                "attachment": {
                  "attachmentId": "eni-attach-07bbe98b3bf06adea",
                  "status": "attaching",
                  "attachTime": 1696787423000,
                  "deleteOnTermination": true,
                  "deviceIndex": 0,
                  "networkCardIndex": 0
                },
                "privateIpAddressesSet": {
                  "items": [
                    {
                      "privateIpAddress": "172.31.29.166",
                      "privateDnsName": "ip-172-31-29-166.us-east-2.compute.internal",
                      "primary": true
                    }
                  ]
                },
                "ipv6AddressesSet": {},
                "sourceDestCheck": true
              }
            ]
          }
        }
      ]
    }
  }
}

Additional CloudTrail Metadata

At the bottom of each event record, CloudTrail provides management-level details that aid traceability:

{
  "maintenanceOptions": {
    "autoRecovery": "default"
  },
  "privateDnsNameOptions": {
    "hostnameType": "ip-name",
    "enableResourceNameDnsARecord": true,
    "enableResourceNameDnsAAAARecord": false
  },
  "requestID": "b3116925-dea3-43fd-9b10-19932ce1925",
  "eventID": "e2f69382-7637-4deb-83ed-e6ee31cac1c4",
  "readOnly": false,
  "eventType": "AwsApiCall",
  "managementEvent": true,
  "recipientAccountId": "629470242021",
  "eventCategory": "Management",
  "sessionCredentialFromConsole": "true"
}

Warning

Make sure your IAM policy includes the cloudtrail:LookupEvents permission to view this data.

0
Subscribe to my newsletter

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

Written by

Arindam Baidya
Arindam Baidya

🚀 Aspiring DevOps & Cloud Engineer | Passionate about Automation, CI/CD, Containers, and Cloud Infrastructure ☁️ I work with Docker, Kubernetes, Jenkins, Terraform, AWS (IAM & S3), Linux, Shell Scripting, and Git to build efficient, scalable, and secure systems. Currently contributing to DevOps-driven projects at Assurex e-Consultant while continuously expanding my skills through hands-on cloud and automation projects. Sharing my learning journey, projects, and tutorials on DevOps, AWS, and cloud technologies to help others grow in their tech careers. 💡 Let’s learn, build, and innovate together!