IAM user console access is disabled, used within the configured inactivity period, or never used
IAM users with console access are evaluated by password_last_used. Inactivity beyond max_console_access_days (default 45) marks stale console access.
Users without console access are excluded.
Risk
Dormant console credentials stay valid and invite password spraying, credential stuffing, and breach reuse. Compromise yields interactive access for data discovery/exfiltration and unauthorized IAM or resource changes, degrading confidentiality and integrity, and risking availability.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks iam_user_console_access_unusedRecommendation
Remove or disable console passwords for users inactive beyond your window (e.g., 45 days). Prefer roles or federation over long-lived IAM users. Enforce least privilege, require MFA for remaining console users, and run periodic reviews and deprovisioning to prevent unused credentials.
Remediation
CLI
aws iam delete-login-profile --user-name <USER_NAME>Terraform
# IAM user with console access disabled by not creating a login profile
resource "aws_iam_user" "<example_resource_name>" {
name = "<example_resource_name>"
# Critical: Do not define aws_iam_user_login_profile for this user -> no console access
}NativeIaC
# CloudFormation: IAM user without console access
Resources:
<example_resource_name>:
Type: AWS::IAM::User
Properties:
UserName: <example_resource_name>
# Critical: No LoginProfile property -> disables console access for the userOther
Check Code
import datetime
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.iam.iam_client import iam_client
class iam_user_console_access_unused(Check):
def execute(self) -> Check_Report_AWS:
maximum_expiration_days = iam_client.audit_config.get(
"max_console_access_days", 45
)
findings = []
for user in iam_client.users:
report = Check_Report_AWS(metadata=self.metadata(), resource=user)
report.region = iam_client.region
if user.console_access and user.password_last_used:
time_since_insertion = (
datetime.datetime.now()
- datetime.datetime.strptime(
str(user.password_last_used), "%Y-%m-%d %H:%M:%S+00:00"
)
)
if time_since_insertion.days > maximum_expiration_days:
report.status = "FAIL"
report.status_extended = f"User {user.name} has not logged in to the console in the past {maximum_expiration_days} days ({time_since_insertion.days} days)."
else:
report.status = "PASS"
report.status_extended = f"User {user.name} has logged in to the console in the past {maximum_expiration_days} days ({time_since_insertion.days} days)."
else:
report.status = "PASS"
report.status_extended = f"User {user.name} does not have console access enabled or is unused."
findings.append(report)
return findings