AWS IAM users audit

2021-06-04

Find unused AWS IAM users - security, audit, compliance.

One of our clients have grown over years to 250+ users, all created \ deleted \ managed manually.
It became obvious that some automation is required, at least to delete users who left the company for security and compliance.

Requirements

Out of scope

Options

Quick googling revealed the following tools.

Tool Link GitHub stars Can find unused users Least privileges based on usage Generate terraform Language UI
AirIAM https://github.com/bridgecrewio/AirIAM 327 Yes Yes Yes Python CLI tool
cloudtracker https://github.com/duo-labs/cloudtracker 683 Yes Yes CLI tool
trailscraper https://github.com/flosell/trailscraper/ 379 No Yes Yes CLI tool
aardvark https://github.com/Netflix-Skunkworks/aardvark 386 No Python Web-based. Runs as docker-compose with db.
repokid https://github.com/Netflix/repokid 910 No Based on Aardvark above

AirIAM

We heavily use aws-vault for AWS authentication, so we run AirIAM like this:

$ aws-vault exec ..... -- airiam find_unused --last-used-threshold 90 --no-cache
...
The following 64 users were found to be unused:
...
The following 12 active access keys aren’t being used:
...
The following 6 users have password access they aren’t using:
...
The following 15 roles are unused:
...
The following 8 groups are redundant:
...
The following 7 policies are redundant:
...
The following 30 policy attachments are unused:
...

Now we can go through the list of unused users and delete them one by one.
AirIAM supports automated deletion via an integration with Bridgecrew Cloud, another their offering, but we didn’t use it.

Running in CI/CD

The client uses Jenkins, and so we wrapped the AirIAM run into the following Declarative job definition Jenkinsfile:

pipeline {
    options {
        skipDefaultCheckout true
    }
    agent {
        docker {
            image 'python:3'
            alwaysPull true
            args '-u root'
        }
    }
    triggers {
        cron('H H(9-16) * * 1-5')
    }
    stages {
        stage('airiam') {
            steps {
                sh 'pip3 install airiam'
                sh 'airiam find_unused --last-used-threshold 90 --no-cache'
            }
        }
    }
}

It relies on the following Jenkins plugins:

See more info: https://www.jenkins.io/doc/book/pipeline/docker/

Permissions

Above Jenkins example relies on AWS authentication to be already in place.
We use Jenkins agents in the same AWS account with Instance profile and Role allowing AirIAM to have access to IAM.

At least the following permissions are required for the Role:

resource "aws_iam_role_policy" "airaim" {
  name   = "airiam"
  role   = var.ci_role_id
  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:GenerateCredentialReport",
        "iam:GenerateServiceLastAccessedDetails"
      ],
      "Resource": "*"
    }
  ]
}
EOF
}

Future

As next steps we are considering to implement the following: