Back to Checks
User active API key is rotated within 90 days or less
identity_user_api_keys_rotated_90_days
Service: identitySeverity: medium
OfficialBuilt-inVerified
Categories:identity-accesssecrets
Resource Type:User
OCI IAM users with active API signing keys older than 90 days are identified. Key age is derived from each key's creation time; only active keys are considered. Users without API keys are recorded.
Risk
Long-lived API keys widen exposure. If a key leaks, an attacker can sign OCI API calls without MFA, enabling unauthorized changes (integrity), data access (confidentiality), and service outages (availability). Delayed rotation prolongs dwell time and complicates incident response.
Run this check with Prowler
Run in Prowler CloudRun
prowler oraclecloud --checks identity_user_api_keys_rotated_90_daysRecommendation
Enforce API key rotation every 90 days.
- Issue a new key, confirm workloads use it, then revoke the old key
- Apply least privilege and avoid shared keys
- Limit active keys per user and remove unused ones
- Monitor usage and automate rotation for defense in depth
Remediation
CLI
oci iam api-key delete --user-id <user-ocid> --fingerprint <old-key-fingerprint> --forceOther
1Sign in to the OCI Console
2Go to Identity & Security > Users, then select the target user
3Open API Keys and click Add API Key
4Generate API Key Pair (or Upload/Paste Public Key), then click Add and download/copy the private key
5For each API key older than 90 days, click the Actions (three dots) next to its fingerprint and select Delete
6Confirm deletion
Check Code
"""Check if user API keys rotate within 90 days or less."""
from datetime import datetime, timezone
import pytz
from prowler.lib.check.models import Check, Check_Report_OCI
from prowler.providers.oraclecloud.services.identity.identity_client import (
identity_client,
)
maximum_expiration_days = 90
class identity_user_api_keys_rotated_90_days(Check):
"""Check if user API keys rotate within 90 days or less."""
def execute(self) -> Check_Report_OCI:
"""Execute the identity_user_api_keys_rotated_90_days check.
Returns:
List of Check_Report_OCI objects with findings
"""
findings = []
for user in identity_client.users:
# Check if user has API keys
if user.api_keys:
for api_key in user.api_keys:
# Only check active API keys
if api_key.lifecycle_state == "ACTIVE":
report = Check_Report_OCI(
metadata=self.metadata(),
resource=user,
region=user.region,
resource_name=user.name,
resource_id=user.id,
compartment_id=user.compartment_id,
)
# Calculate age of the API key
now = datetime.now(timezone.utc)
# Ensure api_key.time_created is timezone aware
if api_key.time_created.tzinfo is None:
key_created = api_key.time_created.replace(tzinfo=pytz.utc)
else:
key_created = api_key.time_created
age_days = (now - key_created).days
if age_days > maximum_expiration_days:
report.status = "FAIL"
report.status_extended = f"User {user.name} has API key (fingerprint: {api_key.fingerprint[:16]}...) that has not been rotated in {age_days} days (over 90 days)."
else:
report.status = "PASS"
report.status_extended = f"User {user.name} has API key (fingerprint: {api_key.fingerprint[:16]}...) that was created {age_days} days ago (within 90 days)."
findings.append(report)
else:
# User has no API keys
report = Check_Report_OCI(
metadata=self.metadata(),
resource=user,
region=user.region,
resource_name=user.name,
resource_id=user.id,
compartment_id=user.compartment_id,
)
report.status = "PASS"
report.status_extended = f"User {user.name} does not have any API keys."
findings.append(report)
return findings