AWS Identity and Access Management (IAM) is likely the first AWS service you’ll encounter when getting started on AWS, as it is Amazon’s authentication and authorization service.
Virtually all other AWS services depend on IAM because it provides the means to authenticate a user, machine, or service and verify that it is allowed to perform the operations it wants to perform. IAM is usually quite easy to navigate at first, but it does also offer advanced features that become increasingly complex.
In Part 1 of this two-part series, I’ll walk you through the basics on how to use IAM when beginning your AWS journey. First, identities…
AWS IAM Identities
A user is any identity that can be authenticated either with a password (when logging in to the AWS web console) or a set of keys (for programmatic access). A user can have IAM policies attached to it, which specify what operations the user can or cannot perform. A user can also be a member of a group (more on that later).
When you create an AWS account, you are identified via your email address. This ID is called a “root user” and has access to everything in your account. In contrast to “IAM users,” which can be created, modified, and deleted, root users are fixed and can’t be changed in any way, except by deleting the account.
For security reasons, when it comes to your root user ID, AWS highly recommends that you set a very strong password, enable two-factor authentication (2FA), delete the root user keys, create one or more IAM users with administrator privileges, and pretty much never use the root user again.
An IAM user can access the AWS web console by providing the account ID, user name, user password, and optionally a code from a two-factor authentication device (physical or virtual). I recommend that you set up a password policy adapted to your business: You can configure the minimum password length, what type of characters the password must contain, and how often you need to rotate the password. I also suggest you enable 2FA—it’s very easy to do and there are many free apps available for both Android and iOS that can provide a virtual 2FA device.
An IAM user can also access AWS through programmatic access via an AWS access key ID and a secret access key. These keys should be considered as secret as any other password, so please treat them accordingly, plus you can also enable 2FA for programmatic access. By using those keys, you can actually provide access to AWS from other services or machines outside AWS as well—it doesn’t have to be a human.
Programmatic access lets you access AWS APIs through AWS SDKs or awscli (the AWS Command Line Interface). Here’s how to configure programmatic access on your local machine:
$ aws –profile myprofile configure
I would strongly recommend that you use profiles when setting up and using programmatic access. I’ve had some mishaps, such as trying to access the wrong account to perform certain tasks, with potentially disastrous consequences. By ensuring that you have one profile for each account, you’ll protect yourself and your business from mistakes that could be very costly.
Are you a tech blogger?
A group is simply an entity a user can belong to, and, just like a user, a group can have IAM policies attached to it to specify which operations are allowed or denied. A user that is a member of a group will inherit those policies.
It should be noted that this is the extent of what groups can be used for. They can’t be used for any other purpose. In particular, they can’t be used as a principal in resource-based policies (which I explain a bit later).
An IAM role is essentially a user without credentials and is usually linked to an AWS service (e.g., an EC2 instance), although there are other use cases, like when a user “impersonates” a role to temporarily acquire a different set of permissions.
When attached to another AWS service, a role allows that service to perform certain actions. For example, it can allow an EC2 instance to access a DynamoDB table or a Lambda function to retrieve some parameters from the Systems Manager Parameter Store.
Whenever you can choose between a user and a role, you should most likely choose the role. For example, an ECS task can be given access to some secrets stored in Secrets Manager by using a user (i.e., by using an access key ID and a secret access key) or by using a role that is attached to the ECS task. In such a case, using a role makes more sense. There are a few reasons for that, but the most important one has to do with security. Indeed, if you want to remove permissions for some EC2 instances but not others, it’s much easier to remove a role from those EC2 instances rather than SSH-ing to each instance and locating and destroying any copy of the user credentials. If you want to be on the safe side, you will have to delete the user itself, but then the other EC2 instances you wanted to leave unaffected will stop having the required permissions.
A typical use case where you can’t avoid user credentials is when your code lives outside of AWS. For example, if you’re running an application on-premises or on another vendor’s cloud.
I should also note that an IAM role is, by design, restricted to a given AWS service. So, if you create a role that would apply to Lambda functions, you won’t be able to apply it to EC2 instances.
Learn how to protect yourself against web app security vulnerabilities in our guide to AWS WAF & AWS Shield.
AWS IAM Policies
IAM policies define what a principal can and cannot do in a series of “statements” with each statement specifying:
- One or more actions, which are actually the names of AWS API calls
- One or more resources, i.e., the object(s) of the action(s)
- An effect, which can be either “allow” or “deny”
- A principal, which identifies the actor, although identity policies don’t specify a principal (more on that below)
Different types of policies exist, depending on the type of entity they’re attached to, as I discuss below.
Identity-based policies are linked to “identity” objects, like users and roles. This is the type of policy you’re most likely to encounter and work with on a daily basis. A policy can be either “managed,” meaning it has an existence of its own, or “inline,” meaning it exists only within the remit of a given user or role.
Inline policies are useful when you want to ensure the policy disappears when the related user or role is deleted—and when you want to ensure the policy can’t be attached to any other identity. Otherwise, you’ll want to work with managed policies, also known as “customer managed policies” (because you, the customer, are managing them).
AWS offers a broad range of ready-made identity policies, called “AWS managed policies.” Unfortunately, these are usually very wide in scope and especially don’t constrain the resources they apply to, thus going against the principle of least privilege. They are useful as references to write your own policies, but I would generally recommend you don’t use them directly.
As mentioned previously, identity-based policies do not specify a principal because the principal is implicitly the identity they are attached to.
Resource-based policies are linked to AWS resources like KMS keys or S3 buckets. These policies do require a principal, which will be the user or role trying to execute a certain action toward that particular resource. Apart from the need to specify a principal and the fact that they are attached to resources rather than identities, resource-based policies are essentially identical to identity-based policies. So everything you learned about identity-based policies applies here as well.
The principal specified in resource-based policies can be:
- An AWS account (or its root user, it’s the same), which means “all users and roles in that other account”
- IAM users
- IAM roles
- AWS service(s); for example, a CloudWatch event calling a Lambda function
- Federated users (these are users that don’t exist in IAM but have been authenticated through another identity provider, such as Google, Facebook, or your corporate Active Directory setup)
- Anyone, meaning public access, which you generally never allow
Attaching Conditions to Policies
IAM does allow you to attach conditions to your policies, but this is an advanced topic that would require its own article. In brief, you can specify a condition that the user must have authenticated using MFA in order to perform a certain action or that the SAML account via which the user authenticated has certain properties with certain values.
You can also use conditions to implement attribute-based access control (ABAC). ABAC can allow or deny certain actions to certain users (or roles) based on the value of tags attached to the user/role and/or the value of tags attached to the target resource. For example, users with a tag “role: developer” can perform certain actions on resources with a tag “environment: dev,” and users with a tag “role: ops” can perform all actions on resources with a tag “environment” with values of either “dev” or “prod.”
Understanding at least the basics of IAM is an absolute prerequisite for using AWS, as almost all AWS services are linked to this service one way or another. As you’ve been able to see, AWS IAM seems quite simple at first, but it can actually get rather intricate even in covering the fundamentals, allowing you to craft complex policies to answer most conceivable use cases.
In Part 2 of this series, we’ll dive deeper and explore some advanced uses of IAM.