# IAM Policies and Data Access Control for AWS Data Services

> Chapter 10 of the Courseiva AWS-DATA-ENGINEER-ASSOCIATE curriculum — https://courseiva.com/learn/aws-data-engineer-associate/iam-data-access-control

**Official objective:** 3.1 — Implement identity and access management for data stores

## Introduction

Your company's most sensitive customer data — payment details, medical records, sales figures — could be accidentally deleted or maliciously stolen by a single wrong click. That is the real-world consequence of ignoring how to control access to data on AWS. For the DEA-C01 exam, you must prove you can write and attach IAM policies to protect data stores like S3, DynamoDB, and Redshift, so only the right people and services can touch the right data at the right time.

## The Stamped Letter Analogy

3 envelopes sit on your desk. One is addressed to your landlord, one to your doctor, and one to your friend. Each envelope has a specific stamp: a red 'PAID' stamp for the landlord's rent cheque, a blue 'MEDICAL' stamp for the doctor's appointment request, and a green 'PERSONAL' stamp for your friend's birthday card. You cannot send the birthday card with the 'PAID' stamp; the post office will reject it because the stamp doesn't match the letter's purpose. 

Now, 3 different people want to post letters through your letterbox. Your neighbour wants to post a parcel, the postman wants to deliver a bill, and your cousin wants to drop off a house key. You give each person a different coloured key to your front door. The neighbour gets a yellow key that only works between 9am and 5pm. The postman gets a blue key that only opens the letterbox flap. Your cousin gets a green key that opens the whole door. Each key is a 'policy' that says exactly what that person can do, with which item, and at what time. 

In AWS data services, you write these 'policies' to control who can read, write, or delete data in services like Amazon S3 or DynamoDB. A policy is a set of rules attached to a user or a service, defining the exact actions allowed on specific data resources. Just as your green key doesn't work on the letterbox, an IAM policy can say 'this user can only read files in this folder, and never delete them'.

## Core explanation

IAM stands for Identity and Access Management. It is a free service inside AWS that lets you create 'users' (people), 'groups' (collections of people), and 'roles' (identities for services) and then attach 'policies' to them. A policy is a formal document written in JSON (JavaScript Object Notation) — a simple text format with keys and values — that lists what actions are allowed or denied on which AWS resources. 

Think of a policy as a rule book. Each rule has three main parts: the 'Effect' (either Allow or Deny), the 'Action' (what you can do, like 's3:GetObject' which means read an object in S3), and the 'Resource' (exactly which bucket or table or file you can do it to). For example, a policy might say: 'Allow the action s3:GetObject on the resource arn:aws:s3:::customer-data-bucket/*'. The 'arn' is Amazon Resource Name — a unique address for every AWS resource. The '/*' at the end means 'any file inside this bucket'. 

Why does this matter for data services? AWS data services like S3 (Simple Storage Service — for files), DynamoDB (a NoSQL database — for fast key-value lookups), Redshift (a data warehouse — for big analytics queries), and RDS (Relational Database Service — for traditional SQL databases) all store your precious data. Without IAM policies, either everyone in your AWS account can access everything (dangerous) or nobody can access anything (useless). Policies give you fine-grained control. 

There are two main types of policies you need to know for DEA-C01: 
- Identity-based policies: These are attached to a user, group, or role. They say 'this identity can do X on resource Y'. 
- Resource-based policies: These are attached directly to the resource itself (like an S3 bucket policy). They say 'anyone who tries to access this resource must meet these conditions'. 

A common exam concept is the 'least privilege principle'. This means you should give a user or role only the exact permissions they need to do their job — no more. For example, a data analyst who only needs to run SELECT queries on a Redshift database should not have permission to DELETE tables. You write a policy that allows only 'redshift-data:ExecuteStatement' with a SQL action of 'SELECT' and deny all other actions. 

Another critical idea is 'conditions' in policies. A condition is an extra rule that must be true for the policy to apply. Common conditions include: 'IpAddress' (the user must be connecting from a specific IP range, like your office network), 'StringEquals' (the request must come from a specific AWS account), and 'Bool' (e.g., 'aws:SecureTransport' must be true — meaning the connection must use HTTPS). 

