# Understanding Authentication and Authorization for API Requests in AWS

Every interaction you have with the cloud is through APIs. When you make an API request to AWS, it goes through several layers of authentication and authorization checks to verify your identity and assess your permissions. This process involves confirming 'you are who you say you are' and evaluating the request context against various predefined policies.

To understand the journey properly, you need to understand different terminologies so that you can clearly understand everything.

### IAM Principals

In AWS, the term "principal" refers to an entity that can make requests to perform actions and access resources. Principals are a fundamental part of IAM and play a crucial role in managing security and access control within your AWS environment.

Types of IAM principals that make requests:

* **AWS Account**
    
    A principal can be an entire AWS account identified by its unique AWS account ID.
    
    ```json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "123456789012"
          },
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::example-bucket/*"
        }
      ]
    }
    ```
    
    The above JSON object is a policy allows any entity/service in the AWS account with ID `123456789012` to perform the `s3:GetObject` action on all objects within the S3 bucket named `example-bucket`.
    
* **IAM Role**
    
    Temporarily gives specific permissions to identities. You can create an IAM role with specific permissions and attach it to a service/user to give a certain level of privilege.
    
    For giving temporary permission to services/users outside the AWS environment (for example, on-prem cloud), an **IAM Role Anywhere** service can be used.
    
* **IAM User**
    
    Specific individuals or services within an AWS account, identified by their IAM username. It is used for long-term credential access to the account. By default, an IAM user doesn't have any permission. To allocate permission, the best practice is to put users in a group and then attach a policy to that group, or attach a role to a user.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719501656119/7904f34e-5196-41ea-90ac-2a7a65bd33b4.png align="center")

* **Federated User**
    
    External users authenticated through identity providers (IdPs) like SAML, OpenID Connect, or AWS Cognito. This principal gets credential by using the `sts:GetFederationToken` API. This is not a user that is Federated by way of an identity provider. Most customers won't use this type of Federated user often.
    
* **Anonymous User**
    
    Makes unauthenticated requests to AWS. An anonymous principal refers to any entity that is accessing your AWS resources without any authenticated identity. Essentially, this means access is being granted to the general public, without requiring them to sign in or provide any credentials. This is often used in scenarios where you want to make certain resources publicly accessible, such as a public website or shared documents.
    
* **Root User**
    
    User with full access to AWS account.
    

Every principal has an ARN, which uniquely identifies the principal within AWS. For example, an IAM user ARN might look like `arn:aws:iam::123456789012:user/JohnDoe`. It is used to specify principal in your policy statement.

### AWS Policy

#### What is AWS Policy?

AWS Policy is a document that defines what actions a principal can perform on which resources within your AWS environment. It is written in JSON using the [IAM JSON Policy Language](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html) (except Access Control List).

We can devide all the policies into two categories:

1. Policies associated with IAM Entity (IAM Role, User, Group)
    
2. Policies associated with AWS Resource
    

Policies that defines the permissions of IAM Entity are:

* **Identity-base Policy**
    
    Grants permission to identities (Users, Groups, Roles). This policy can be managed or inline.
    
* **Organization's Service Control Policy (SCP)**
    
    Limits maximum permissions for account members of an organization or organizational unit (OU).
    
* **Permission Boundary**
    
    Limits how much permission *Identity-based policy* can give to an entity (user/role). It can only be used as managed policy.
    
* **Session Policy**
    
    Limits permissions that role or user's *identity-based policies* grant to the session.
    

Policies that defines the permission of AWS Resource are:

* **Resource-base Policy**
    
    Grants permission to principals of same account or different account. It is attached with resources like S3, EC2, etc and also the principal is specified in this policy statment. There are some special type of resource-based policies. Some of them we will talk in this blog are:
    
    * **Trust Policy**
        
        The trust policy defines which principals can assume the IAM Role, and under which conditions.
        
    * **VPC Endpoint Policy**
        
        It is used to control which AWS principals can use the endpoint to access an AWS service. An endpoint policy does not override or replace identity-based policies or resource-based policies.
        
* **Access Control List (ACL)**
    
    Grants permission to principals of same or different accounts. It doesn't use JSON format and few AWS service support this policy.
    

Following two mindmap screenshots are from my notes:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719507720242/6727ef64-be36-40fd-aeab-b0d5bbd4e665.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719243536779/e576caa5-42c2-46fa-8af8-3f3a6b5a2c14.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Any type of policy can have <strong>multiple policies</strong>, and each policy can have <strong>multiple statements</strong>.</div>
</div>

