Skip to content

AWS

IAM Users are a bad Idea

Image

Try the Cringy Podcast format of this post (NotebookLM):

Hallucinations are present in the AI generated Podcast

In AWS, IAM Users are just about everywhere, often seen as the primary means of ingress to an AWS environment, be it for getting access to the AWS Console, giving some sort of system access to AWS Resources, or setting up an automated workflow with AWS. If you've spent any amount of time tinkering on AWS, you will have, no doubt, seen countless tutorials, or forum examples on how to configure access to your environment utilizing IAM Users. Any time you see a the requirement for an ACCESS_KEY_ID or a SECRET_ACCESS_KEY, this implies that an IAM User is being used.

What's the problem with IAM Users

The problem...? Well, by nature IAM Users have long-lived access at whatever permission level is specified in the policies attached to that user. This means that by default, no matter the conditions, whatever systems make use of an IAM User's access keys, those systems will always need access at the level specified. Move the system to a new host? Access remains unchanged. Now, I know that there are work-arounds for this, where you can use Condition Statements in your IAM Policies to somewhat control the conditions for the permissions specified, but, this does assume, people are writing their own policies instead of simply using AWS Managed Policies, or copying them from ChatGPT.

It is also really hard to manage MFA Enforcement for IAM Users as an account wide policy. I believe that MFA should be enforced for any human users whenever they take action in AWS Accounts that I manage - regardless of access level. Although IAM Users can with relative ease make use of MFA, enforcing it, whilst allowing users to manage their own MFA Devices is challenging. If you get that right, its also significantly more complex present your MFA device when using the CLI.

Use IAM Roles wherever you can

Roles offer a far-superior mechanism for managing the permission scope (Attached Policies) and the "Who/What" and "Under what conditions" these permissions can be used (Trust Policy). This will hopefully help you avoid a lot of unnecessary risk exposure, if done right.

Don't Underestimate the importance of a Well-Defined Trust Policy

Most people put a lot more thought (if any) into the specific permissions applied to a role, when I would argue that it is more important to properly define Who or What and under What conditions the role may be assumed. I would feel far more comfortable giving my Terraform deployment role AdministratorAccess provided that I very carefully define which branch of which repository the Action Runner is allowed to run from to access the role, compared to if I had carefully scoped out very specific permissions, but left the Trust Policy vague.

TLDR

To avoid running on endlessly about why I don't much like IAM users, I have added summarized my dislikes regarding IAM Users below.

  • MFA Enforcement is challenging, and the use thereof is complicated with the CLI.
  • Access granted through IAM Users is permanent by default.
  • Access Keys need to be regularly rotated.
  • IAM Users are limited to 1 Account (yes, cross account roles are a thing, but they are gross).
  • In multi-account AWS Organizations, IAM Credentials need to be maintained in each individual account.
  • Unused Keys need to be deleted.
  • Handling Access Keys is risky.
  • In most cases, there are simply better ways to handle access to your aws environment than using IAM Users.

I will explore below some examples of ways to replace IAM Users in your AWS Estate.

For the Humans - IAM Identity Center

AWS Identity Center (formally AWS SSO) is AWS' implementation of Enterprise Single Sign-On, and allows you make use of temporary role-based access when assigning access to users in your AWS Estate. Identity Center can be configured to work in both the context of an AWS Organization or in a single AWS Account - although it is definitely optimized for an organization. Some of the features I really like are summarized below:

  • MFA Enforcement for all users is very easy.
  • Permissions can be centrally managed fro an entire AWS Organization from a single place.
  • Multiple Roles can be given to a single user or group in a single account - and with a bit of work, the roles can be conditional.
  • A single user or group can have differing permissions.
  • It can integrate with a multitude of Identity Sources (including Entra ID / Active Directory), or it can use it's own.
  • Any applications supporting OIDC or SAML integration can be integrated with IAm Identity Center to Manage User Access.
  • Its free to use.

The Management interface for IAM Identity Center is pretty intuitive to use. Managing things like Users, Groups, Permission Sets (Roles), and AWS Account Assignments is straightforward. Enforcing MFA for all users is literally a checkbox exercise.

User Access to the Console

Logging in to an AWS Account with IAM Identity Center is equally as straightforward as logging in to an AWS account with an IAM User. The only real difference is that instead of logging into an AWS Account directly, you will log in to a Single Sign-On Portal, from which you will have access to which ever accounts you have been granted access to with whichever Roles you have assigned to you. See the Screenshot below as an example.

SSO Roles SSO Roles

Clicking on any of the roles assigned to you under one of the accounts will open the AWS Console in that account, and with that Role, in a new tab in your browser.

User Programmatic Access

If you are already familiar with the AWS CLI, then switching to use IAM Identity Center is very straightforward. There is a slight difference in how you configure your credentials, and before making use of your configured credentials in the CLI, you will need to run an aws sso login command and present MFA when prompted in your browser (How often you need to do this depends on the session duration configured for the permission set you are using).

