5

In AWS in the GUI you can select a role and then click on delete, then when you are prompted to approve or deny the deletion it shows you when the role was last used.

I would like to be able to know when a role was last used without pretend deleting it via the GUI.Ideally if I could get that data from the AWS CLI or a Boto3 script that would be great. Is there a way to accomplish that?

4 Answers 4

5

Amazon CloudTrail tracks all API use

In CloudTrail create a new trail

CloudTrail Create New Trail

You can configure each trail to send log events to CloudWatch: Edit the trail and choose to send Logs to CloudWatch. It will offer you to create a Role for this

Send CloudTrail logs to Cloudwatch

https://docs.aws.amazon.com/awscloudtrail/latest/userguide/monitor-cloudtrail-log-files-with-cloudwatch-logs.html

Then, run some calls on your role and wait 5 minutes.

In Cloudwatch, go to your log trail and search for "AssumedRole". Your events will be shown here

enter image description here

There is also documentation on searching Cloudwatch logs with filters through the api https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SearchDataFilterPattern.html

2
  • Do you mean CloudTrail? If you mean CloudWatch, can you explain how would you go about it?
    – Uberhumus
    Commented Dec 31, 2018 at 10:44
  • have updated answer and linked docs
    – jdog
    Commented Dec 31, 2018 at 21:41
3

I've been meaning to come back to this. After consulting with AWS support it would seem that this is possible using some functions of the AWS CLI, that I was not aware of.

Specifically they recommended using aws iam generate-service-last-accessed-details and aws iam get-service-last-accessed-details-with-entities, and they referred me to https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor-view-data.html#access_policies_access-advisor-viewing-cli.

For completion's sake here's how I used it:

#! /bin/bash

ROLES=$(aws iam list-roles | jq -r .Roles[].Arn)
for ROLE in $ROLES
do 
    echo $ROLE
    JOBID=$(aws iam generate-service-last-accessed-details --arn $ROLE | jq -r .JobId)
    echo $JOBID
    NAMESPACES=$(aws iam get-service-last-accessed-details --job-id $JOBID | jq -r .ServicesLastAccessed[].ServiceNamespace)
    for NAMESPACE in $NAMESPACES
    do  
        echo $NAMESPACE
        aws iam get-service-last-accessed-details-with-entities --job-id $JOBID --service-namespace $NAMESPACE | jq '.JobCompletionDate,.EntityDetailsList[].EntityInfo.Name,.EntityDetailsList[].EntityInfo.Id'
    done    
done 
3

This is possible using AWS SDKs.

I was cleaning my tabs after finishing this task and decided I would write an answer to help other people.

Versions:

  • aws-cli/2.0.61

  • go1.15.3 linux/amd64


Let's do this in Golang with the right imports.

 import (
     "fmt"
     "github.com/aws/aws-sdk-go/aws"
     "context"
     "github.com/aws/aws-sdk-go-v2/config"
     "github.com/aws/aws-sdk-go-v2/service/iam"
)

First, you want to init a session and a client:

cfg, err := config.LoadDefaultConfig() 
svc := iam.NewFromConfig(cfg)

Then you want to get a list of roles, to iterate through all role names. You can also use a specific role name because that's the only thing you will need to get the LastUsedDate:

roles_iam, err := svc.ListRoles(context.Background(), &iam.ListRolesInput{
PathPrefix: aws.String("/")})
if err != nil {
    fmt.Println("Error", err)
    return  
}

/** For simplicity and less dereferencing: more execution speed **/
roles_list := roles_iam.Roles    

Finally, iterate through a loop if you need to get LastUsedDate for all roles. Just set input with the right GetRoleInput arguments then call svc.GetRole to get a structure with your info.

/** Declare slice 'unused_roles' containing string unused role names **/
var unused_roles []string 

for i := range roles_list {
    role_name := *roles_list[i].RoleName
    input := &iam.GetRoleInput{
        RoleName: aws.String(*roles_list[i].RoleName),
    }
    role_info, err := svc.GetRole(context.Background(), input)
    if err != nil {
        fmt.Println("Error", err)
    }    
      
/** Check if role has never been used **/           
    if (role_info.Role.RoleLastUsed.LastUsedDate) == nil {
        fmt.Printf("Role %s has never been used\n", role_name)
        unused_roles = append(unused_roles, role_name)
        continue
    }
    last_used_date := *role_info.Role.RoleLastUsed.LastUsedDate
}

More info:

https://docs.aws.amazon.com/IAM/latest/APIReference/API_Role.html

https://docs.aws.amazon.com/IAM/latest/APIReference/API_RoleLastUsed.html

2

There currently is no method using SDKs for the AWS CLI to get the last accessed time of an IAM role.

Currently, the only way is to use the AWS Management Console.

  1. Select your IAM role and explore it
  2. Click the "Access Advisor" tab.
  3. The contents of this tab will display the last access time for each of the various services.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.