Not Just Another AWS Identity and Access Management (IAM) Tutorial

Many teams starting with AWS begin their journey by spending more time on the underlying service like EC2, lambda, etc. While this is understandable, it is important to know that for an enterprise-grade deployment a critical point to invest in early on is the Identity and Access Management (a.k.a. IAM). Not sure why? Read along. In this tutorial, we will go over IAM basics, users, groups, roles, policies and some key best practices. In fact, IAM is such an important service for Architects and deployment admins that spending more time understanding it is well worth.

IAM Overview

Let’s first understand what IAM is and what value it offers? Simply put, IAM is the gatekeeper of your AWS deployment. It helps manage the following.

(Image courtesy of AWS)
  • Firstly, it is a Global service. This means you would typically do IAM setup only once even if you have a multi-region deployment.
  • IAM facilitates management of Users and Groups.
    • A user could be a real-world user or a pseudo user created for application purpose, such as a user created for application usage.
    • A group is a collection of like users.
  • IAM supports several authentication capabilities from basic password-based authentication to integrating with an identity provider, such as your corporate Active Directory.
  • IAM offers controlling access to resources via Policies. Think of a policy as an authorization letter. Only the specified access will be granted. This means unless you granted access in the policy, the access will not be provided.
  • IAM also offers an advanced entity called Role, which is again used to control access to AWS resources. A role cannot make direct AWS service requests. But, it is typically used by an IAM user or an AWS service. This is often referred to as the assume role capability. For example, a role can be assigned to an EC2 instance that will control which all AWS resources that instance can access. This helps in avoiding storage of sensitive AWS keys on the EC2 filesystem thus making a more secure deployment. Don’t worry if this part is not clear. We will talk about it again in this tutorial.

Getting Started with IAM

Now that we understand the IAM basics, let’s go over how to get started with IAM. Assuming you have already signed up for an AWS account, follow these key steps to start using IAM.

Create an Admin IAM User (and potentially other IAM users)

  • Login to AWS with your root account and launch IAM from the Services menu. This is the account that was used to sign up and create the AWS account. 
  • If you have not done any IAM setup, your IAM console would look similar to the screenshot below. As you complete IAM setup, the dashboard will start reflecting the progress.
  • Create an admin IAM user that will be used for further setup. If you expect to have more than one admins, create an admin group first and assign users to it.
    • Assign the builtin AdministratorAccess managed policy to this user/group.
      Note: Even though this user is an administrator, it still will not have billing access. By default, the billing access is only available to the root account unless explicitly granted to other users or groups.
  • Create additional IAM groups/users, as needed.
  • Following are the steps to create an IAM Group.
    Note: Only attach the necessary policies to a given group.
  • Following are the steps to create an IAM User.
    • Some key guidelines to follow while creating users.
      • Think of users as all possible actors in the system. This could be real-world users, system users (required by your application) and other users required for purposes like automation, DevOps, security scans, etc.
      • Use a strong password.
      • Grant only the type of access that is needed for the user. For example, a DevOps or system user does not need to have console access typically.
      • If you used generated password, make sure to copy it to use later.
      • If you granted programmatic access, make sure to grab the access and secret keys. You will not have another opportunity to get these. However, you can always create another set of keys later.
      • Only attach the necessary policies.
      • When using groups, attach policies to groups and avoid attaching policies directly to users. Instead, assign users to the appropriate groups.
  • IAM also offers a neat capability to create a custom sign-in URL. While this is not necessary, it could be helpful in creating a more intuitive sign-in URL for your organization.

Start using the IAM users from this point

Once you have the basic IAM setup done, start using the IAM users. Avoid using the root account directly as much as possible. As you make progress, you will invariably come back to IAM to manage resource access, users and so on. Hence it is important that you keep the IAM setup as clean as possible and avoid sprawl. IAM plays a critical role in the security of your deployment. Hence, it is a good idea to be as conservative as possible.

Understanding an IAM Role

What is an IAM role and why is it so important? How is it different from an IAM user or an IAM policy? If these questions come to your mind (even after having used IAM role a bit), it’s fine. At the outset, the purpose and benefits of an IAM role may not be as obvious. So, let’s take a few use cases to understand why is a role there in the first place.

  1. Controlling access to AWS resources for an application running on an EC2 instance: You are creating an EC2 instance that will host an application which should be able to publish logs to CloudWatch and use S3 for files. Sounds pretty common, right? But, how do you go about it in a deployment? There are 2 options.
    1. Create a user for the application only with the required policies and store its access and secret keys in the AWS credentials file. When the application comes up, the AWS SDK will retrieve these keys at runtime and the application will be able to access the AWS resources. So, what’s the issue? The issue is the storage of credentials on the filesystem. While it may not be obvious, access to any sensitive data is a security risk. For example, anyone who can access this EC2 instance could potentially grab the keys and cause a security issue.
    2. The other option is to create an IAM role and attach the required policies to it. When creating the EC2 instance, assign it this IAM role (in the “Configure Instance Details” section). No need to create an application user and keys. Simple! The instance will have access to the desired resources and no sensitive data is stored. This is one of the best ways to handle security.
  2. Controlling access to AWS resources used by a serverless application using lambdas: Similar to the use case above, you could use both the options here. Again using the role-based option is better as you do not need to bake the credentials in your lambda distribution keeping it more secure and clean.

How does a role work and why is it better?