Here is a comparison of using an IAM User and an Identity Center User for the AWS CLI.

  • Configuring Credentials aws configure --profile <profile_name>
    • Here you will provide the Access Key ID and Secret Access Key of your IAM User.
  • Use the Credentials aws s3 ls --profile <profile_name>
  • Configuring Credentials aws configure sso --profile <profile_name>
    • Here you will need to provide a series
  • Login aws sso login --profile <profile_name>
    • Here you will need to present MFA in a pop-up in your web browser.
  • Use the Credentials aws s3 ls --profile <profile_name>

Always use names Profiles with the AWS CLI

Named Profiles allow for multiple sets of configurations for different AWS Accounts or Roles. If you work frequently with multiple AWS Accounts, or have different roles within an AWS Account, then named profiles also make it harder to accidentally run a command against the wrong account, or with dangerously elevated permissions. Named Profiles can also be used with the AWS SDK (any supported language) to authenticate with AWS.

Less-Human Users

Admittedly things tend to get slightly more complex when configuring system access to your aws environment, such as integrating a SIEM Tool with your aws account, or configuring a CI/CD Pipeline to authenticate with AWS. Things can get especially tricky when the system you are integrating does not natively support making use of an IAM Role directly. In most cases there will still be ways to work around this. I believe that the principle of only creating a User for an actual human should still stand.

To keep this discussion brief, I will go over an example of configuring authentication a CI/CD Pipeline built with GitHub Actions using OIDC (OpenID Connect). I will then also give a few brief mentions of solutions that may work for your system.

Example | CI/CD Pipeline with OIDC - GitHub Actions Workflow

Almost every blog post or online forum showing how to authenticate a Github Actions Workflow with AWS will show you how to do it using an AWS IAM User. Fortunately, there is some very good documentation on how to do this with OIDC if you turn to the github docs. AWS also has a handy blog post about how to do this.

The process is a three step one:

Read the documentation - please don't follow this blindly.

This is just one simple example. The documentation will give you a better idea of how to apply this to your environment.

  1. Create an OIDC Identity Provider
    • For the Provider use: https://token.actions.githubusercontent.com
    • For the Audience use: sts.amazonaws.com
  2. Create and IAM Role
    • Configure the Trust Policy as follows (Replace the items between the < >):
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Federated": "<ARN_of_Identity_Provider_from_step_1>"
                    },
                    "Action": "sts:AssumeRoleWithWebIdentity",
                    "Condition": {
                        "StringLike": {
                            "token.actions.githubusercontent.com:sub": "repo:<github-org>/<repo-name>:*"
                        },
                        "StringEquals": {
                            "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                        }
                    }
                }
            ]
        }
      
    • Set the Permissions to the minim,um required for your pipeline tasks.
  3. Configure the Github Actions Workflow
    • Below are the two examples illustrating what you might need to do differently to modify your Github Actions Workflow to make use of OIDC to authenticate with AWS.
name: Gross way with IAM User

on:
  push:
    branches:
      - main

jobs:
  aws-thing:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Configure aws credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: eu-west-1

    - name: Do the AWS Things
      run: |
        aws s3 sync / s3://${{ secrets.BUCKET_NAME }}/ --delete
name: Tasty way with OIDC

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

jobs:
  aws-thing:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Configure aws credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: ${{ secrets.DEPLOYMENT_ROLE }}
        aws-region: eu-west-1

    - name: Do the AWS Things
      run: |
        aws s3 sync / s3://${{ secrets.BUCKET_NAME }}/ --delete
Permissions Block

Note the additional permissions block that is required here for the OIDC Option. This is needed to facilitate the JWT Exchanged.

Honorable Mentions

IAM Roles Anywhere

AWS IAM Roles Anywhere enables workloads outside AWS, such as on-premises servers or applications, to securely access AWS resources using X.509 certificates from a trusted certificate authority (CA). The CA is registered with IAM Roles Anywhere as a trust anchor, allowing workloads to obtain temporary security credentials.

This method removes the need for long-term credentials, enhances security through short-lived credentials, and integrates seamlessly with IAM roles and policies. It's particularly useful for hybrid or multi-cloud environments requiring secure AWS access.

OIDC

OIDC (OpenID Connect), built on OAuth 2.0, enables secure authentication by relying on an external identity provider (IdP), like Google, to issue JSON Web Tokens (JWTs) after user authentication. In AWS, these tokens are used to request temporary security credentials via an IAM OIDC identity provider.

By setting up roles in IAM, AWS dynamically assigns temporary credentials to users based on the JWT's claims. This approach eliminates the need for static credentials, enhancing security and simplifying access to AWS resources for applications like web or mobile apps.

SAML

SAML enables systems to securely access AWS resources by using a trusted identity provider (IdP) for authentication. The system authenticates with the IdP, which verifies its identity and issues a SAML assertion containing key details like identity attributes and group memberships. This assertion is securely passed to AWS, where it is validated against pre-configured trust settings.

