AWS identity and access management
Tags: aws, serverless, security, cloud
Published: 2021-10-06 08:04:12

*From the basic to advanced concepts of AWS own service for identity and access management: users, groups, permissions for resources and much more.*

For seriously working with AWS, there's no way around its Identity and Access Management (IAM) service. Skipping to understand its core principles will bite you again and again in the future️.

Take the time to do a deep dive, so you won't be frustrated later.

Overview of the topics to cover:

-   IAMs Capabilities
-   Key Terms
-   Identity- & Resource-based Policies
-   Securing your AWS Account
-   Basics: Credentials & AWS CLI
-   Dealing with "Access Denied"
-   Least Privilege
-   Permission Boundaries
-   Tooling

IAMs Capabilities
-----------------

Personally, IAM is the most outstanding AWS core service, with an endless list of features that are well-integrated into the whole service landscape.

A small, non-exhaustive list of those features:

-   managing users for your AWS account, with individual rights and/or temporary access
-   enforcing password policies or Multi-Factor Authentication
-   setting rights boundaries for AWS services & your apps
-   identity federation

Take your time to get to know the basics is crucial.

Key Terms
---------

Starting with IAM can cause you to feel overwhelmed, alone due to its huge vocabulary. Let's cover the fundamental concepts you will work with on a daily basis.

-   User - an end-user, accessing the console, AWS API, or both.
-   Group - a group of users, sharing the same privileges and permissions.
-   Policy - a defined list of permissions, specified as JSON.
-   Role - a set of policies, that can be assumed by a user or AWS Service to gain those permissions.

### Policies

At AWS IAM, everything evolves around Policies.

By default, all actions for all services are denied, so you have to explicitly grant rights by adding a policy with your targeted actions and resources to your service role, user, or group.

You can attach one or multiple policies to a role and each policy can contain one or multiple *Statements*.

### Statements

Statements contain the permissions you want to grant and are structured in a specific way, defined as a JSON.

An important detail about policies: they come in two different types.

- Identity-based - attached to a user, group, or role.

- Resource-based - attached to a resource, e.g. S3 bucket, SQS queue, or KMS key.

Let's have a look at what a Statement must contain

- Effect - the indication if it's *Deny* or *Allow*.

- Action - a list of actions.

- Resource - a list of resources for which the actions are granted.

For resource-based policies, Resouce is optional. Resource-based Policies also need to define a *Principal*. It indicates for which account, (federated) user, or role user you'd like to allow or deny access.

There are more specifics for this type of policy like they aren't being affected by permission boundaries

If you got to this point, your IAM knowledge foundation is laid.

Securing your own AWS account
-----------------------------

It's not recommended to work with your root credentials. Those should only be used to enable MFA, create your first IAM user, and should then be locked away securely.

