As an Administrator you provide access to AWS environment to developers and other business users to enable them doing their work . However, it is always recommended to go back and review IAM(Identity and Access Management) entities, such as, users, roles, policies etc. to make sure, they are set up with right set of permissions. As a common practice, usually we provide more access than needed to developers and as time passes and applications stabilize, we tend to revoke unnecessary permissions and provide with only required permission to perform the job.
Today, I am sharing a script which you can periodically run to generate a report on IAM users access.By no means, this is a complete access roster review, however, it will help you with enough information to make decision if certain user(s) still need access in the environment. How they are using AWS resources?
Please note, you can run this script as a simple script from your work machine. In addition, you can set this script as a Lambda function to run periodically and integrate with AWS Config and SNS to report on console or send notifications.
With that being said, let’s start scripting!
To run this script you need to install AWS Tools for Powershell and configure AWS credentials. I am assuming you have already set up your system. If you still have any issue, refer following documents by Amazon :
- https://docs.aws.amazon.com/powershell/latest/userguide/specifying-your-aws-credentials.html
- https://aws.amazon.com/powershell/
First, start with a script block to define the output result CSV File path and define 2 global array variables:
$date = Get-Date -UFormat "%m%d%Y"
$currentDir = $(Get-Location).Path
$oFile = "$($currentDir)\AWS-IAM-UserAccessReview-$($date).csv"
if(Test-Path $oFile){Remove-Item $oFile -Force}
"User Name, User Id, User Arn, Creation Date, Associated Groups, Last Authentication Date, Last Accessed Service" | Out-File -FilePath $oFile -Append -Encoding ascii
$Global:allIAMUsers = @()
$Global:allAccessInfo = @()
Next, we will use Get-IAMAccountAuthorizationDetail powershell cmdlet with a filter “User”. This command will generate all authorization information for AWS IAM users in your account. After that, we will use Request-IAMServiceLastAccessedDetail to generate a report that includes details about when an IAM resource (user, group, role, or policy) was last used in an attempt to access AWS services. In this case, we will use it to generate such report for an user ARN. It generates a Job Id which we will use to generate detailed access report. Finally, we will use Get-IAMServiceLastAccessedDetail with the Job Id generated in previous step. It retrieves a service last accessed report that was created using the GenerateServiceLastAccessDetails operation. Here is the code snippet to generate final CSV report as described in the begining. Let me know if it is helpful. Contact me if you face any issue running this script!
$users = Get-IAMAccountAuthorizationDetail -Filter User
if(!([string]::IsNullOrEmpty($users))){
Do{
$userMarker = $jobId = ""
$users.UserDetailList | ForEach-Object{
$userArn = ""
$userObj = New-Object psObject
$userObj | Add-Member UserName $_.UserName
$userObj | Add-Member UserId $_.UserId
$userObj | Add-Member CreationDate $_.CreateDate
$userArn = $_.Arn
$userObj | Add-Member UserArn $_.Arn
if([String]::IsNullOrEmpty($_.GroupList)){$userObj | Add-Member GroupList "NA"} else{$userObj | Add-Member GroupList ($_.GroupList -Join ";")}
$Global:allAccessInfo = @()
$jobId = Request-IAMServiceLastAccessedDetail -Arn $userArn
$accessDetails = Get-IAMServiceLastAccessedDetail -JobId $jobId
Do{
$accessMarker = ""
$accessDetails.ServicesLastAccessed | Where-Object{$_.TotalAuthenticatedEntities -gt 0} | ForEach-Object{
$accessObj = New-Object psObject
$accessObj | Add-Member LastAuthenticated $_.LastAuthenticated
$accessObj | Add-Member ServiceName $_.ServiceName
$Global:allAccessInfo += $accessObj
}
$accessMarker = $accessDetails.Marker
if(!([String]::IsNullOrEmpty($accessMarker))){
$accessDetails = Get-IAMServiceLastAccessedDetail -JobId $jobId -Marker $accessMarker
}
}While($accessDetails.IsTruncated)
if($Global:allAccessInfo){
$lastAccess = $Global:allAccessInfo | Select-Object | Sort-Object Desc | Select-Object -First 1
$lastAccessDate = $lastAccess.LastAuthenticated
$lastAccessService = $lastAccess.ServiceName
}
else{
$lastAccessDate = "NA"
$lastAccessService = "NA"
}
$userObj | Add-Member LastAccessDate $lastAccessDate
$userObj | Add-Member LastAccessedService $lastAccessService
$Global:allIAMUsers += $userObj
$userMarker = $users.Marker
if(!([String]::IsNullOrEmpty($userMarker))){
$users = Get-IAMAccountAuthorizationDetail -Filter User -Marker $userMarker
}
}
}While($users.IsTruncated)
}
$Global:allIAMUsers | ForEach-Object{
"$($_.UserName),$($_.UserId),$($_.UserArn),$($_.CreationDate),$($_.GroupList),$($_.LastAccessDate),$($_.LastAccessedService)" | Out-File -FilePath $oFile -Append -Encoding ascii
}
Here is a sample output – a csv file generated with IAM users access details :