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