IAM User Unused Access Keys
Overview
This check identifies IAM users who have active access keys that have never been used. When an IAM user has console access and also has access keys showing "Last used: N/A," it indicates credentials were created but never exercised.
Risk
Unused but active access keys create unnecessary security exposure:
- Data breach risk: If an attacker discovers these keys, they gain programmatic access to your AWS account
- Unauthorized changes: Compromised keys can be used to modify or delete resources
- Service disruption: Attackers could shut down critical services
- Audit complexity: Dormant credentials make it harder to track who is actually using what
Since these keys have never been used, they likely are not needed and should be removed.
Remediation Steps
Prerequisites
You need permission to manage IAM users. Typically this means having the IAMFullAccess policy or equivalent permissions.
AWS Console Method
- Sign in to the AWS Management Console
- Navigate to IAM (search for "IAM" in the top search bar)
- Click Users in the left sidebar
- Select the user flagged by Prowler
- Click the Security credentials tab
- Scroll down to Access keys
- Find keys where:
- Status = Active
- Last used = N/A (or "Never used")
- For each unused key, click Actions then choose:
- Deactivate if you want to temporarily disable it (safer first step)
- Delete if you are certain it is not needed
- Confirm your choice when prompted
Tip: If unsure, deactivate first. Wait a few days to see if anyone reports issues, then delete.
AWS CLI (optional)
List Access Keys for a User
aws iam list-access-keys \
--user-name <username> \
--region us-east-1
This returns all access keys and their status. Look for keys with no recent usage.
Deactivate an Access Key
To deactivate (but not delete) an unused key:
aws iam update-access-key \
--user-name <username> \
--access-key-id <access-key-id> \
--status Inactive \
--region us-east-1
Delete an Access Key
To permanently delete an unused key:
aws iam delete-access-key \
--user-name <username> \
--access-key-id <access-key-id> \
--region us-east-1
Warning: Deletion is permanent. Make sure the key is truly unused before deleting.
Find All Users with Unused Keys
Generate a credential report to audit all users:
# Generate the report
aws iam generate-credential-report --region us-east-1
# Download and decode the report
aws iam get-credential-report \
--query 'Content' \
--output text \
--region us-east-1 | base64 --decode > credential-report.csv
Review the CSV for users where access_key_1_last_used_date or access_key_2_last_used_date is "N/A" but the key is active.
CloudFormation (optional)
CloudFormation's AWS::IAM::AccessKey resource does not support setting the Status property. Access keys created via CloudFormation are always Active.
Recommended approach: Do not create access keys in CloudFormation templates. Instead, create them manually when needed, or use IAM roles with temporary credentials.
If you must manage access keys via infrastructure as code, use Terraform (see below) or handle key lifecycle through AWS CLI scripts triggered by CloudFormation custom resources.
Example: IAM User Without Access Keys
AWSTemplateFormatVersion: '2010-09-09'
Description: IAM User without programmatic access keys
Parameters:
UserName:
Type: String
Description: Name of the IAM user
Resources:
IAMUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref UserName
# No access keys created - user has console access only
# Access keys should be created manually if/when needed
Outputs:
UserArn:
Description: ARN of the IAM user
Value: !GetAtt IAMUser.Arn
Terraform (optional)
Deactivate an Existing Access Key
If you manage an access key in Terraform and want to deactivate it:
resource "aws_iam_access_key" "example" {
user = "example-user"
status = "Inactive"
}
Recommended: Avoid Creating Access Keys
The best practice is to not create long-term access keys at all. Instead, use IAM roles:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# Create an IAM user without access keys
resource "aws_iam_user" "example" {
name = "example-user"
tags = {
Environment = "production"
}
}
# If programmatic access is needed, prefer IAM roles with assume role
resource "aws_iam_role" "example" {
name = "example-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
AWS = aws_iam_user.example.arn
}
}
]
})
}
This approach uses temporary credentials via sts:AssumeRole instead of long-lived access keys.
Verification
After remediation, confirm the fix:
- Go to IAM > Users > select the user > Security credentials
- Verify that:
- No access keys exist, OR
- Remaining keys show Status: Inactive or have recent Last used dates
CLI Verification
# List remaining keys
aws iam list-access-keys \
--user-name <username> \
--region us-east-1
# Re-run Prowler to confirm the check passes
prowler aws --check iam_user_no_setup_initial_access_key
Additional Resources
- AWS IAM Best Practices
- Managing Access Keys
- IAM Credential Reports
- Using IAM Roles Instead of Long-Term Credentials
Notes
- Prefer roles over access keys: IAM roles with temporary credentials are more secure than long-lived access keys
- Deactivate before deleting: When unsure, deactivate first and wait to see if anyone reports issues
- Audit regularly: Use IAM credential reports to periodically review access key usage across all users
- One key per user: AWS best practice recommends having at most one active access key per user to simplify rotation