For data services, you often combine IAM policies with 'encryption' — protecting data by scrambling it so only someone with a key can read it. AWS Key Management Service (KMS) manages these keys. You can write a policy that says 'this role can decrypt data only if they are using a specific KMS key'. 

Finally, AWS evaluates policies using a logic called 'explicit deny overrides allow'. If one policy says 'allow read' but another policy says 'deny read', the deny wins — the user cannot read. This is a safety net to prevent accidental over-permissioning. 

In summary: IAM policies are your barrier and gatekeeper for all AWS data services. They define identities, attach rules, and enforce conditions so your data stays secure. On the DEA-C01 exam, you will be asked to read JSON policies, identify what they do, and choose the correct policy to meet a specific security requirement.

## Real-world context

An IT professional at a mid-sized e-commerce company, let us call her Priya, is responsible for setting up data access controls for a new analytics project. The company stores customer orders in an S3 bucket called 'orders-bucket', and a team of 5 data scientists need to read those files to build sales forecasts. 

Step 1: Priya logs into the AWS Management Console and goes to the IAM service. She creates a new IAM group called 'DataScientists'. She creates 5 IAM users (one for each scientist) and adds them all to this group. This is more efficient than attaching policies to each user individually. 

Step 2: Priya needs to write a policy that allows only read access to 'orders-bucket'. She opens the policy editor and writes a JSON policy that says: 
- Effect: Allow 
- Action: s3:GetObject, s3:ListBucket 
- Resource: arn:aws:s3:::orders-bucket/* (for GetObject) and arn:aws:s3:::orders-bucket (for ListBucket) 
She also adds a condition that the request must come from the company's office IP range (192.168.1.0/24) and must use HTTPS (aws:SecureTransport is true). 

Step 3: Priya attaches this policy to the 'DataScientists' group. Now every user in that group can list the files in the bucket and download them, but they cannot upload, delete, or change any files. 

Step 4: A few weeks later, the company starts using a new AWS Glue job (an extract-transform-load service that runs code automatically) to clean the data before the scientists use it. The Glue job needs write access to a separate 'staging-bucket'. Priya creates an IAM role (not a user — because services, not people, need this access) called 'GlueServiceRole'. She writes a policy that allows s3:PutObject and s3:GetObject on 'staging-bucket'. She attaches this role to the Glue job configuration. 

Step 5: An auditor later asks which users have access to sensitive payment data. Priya uses IAM's 'Access Analyzer' tool to generate a report showing all policies and their effective permissions. She discovers that an old admin user accidentally has full access to all S3 buckets. She removes that policy immediately. 

Key actions Priya performed: 
- Created IAM groups and users 
- Wrote a custom JSON policy with conditions 
- Attached policies to a group 
- Created an IAM role for a service 
- Used Access Analyzer for auditing 

This scenario is exactly what DEA-C01 expects you to understand: how to design policies for different identities (human users vs. automated services), how to use conditions to add security layers, and how to audit existing permissions.

## Exam focus

DEA-C01 tests IAM policies and data access control heavily, usually as part of multiple-choice questions where you need to analyse a policy JSON or choose the correct policy for a given scenario. Here are the specific areas they love to test: 

- Policy evaluation logic: Expect at least one question where they give you two policies attached to the same user — one allows, one denies — and ask what the effective permission is. The answer is always 'Deny' because explicit deny overrides allow. Trap: beginners think the most specific policy wins, but it is the deny that always wins. 

- Resource-based vs. identity-based policies: They will give you a scenario like 'a user in Account A needs to read data from an S3 bucket in Account B'. The correct answer is that you need both: an identity-based policy on the user (or role) in Account A allowing s3:GetObject, AND a resource-based policy (bucket policy) on the S3 bucket in Account B that allows the Account A user's ARN. Trap: candidates only set one policy and think that is enough. 

- Conditions: Questions will include conditions like 'IpAddress' or 'StringEquals'. You must know that 'IpAddress' checks the source IP, and 'StringEquals' checks exact string matches (like a specific AWS account ID). Trap: they might include a condition that seems logical but uses the wrong condition key (e.g., using 'StringEquals' for an IP range, which would fail). 

- Least privilege principle: They will describe a role that needs only read access to a DynamoDB table and ask for the correct policy. The correct answer will have only 'dynamodb:GetItem' and 'dynamodb:Query' actions, and the resource will point to the specific table ARN. Trap: a distractor answer will list broader actions like 'dynamodb:*' or forget to specify the resource, effectively granting too much access. 

- IAM roles vs. IAM users: You will be asked 'should you create a user or a role for an EC2 instance that needs to access an S3 bucket?'. The answer is always a role, because roles are designed for AWS services. Trap: a distractor says 'create a user and store the access key on the instance' — that is insecure and against best practice. 

- S3 bucket policies specifically: They love to test the difference between a bucket policy that grants public access (Principal: '*') and a policy that restricts access to a specific IAM role. Public access is almost never the correct answer for data security questions. Trap: they might phrase the question as 'allow anyone to read objects' but include a condition that looks secure but is not. 

- Encryption and KMS: A common question type is 'a user gets an access denied error when trying to read an encrypted S3 object even though they have s3:GetObject permission'. The answer is that the user also needs kms:Decrypt permission on the KMS key. Trap: candidates forget that IAM policies on the key itself (KMS key policies) must also allow the user. 

- Policy structure: You must be able to read a JSON policy and identify the Effect, Action, Resource, and Condition blocks. They may present a malformed policy (missing a required field) and ask what is wrong. Trap: a policy without a 'Principal' field is fine for identity-based policies but required for resource-based policies. 

- Cross-account access: Expect a question about granting access to a user from another AWS account. The correct approach is to create a role in the target account with a trust policy that allows the external account to assume that role. Trap: candidates try to attach a policy directly to the external user, which does not work across accounts without a role. 

Key definitions to memorise: 
- ARN (Amazon Resource Name): the unique identifier for any AWS resource 
- Principal: the entity (user, role, service) that the policy applies to 
- Effect: Allow or Deny 
- Action: the specific API call (e.g., s3:PutObject) 
- Resource: the ARN of the resource 
- Condition: an optional block that adds extra requirements 
- STS (Security Token Service): the service that issues temporary credentials when you assume a role

## Step by step

1. **Define the identity** — Decide who or what needs access. If it is a human, create an IAM user or add them to an IAM group. If it is an AWS service like an EC2 instance or a Lambda function, create an IAM role. The identity is the 'who' in the access control equation.
2. **Identify the data resource and required actions** — Determine exactly which AWS data service the identity needs to access (e.g., an S3 bucket called 'sales-data', a DynamoDB table called 'Users', or a Redshift cluster). Then list the specific API actions required (e.g., s3:GetObject to read, dynamodb:Query to search items). This step follows the least privilege principle.
3. **Write the policy JSON** — Open the IAM policy editor and write a JSON document. Include a Statement block with Effect (Allow or Deny), Action (the list of API calls), Resource (the ARN of the data resource, often with a wildcard for sub-resources like files inside a bucket), and optionally a Condition block (e.g., IpAddress or Bool). Use the ARN format arn:aws:s3:::bucket-name/* for all objects in a bucket.
4. **Attach the policy to the identity** — If you wrote an identity-based policy, attach it to the IAM user, group, or role under the 'Permissions' tab. If you wrote a resource-based policy (like an S3 bucket policy), go to the resource's settings (e.g., S3 bucket > Permissions > Bucket Policy) and paste the JSON there. This step enforces the rules you wrote.
5. **Test and audit the access** — Use AWS's IAM Access Analyzer or the 'Policy Simulator' tool to test what actions the identity can actually perform. This step catches mistakes like missing conditions or incorrect ARNs. Regularly review policies to ensure they still follow least privilege as roles change over time.

## Comparisons

### IAM User vs IAM Role

**IAM User:**
- Represents a person with a long-term password or access key
- Best used for individual human beings or applications with static credentials
- Cannot be assumed by AWS services directly

**IAM Role:**
- Represents a set of permissions with temporary credentials from STS
- Best used for AWS services like EC2, Lambda, or Glue
- Can be assumed by both users and services via trust policies

### Identity-based Policy vs Resource-based Policy

**Identity-based Policy:**
- Attached to a user, group, or role
- Controls what actions the identity can perform across all resources
- Does not require a Principal field

**Resource-based Policy:**
- Attached to the resource itself (e.g., S3 bucket)
- Controls who can access that specific resource
- Requires a Principal field to specify who is allowed

### S3 Bucket Policy vs IAM User Policy (S3 Access)

**S3 Bucket Policy:**
- Resource-based, attached to the bucket
- Can grant access to users from other AWS accounts
- Evaluated before IAM user policies for the same bucket

**IAM User Policy (S3 Access):**
- Identity-based, attached to a user
- Only applies to the user it is attached to
- Cannot grant cross-account access alone; needs a resource-based policy

### Allow Effect vs Deny Effect

**Allow Effect:**
- Permits a specific action on a resource
- Multiple Allows can stack to grant broader permissions
- Overridden by an explicit Deny on the same action

**Deny Effect:**
- Blocks a specific action on a resource
- A single Deny overrides all Allows for that action
- Used as a safety measure to prevent accidental over-permissioning

### Action: s3:GetObject vs Action: s3:*

**Action: s3:GetObject:**
- Grants read access only to individual S3 objects
- Follows the least privilege principle
- Safe for users who only need to download files

**Action: s3:*:**
- Grants all S3 actions including delete, put, and list
- Violates least privilege principle
- Risky for any user who does not need full administrative access

## Diagram

_This flow chart shows how IAM users and roles, with their identity-based policies, and resource-based policies (like S3 bucket policies) are all evaluated together to either allow or deny access to AWS data services._

```mermaid
flowchart TD
    A[IAM User (Human)] --> B[Identity-based Policy]
    C[IAM Role (Service)] --> D[Identity-based Policy]
    B --> E{Policy Evaluation}
    D --> E
    F[S3 Bucket Policy (Resource-based)] --> E
    G[DynamoDB Table Policy] --> E
    E --> H[Allow Access]
    E --> I[Deny Access (if any explicit Deny)]
    H --> J[Access Data Services]
    I --> K[Access Denied]
```

## Common misconceptions

- **Misconception:** An IAM policy attached to a user automatically applies to any AWS service that user accesses, regardless of the resource. **Reality:** An IAM policy only applies to the resources explicitly listed in the policy's Resource field. If the resource is not mentioned, the action is denied by default. (Beginners think IAM is a blanket permission system, but it is resource-specific. Without specifying the resource ARN, the policy gives no access.)
- **Misconception:** If you have both an Allow and a Deny policy, AWS chooses the one that is more specific. **Reality:** AWS's evaluation logic always prioritises an explicit Deny over any Allow, regardless of specificity. The Deny always wins. (This comes from real-world IT where a deny override is a safety feature to prevent accidental over-permissioning. It is counter-intuitive because specificity often wins in other contexts.)
- **Misconception:** An S3 bucket policy and an IAM user policy are interchangeable and achieve the same thing. **Reality:** A bucket policy is resource-based and controls access to the bucket itself, including from other accounts. An IAM user policy is identity-based and controls what that user can do across all services. They work together but are not interchangeable. (Because the exam often gives one or the other in a scenario, and candidates pick the wrong one because they do not understand the difference between identity-based and resource-based.)
- **Misconception:** IAM roles are only for human users who need temporary access. **Reality:** IAM roles are primarily used for AWS services (like EC2, Lambda, or Glue) to grant them permissions. Human users can assume roles, but the main purpose is to give AWS resources permissions to act on your behalf. (The name 'role' sounds like something a person would 'play', so beginners associate it with humans, not machines.)
- **Misconception:** A condition in a policy is optional and rarely used in practice. **Reality:** Conditions are extremely common and powerful. They are used to enforce IP address restrictions, require HTTPS, enforce encryption, and much more. The exam tests them frequently. (Beginners focus on the core Effect-Action-Resource structure and skip reading about conditions, missing a major exam topic.)
- **Misconception:** If a user has s3:GetObject permission, they can always read any S3 object in the bucket. **Reality:** If the object is encrypted with a customer-managed KMS key, the user also needs kms:Decrypt permission on that key. S3 permissions alone are not enough for encrypted objects. (Candidates forget that encryption adds another layer of access control beyond the data service itself.)

## Key takeaways

- An IAM policy is a JSON document that defines the Effect (Allow or Deny), Action (specific API call), Resource (ARN of the target), and optional Conditions that must be met.
- The explicit Deny in any policy always overrides any Allow, making Deny the ultimate safety mechanism in AWS access control.
- Resource-based policies (like S3 bucket policies) are attached to the resource itself, while identity-based policies are attached to a user, group, or role.
- To grant cross-account access to an S3 bucket, you must configure both a bucket policy (resource-based) in the target account and an IAM role (identity-based) in the source account.
- When an S3 object is encrypted with a customer-managed KMS key, the user needs both s3:GetObject and kms:Decrypt permissions to read the object.
- IAM roles are designed for AWS services like EC2, Lambda, and Glue, not for human users; they use temporary credentials from AWS STS.
- The least privilege principle means you should grant only the exact actions and resources a user or service needs — never use wildcard (*) actions or resources unnecessarily.
- Conditions in policies can restrict access based on IP address, time of day, encryption in transit (HTTPS), and many other factors.

## FAQ

**What is the difference between an IAM role and an IAM user in AWS?**

An IAM user represents a person with a long-term password or access key. An IAM role represents a set of permissions that can be assumed temporarily by an AWS service or a trusted user, using temporary credentials from AWS STS.

**How do I give a user in another AWS account access to my S3 bucket?**

You need to do two things: create a bucket policy on your S3 bucket that allows the external user's account principal, and have the external account create an IAM role with a trust policy that allows their user to assume it.

**What does 'Action': 's3:*' mean in an IAM policy?**

It means the identity is allowed to perform every possible action on S3 (read, write, delete, list, etc.). This violates the least privilege principle and is generally not recommended for security.

**Why do I need a condition in an IAM policy?**

Conditions add extra security requirements that must be met for the policy to apply, such as requiring the request to come from a specific IP address or use an encrypted connection. They help prevent unauthorised access even if the policy is attached to the wrong user.

**Can I attach an IAM policy directly to an S3 bucket?**

Yes, but that is called a bucket policy — it is a resource-based policy. Identity-based policies are attached to users, groups, or roles. Both types can coexist for the same bucket.

**What happens if one policy says Allow and another policy says Deny for the same action?**

The Deny always wins. AWS evaluates all policies and if any explicit Deny applies to the request, the action is denied regardless of any Allow from another policy.

## Check your understanding

1. **What is the evaluation outcome when one IAM policy allows s3:GetObject but another policy explicitly denies s3:GetObject for the same user?**

   Answer: The action is denied because an explicit Deny always overrides any Allow in AWS policy evaluation logic.

2. **If an S3 object is encrypted with a customer-managed KMS key, what additional permission must an IAM user have beyond s3:GetObject to read the object?**

   Answer: The user must also have the kms:Decrypt permission on the specific KMS key that encrypted the object.

3. **What is the difference between an identity-based policy and a resource-based policy in terms of where they are attached?**

   Answer: An identity-based policy is attached to a user, group, or role, while a resource-based policy is attached to the AWS resource itself, such as an S3 bucket.

4. **To grant cross-account access to an S3 bucket, which two policy types must be configured?**

   Answer: You need a resource-based policy (bucket policy) on the target bucket and an identity-based policy on the IAM role in the source account (or a trust policy that allows the external account).

5. **Why should an IAM role be used instead of an IAM user for an EC2 instance that needs to access S3?**

   Answer: An IAM role provides temporary credentials via AWS STS and avoids the security risk of storing long-term access keys on the instance.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/aws-data-engineer-associate/iam-data-access-control