To learn more about AWS Policy, you can have a look in [AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html).

#### Statement: Building block of AWS Policy

An AWS Policy Statement is a component of an AWS Policy that specifies the permissions for a particular action or set of actions on specific resources. Each policy can have multiple statements, each providing detailed control over permissions. Lets analyze the following Identity-based policy.

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket",
        "arn:aws:s3:::example-bucket/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "ec2:StartInstances",
      "Resource": "arn:aws:ec2:us-west-2:123456789012:instance/*"
    },
    {
      "Effect": "Deny",
      "Action": "s3:DeleteObject",
      "Resource": "arn:aws:s3:::example-bucket/*"
    }
  ]
}
```

This policy grants specific permissions and denies one particular action within AWS. It allows the identity to list the contents of and retrieve objects from the S3 bucket named `example-bucket`, as well as start any EC2 instances in the `us-west-2` region under the account `123456789012`. However, the policy explicitly denies the ability to delete objects from the `example-bucket` S3 bucket.

#### How is a Policy Evaluated?

A policy can have multiple statements. But to pass through the policy, only one allow statement and no deny statement is required. For an incoming request, the request context is evaluated against the policies. To authorize the request against a policy,

1. At least one **statement** with an effect of allow must match for a request to be allowed.
    
2. A matching statement with an effect of deny takes precedence over a matching statement with an effect of allow.
    

This process will be repeated for all the policies in the policy chain. (Be aware that, based on scenario, different set of policies are evaluated in different order. We will learn about this in later part of this blog.)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719150042436/229e3197-f503-4ec0-af5c-2dd9bdf1188b.png align="center")

Based on the policy evaluation, AWS decides whether to allow or deny the request. The decision is logged in **AWS CloudTrail** for auditing purposes.

#### Tools and Resources for AWS Policies

* [AWS Policy Visualizer](https://bourabdelhadi.github.io/awsviz/)  
    Using this tool you can visualize AWS Policies and can manually debug the policy to check if has appropriate permissions. Great tool for writing and debugging effective policies.
    
* [Policy Simulator](https://policysim.aws.amazon.com/home/index.jsp)  
    Using this you can simulate how policy will work before adding/using the policy. You need an AWS account to use it (because it will use your IAM user to simulate).
    
* [Policy Generator](https://www.awsiamactions.io/)
    
    Use this website to generate policy in easy way.
    
* [Actions, resources, and condition keys for AWS services](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html)
    
    If you are someone who write AWS policies, then this page should be bookmarked. You will get all everything to write policies for all services in AWS.
    

### Request Journey

Now let’s break down the journey from the moment a request is made by an AWS principal until it’s authorized or denied. For simplicity we will focus on only one principal, AWS Role.

#### 1\. Making the API Request

You can only interact with AWS through API. For that, there are 3 ways — Console, CLI, and SDK.

* **AWS Management Console**: When you perform an action using the AWS Management Console, the console makes API calls on your behalf.
    
* **AWS CLI**: You can run commands directly in your terminal or write a script to interact with AWS services.
    
* **AWS SDKs**: When you are building a software and need to interact with AWS programmatically, you will use libraries that is build and maintained by AWS. [Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html) for python3 is such an example.
    

(You can also interact with AWS as an anonymous user. But for this scenario, I am not considering this.)

#### 2\. Authentication

Before interacting with AWS, you have to authenticate yourself - so that AWS can recognize who you are.

In case of console, the authentication process complete when you signin using account ID, IAM username, password and MFS.

When you are interacting with AWS programmatically using SDK and CLI, you need to use appropriate access key and secret key to authenticate yourself.

In case of IAM Role, it authenticates with temporary credentials, which are given by **AWS Security Token Service (STS)**. This service by default runs in every AWS region. Its job is to produce short time credentials to use by an IAM Role.

An IAM Role needs two resource-based policies when it is created. Trust Policy and Role Policy.

**Trust Relationship Policy**

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

For Lambda functions, you need to grant this permission to the Lambda service itself. The Principal element with Service set to [lambda.amazonaws.com](http://lambda.amazonaws.com) indicates that the AWS Lambda service is trusted to assume this role. The Action element with `sts:AssumeRole` specifies the action that is allowed. This setup ensures that only AWS Lambda can use this role, adding another layer of security by preventing other AWS services or users from assuming this role and accessing its permissions.

**IAM Role Policy**

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::example-bucket/*"
    }
  ]
}
```

The IAM Role Policy defines **what actions the Lambda function is allowed to perform**. In this example, the policy allows the Lambda function to read from and write to an specific S3 bucket.