Go to your [security page](https://console.aws.amazon.com/iam/home?#security_credential) & select **Manage MFA Device**. You can use an authentication app of your choice.

> 💡 If there's already an Access Key, you can delete it as you shouldn't work with your root credentials in any way.

Afterward, you can create your first user by clicking on **Users > Add User**. You can make use of AWS' predefined policies in the first place.

If you're working on a serious project, make sure to use groups to manage rights across different roles easily.

After creating your user with enabled console access, you can now log out with your root user and log back in with your IAM user.

> 💡 Note down your AWS' account identifier on the top right before logging out, because it's needed for the IAM user login.

Credentials
-----------

For accessing AWS' API to maintain your infrastructure via code, we'll need credentials.

Go back to your security credentials page and click **Create Access Key** to get your `Access Key ID` & `Secret Access Key`.

> 💡 There's no way to display the Secret Access Key again, but you can create a new one at any time.

AWS' Command Line Interface
---------------------------

Now that we've got our credentials, we can install the [AWS CLI](https://aws.amazon.com/cli/). After installation, you can run `aws configure` for doing our initial setup.

You'll be prompted for credentials (which we received in the previous step) and some default settings.

> 💡 When working with different accounts and/or roles and enabled MFA, it's recommendable to get some tooling support. I love working with [AWSume](https://awsu.me/) in this case. It's easy to set up and really intuitive to work with.

Handling "Access Denied"
------------------------

Working with AWS, especially in the beginning, you'll face this message regularly. Mostly, AWS' API will point you to missing permissions so you can easily extend your policy.

Sometimes it's not that easy and you'll need to get back to the docs.

What you should not do: just extending your policy with all permissions for your target service by adding e.g. `ᴀᴄᴛɪᴏɴ: ["dynamodb:*"]` and `ʀᴇꜱᴏᴜʀᴄᴇ: ["*"]`

You won't learn anything by that and you're not respecting the rule of *Least Privilege*.

Least Privilege
---------------

Least Privilege states that you should always just assign the permissions that are actually needed for the service to fulfill its goals.

Example: An app that runs on Lambda and now needs access to a recently created DynamoDB table.

The easiest way would be to just create a policy that grants full permissions to DynamoDB and attach the role to your Lambdas role.

But that's not a good solution, because our app just needs to have read & write permissions for a single table.

How can we improve?

### Restricting actions

We don't manage tables, so we shouldn't grant `DeleteTable`.

What we need:

-   `Query`
-   `GetItem`
-   `PutItem`
-   `UpdateItem`

You'll always find all permissions in the [docs](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html)!

### Restricting resources

As we're only working with a specific table, we can really fix the permissions to be only valid for this single table by listing the ARN.

`arn:aws:dynamodb:𝙍𝙀𝙂𝙄𝙊𝙉:𝘼𝘾𝘾𝙊𝙐𝙉𝙏_𝙄𝘿:table/𝙏𝘼𝘽𝙇𝙀_𝙉𝘼𝙈𝙀`

Sounds complicated?

For enforcing least privilege, you'll need to fiddle around with ARNs a lot.

Maybe this sounds tedious, but if you start working with *Infrastructure as Code* (IaC) tools like Terraform, CloudFormation, or AWS CDK, this is really easy & comfortable!

Regardless of what you're using, all tools will create output variables for your created resources that include all the references you need, like for example the ARN.

You can create other resources that depend on those.

That's not the end of IAMs capabilities.

Permission Boundaries
---------------------

AWS' *Permission Boundaries* help you to restricted effective permissions for a user or role.

They also contain policies that describe actions and resources, but they are acting as an outer boundary.

What it means: the actually attached permissions can never exceed the boundary!

So if your boundaries only list `dynamodb:query` for all resources, a role with `dynamodb:*` can't update or delete items, but only query!

What is it good for?

Boundaries can be defined in one place but re-used across all of your account's roles and users.

By that, you could for example strictly separate an app's permissions to only access resources with a given name prefix, but having multiple apps within your account.

You can also use your boundary policy not only as a boundary but as actual permissions, for example for your CI/CD service/tool like CodeBuild.

By that, you'll automatically grant all necessary rights, but still with respect to the boundary.

Important details about boundaries policies:

- if used as a boundary, they are not actually granting permissions, but only restricting them!

- there's **no effect** on resource-based policies, e.g. for your S3 bucket!

There are a lot more features that IAM offers and this was just an introduction with some general recommendations, but it will be enough to get you started.

Tooling
-------

For following security best practices, there's also a lot of tooling you can fall back to.

### [AWS Trusted Advisor](https://aws.amazon.com/premiumsupport/technology/trusted-advisor)

It reviews your permissions for unnecessary rights or best practice violations and checks that you've enabled AWS security features for your services and resources.

### [AWS Policy Simulator](https://policysim.aws.amazon.com/)

It greatly helps to build, validate and troubleshoot your policies. It supports identity-based, resource-based, and even Organizations service control policies.

### Third-Party services

There are a lot more third-party services guiding you with security recommendations & Well-Architected tips like [dashbird.io](http://dashbird.io/).

![](https://miro.medium.com/max/1400/1*w4cEScYqHiL5V3m-jvgKuQ.png)

Final words
-----------

Completely mastering AWS Identity and Access Management is more of a holy grail, as it's a complex topic and there will always be days where you're stuck on some permissions issue, regardless of your experience.

But it gets a lot easier with time.

* * * * *

Further reading:

[How I manage credentials in Python using AWS Secrets Manager](https://dashbird.io/blog/aws-secrets-manager-python/)

[Secure your data with serverless access points](https://dashbird.io/blog/how-to-secure-your-data-with-serverless-access-points/)

[Well-Architected Framework in serverless: Security Pillar](https://dashbird.io/blog/well-architected-framework-security/)

[Debugging with Dashbird: Lambda not logging to CloudWatch](https://dashbird.io/blog/lambda-not-logging-to-cloudwatch/)