AWS then allows the system to assume a specific IAM role based on the information in the SAML assertion, granting temporary security credentials with defined permissions. This approach ensures access is both secure and dynamic, avoiding the need for long-term credentials while enforcing fine-grained access control aligned with organizational policies.

Conclusion

I don't completely dislike IAM Users, but hopefully I have illustrated the point that there are, in most cases better options. Please let me know in the comments bellow if you have any thoughts or examples of how you have purged IAM users from your estate - Or even if you have a case which proves IAM Users to be the very best option available. Also do feel free peruse the additional links I've added on the left pane of this blog post (Or at the bottom if you're reading this on your phone).

Lets all make sure we do out best to keep "Users" for Humans, and use better means for systems. Lets also do our best to use the best tools at our disposal to securely manage who and what has access to our environments. The world would be a better place for it.

A Day in the Life of a Cloud Engineer

image

Try the Cringy Podcast format of this post (NotebookLM):

Hello, world! I’m Lauric's AI Assistant, prentending to be a cloud engineer working for CloudWizards Consulting and writing blog posts about it. My job? Making sure our clients' cloud infrastructure runs smoother than a greased-up otter on a water slide. I primarily work with AWS, so if you’re curious about what a typical day looks like for a cloud engineer, grab a cup of coffee and join me for a fun ride through the clouds!

Morning Mayhem: The Daily Stand-Up

My day kicks off at 8 AM with a strong cup of coffee and our daily stand-up meeting. Picture a Brady Bunch-style video call with my fellow CloudWizards. We each give a quick rundown of what we accomplished yesterday and what’s on our plate today. It’s like speed dating, but for techies.

Today’s highlight? A colleague accidentally created 100 EC2 instances instead of 10. His credit card statement is going to look like he bought a small island. Classic rookie mistake!

First Task: Security Audit

My first task is performing a security audit for a new client. They’re a fintech startup and, as you might guess, security is paramount. I dive into their AWS environment, armed with a checklist that would make a pilot jealous.

  • IAM Policies: I start by reviewing their Identity and Access Management (IAM) policies. Turns out, their intern has more access than the CEO. Time to tighten those permissions!

  • S3 Buckets: Next up, I check their S3 buckets. As expected, some are public when they shouldn’t be. Remember kids, S3 stands for Secure, Secure, Secure. Well, at least in my book.

  • Security Groups: I find a few security groups that are as open as the Grand Canyon. Note to self: Block port 22 from the whole internet, not just your nosy neighbor.

Mid-Morning Madness: Solving a Production Outage

Just as I’m patting myself on the back for a thorough security audit, my Slack notifications explode. One of our e-commerce clients is experiencing a production outage. Time to don the superhero cape!

I jump on a call with the client’s team, and we dive into the CloudWatch logs. Turns out, an autoscaling misconfiguration led to all instances being terminated. Whoops! We quickly adjust the autoscaling policies and spin up new instances. Crisis averted!

The client jokes that they’ve aged ten years in the past hour. I tell them it’s just the cloud engineer way of giving you a free anti-aging treatment—stress-induced, of course.

Lunchtime: The Great Sandwich Debate

Lunchtime is a sacred ritual. Today, the team debates the age-old question: Is a hot dog a sandwich? The consensus: We have no idea, but we do agree that tacos are the superior handheld food. It’s these deep, philosophical discussions that keep us going.

Afternoon Adventure: Migrating to the Cloud

Post-lunch, it’s time to tackle a cloud migration for a healthcare client. They’re moving their on-premises infrastructure to AWS. This involves setting up VPCs, configuring RDS, and ensuring HIPAA compliance. It’s like playing a game of Tetris, but with servers and databases.

  • VPC Setup: I create a Virtual Private Cloud (VPC) with subnets spread across multiple Availability Zones for redundancy. It’s like building a digital fortress.

  • Database Migration: I use AWS Database Migration Service (DMS) to move their data to RDS. Watching the data flow seamlessly feels like magic, except it’s not; it’s pure cloud engineering wizardry.

  • Compliance Check: Ensuring everything meets HIPAA standards involves a lot of checkbox ticking and documentation. Not the most thrilling part, but crucial nonetheless.

Wrapping Up: Documentation and Deployment

As the day winds down, I document all the changes and configurations. If it’s not documented, it didn’t happen—wise words from a former boss. I also prepare for tomorrow’s deployment of a new feature for another client. Think of it as packing your bag the night before a big hike.

Evening: Unwinding and Reflecting

Finally, I shut down my laptop and unwind with a bit of gaming. There’s something cathartic about blowing off steam in a virtual world after a day of solving real-world problems.

As I drift off to sleep, I dream of S3 buckets, EC2 instances, and the endless possibilities of the cloud. Being a cloud engineer is challenging, but it’s also incredibly rewarding. After all, who else gets to play in the clouds all day and call it work?

Thanks for joining me on this journey. Until next time, keep your clouds secure and your coffee strong!