In case of anonymous user, no authentication is required.

#### 3\. Building Request Context

Every request to AWS contains unique properties that is be provided along with an authorization request to make more granular authorization decisions. Till of this date there are total **18types** of request context parameters — account ID, authorizer principal ID, source IP, user aget, etc are such examples. IAM then compares this authorization context with to your IAM policies to determine which policy statements match.

In case you are curious and want to know more, read the [AWS documentation on request context](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_apigateway/RequestContext.html).

#### 4\. Evaluate Policies

Before understanding evaluaton process of the policies, its crucial to understand what is Root account and Organization Unit in AWS Organization.

**AWS Organization**

In a large organization, there might be multiple (sometimes hundreds/thousands) of AWS accounts for different use cases. For proper security, resource, and bill management, AWS offers the AWS Organization service. This service allows you to centrally manage and govern multiple AWS accounts. It simplifies billing by consolidating payments for all accounts under a single master account, known as the **Root Account**. AWS Organizations also enhance security and compliance by enabling you to apply **Service Control Policies** (SCPs) that define the services and actions each account can use. Additionally, it helps streamline workflows by allowing you to create **Organizational Units** (OUs), which are groupings of accounts that can be managed collectively based on similar requirements or functions. This hierarchical structure facilitates efficient resource management, policy enforcement, and cost tracking across the entire organization.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719191156209/8241c5c7-f400-4edf-a84a-e19ebd1577ac.png align="center")

For the example shown above, you can attach SCP policies directly to the Root Account, which will apply to all accounts under it. You can also attach SCP policies to a group of accounts by attaching it to OU. Additionally, it is possible to attach SCP policies to individual accounts.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719191898503/7f503360-2020-4091-a635-7109a044f6c9.png align="center")

For the simplicity of explanation and demonstration, we will abstract all the SCP policies into one.

**Policy Evaluation: IAM Role**

Now lets get to our IAM Role. An IAM role by itself does not make requests without a session. A role always has a corresponding session which is the principal that actually makes request.

The request is first evaluated against the SCPs defined at the organizational level. SCPs apply to all principals (users, roles, etc.) within the organization. These policies determine the upper limit of what actions are allowed or denied within the organization. The account context comes into play next, where the request is evaluated based on the policies specific to the account in which the resource resides.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719237198192/5e39fdb9-3fbe-49de-ac79-2c5b5a2036a2.png align="center")

Here when a request is invoked by a AWS Role Session, the role need to be allowed by multiple policies startign from organization's SCPs. If the role need to access a resource inside the same account then one of the following three policy chain will be evaluated accourding to the principal that is specified in the Resource-based Policy statment.

If the resource-based policy statement specifies principal for Accout, Role or Session then the policy evaluation path will be taken the followign 1, 2 or 3 respectively.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719448747184/602f0d70-7696-40be-b3f3-117fa3ff0702.png align="center")

If the request doesn't access any resource then the following policy chain will be evaluated.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719448411886/cb508be3-5a0e-4d94-bf58-8d13c8cc35b6.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💀</div>
<div data-node-type="callout-text">If any of the policy has Explicit Deny statement then the request will be denied, <mark>even if there is a path that allows the request</mark>.</div>
</div>

When the requested Role session originates from one account and the requested resource is in different account, then **all the policies need to approved** to access the resource.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719237749899/50eb14b2-4921-431b-a357-91d6135a3ecf.png align="center")

**Policy Evaluation: IAM User**

Till now we have understood the policy chain evaluation in case of AWS Role. But for other principals, the evaluation chain is different. For the completeness of the article, let's consider the AWS User principal in the following scenario.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719238606588/370072ca-33c2-4d0c-8920-e4494ac55dda.png align="center")

For request approval of an AWS User, all three session need to be evaluated. Note that the order of evaluation chain is different. It is evaluating Permission boundary policies before Identity-based policy. Rest of the structure is same as IAM Role.

**Policy Evaluation with VPC Endpoint**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719239372566/e4c793be-8b03-4cc2-b301-8ad243c12e51.png align="center")

In the previous examples, we assumed that there is no VPC endpoint service attached. If there is any VPC endpoint service, then the evaluation process of VPC endpoint policy will be after SCP, before getting access to the Account.

### Conclusion

Every API request in AWS is a multi-step journey involving authentication, building request context, collection, and evaluation of various policies. By understanding how each type of policy contributes to the final authorization decision for each type of principal, you can better manage and troubleshoot access controls in your AWS environment.