A consumer entity (such as a user or a service like EC2) assumes the role at runtime. At this point, a set of temporary credentials (a.k.a token) are generated (by the Simple Token Service (STS)), which are used to sign the requests to the AWS services. This is generally transparent to the consuming entity.

As we can see from the use cases above, a role is somewhat similar to a user in the sense that it controls access to AWS resources. But, it is also important to understand some key ways in which it differs from an IAM user.

  • An IAM user uses long-term credentials whereas a role uses temporary credentials that are valid for a much shorter duration. Once the credentials expire, these cannot be reused.
  • Unlike IAM user keys, you do not have to distribute these.
  • A role by itself cannot make requests to AWS resources.
  • And, as we saw earlier, these temporary credentials are not available on the filesystem thus eliminating the security risk of someone grabbing these from the disk.

Are there any limitations of a role?

So, everything so far sounds great about an IAM role. But, what are some of the limitations? As an Architect and Application Designers, we often deal with things that are not deployed in the cloud even if the application itself may be running on the cloud. For example, you may have a DevOps system that has to deploy the stack in AWS or a monitoring process that periodically analyzes the CloudWatch Logs. In such cases, you will invariably end up having one or more IAM users that are used by such components. The key point being, an IAM role is only good for components that are running inside the AWS cloud. If you have components in your deployment (or supporting your deployment) that live outside of AWS and requires access to the AWS resources, you will set up IAM user(s) for these.

Understanding IAM Policies

A discussion on IAM would be incomplete if we did not talk about policies. I mentioned earlier, a policy is like an authorization letter in which you tell which all actions are permitted on what resources. AWS offers several out-of-the-box policies (a.k.a. Managed Policies). In addition, you can write your own custom policies (a.k.a. Customer Managed Policies) tailored to meet specific needs. Why would you do that? Can you guess? Tick… Tick… Tick… Perhaps you got it – when AWS Managed Policies do not meet your needs. Remember that as a rule of thumb you should only grant the required access to AWS resources. This is not always as obvious. It requires patience and attention to detail. But, IMHO it is worth it. Let’s take our earlier EC2 example wherein we want the application running on the EC2 instance to be able to publish logs to CloudWatch and put/get files from S3. The following custom policy called “MyAppAWSAccess” shows one way of doing this.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogStreams"
      ],
      "Resource": [
        "arn:aws:logs:*:*:*"
      ]
    },
    {
       "Effect":"Allow",
       "Action":[
          "s3:ListAllMyBuckets"
       ],
       "Resource":"arn:aws:s3:::*"
    },
    {
       "Effect":"Allow",
       "Action":[
          "s3:ListBucket",
          "s3:GetBucketLocation"
       ],
       "Resource":"arn:aws:s3:::myappbucket"
    },
    {
       "Effect":"Allow",
       "Action":[
          "s3:PutObject",
          "s3:GetObject"
       ],
       "Resource":"arn:aws:s3:::myappbucket/*"
    }
  ]
}

Let’s walk through this.

  • A policy document uses JSON format.
  • The Version specifies the policy language version.
  • A policy is essentially a collection of statements where each statement specifies the following.
    • Effect: Whether the policy allows or denies that specific access.
    • Action: The list of actions allowed/denied.
    • Resource: The list of resources on which the actions apply. Some actions let you specify more granular resources (such as the s3:PutObject action on a specific bucket). Other actions are global in nature (such as s3:ListAllMyBuckets).
    • A statement can also have additional fields, such as “Sid” (or a statement id).
  • We have 4 statements in our policy that do the following.
    1. The first statement grants access to create LogGroup, create LogStream, put Log Events and obtain the Log Streams. As you may have noticed, this does not grant access to get the Log Events. That is intentional. Because we do not expect our application to read the logs. It only intends to publish logs. This thought process is very important when you design IAM policies – only grant the needed access.
    2. Statement#2 provides access to list all buckets. This is needed due to the way S3 access works. You cannot simply grant access on the bucket. You have to be first able to reach the bucket.
    3. Likewise, statement#3 also helps in reaching till the bucket (again due to the way S3 access works).
    4. The last statement specifies that put and get are allowed on a specific bucket – myappbucket. This is an example of how to grant access to a specific resource. If an entity with which this policy is associated tries to do a get on another S3 bucket, it will be denied access.

In this discussion, we have only scratched the surface of IAM policies. But hopefully, this gives you an idea of how powerful this capability could be to make your deployment more secure and robust.

IAM Best Practices

There are several best practices for IAM. But, here are some key ones to follow.

  • Minimize the use of root account. Use it primarily to set up the initial IAM admin user. In fact, set up an MFA (multi-factor authentication) on the root account as an additional layer of security.
  • Restrict the sharing of root account credentials.
  • Restrict the sharing of IAM admin user credentials.
  • You should only club like users in the same group. Put another way, just because two totally different types of users require similar permissions don’t just assign them to the same group.
  • Grant only required permissions via the IAM policies. Many times it is easier to add permissions than to revoke later.
  • Review your IAM setup periodically and optimize as necessary. For example, delete obsolete users, update permissions, etc.
  • Prefer using an IAM role over an IAM user wherever possible.

Additional Reading

 

Happy learning!
– Nitin

 

Enhance your AWS skills with these hands-on courses for real-world deployments.

Learn AWS basics for FREE.

Learn practical application development on AWS.

 


Also published on Medium.

Leave a Reply

Your email address will not be published. Required fields are marked *