OCI IAM API Keys Should Be Rotated Every 90 Days
More Info:
API signing keys should be rotated every 90 days. Regular rotation limits the window of exposure if a key is compromised and ensures cryptographic material stays current
Risk Level
High
Address
Compliance, Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS AWS
- CIS Critical Security Controls v8
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- Cloudanix Best Practice
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- GDPR
- HIPAA
- HITRUST CSF
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- Reserve Bank of India (RBI) Master Direction – Information Technology Framework
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Using Console
Below are the console-based steps to remediate “OCI IAM API Keys Should Be Rotated Every 90 Days” by rotating a user’s API key and aligning with monitoring.
1. Identify which API keys need rotation
- Sign in to the OCI Console.
- Go to Identity & Security → Identity → Users.
- Click the specific user.
- In the user details, go to the API Keys tab.
- Note the Created date of each key. Any older than 90 days should be rotated.
2. Create a new API key for the user
- Stay on the same user’s API Keys tab.
- Click Add API Key.
- Choose Generate API Key Pair (recommended for simplicity):
- The console generates a public/private key pair.
- Click Download Private Key and save it securely (this is your only chance).
- Click Add to register the new key.
- Copy and save:
- Fingerprint
- Tenancy OCID
- User OCID
- API endpoint region (for CLI/SDK config later).
If you already have your own key pair, choose Upload Public Key and upload the public key instead.
3. Update applications / tools to use the new key
Wherever the old key is used (CLI config, SDKs, automation scripts, CI/CD):
- Update the configuration with:
- New private key file path
- New fingerprint
- Same user OCID and tenancy OCID (unless you changed the user/tenancy)
- Same region
- Test that:
oci iam compartment list(or another simple call) works for that user.- Applications using the key can still access needed resources.
Ensure everything is working before deleting the old key.
4. Delete the old API key
- Back in Identity & Security → Identity → Users → user → API Keys.
- Identify the old key (by Created date or fingerprint).
- Click the three dots (⋯) next to the old key.
- Click Delete and confirm.
That fully rotates the key: new key in use; old key removed.
5. Set up / confirm monitoring for 90‑day rotation
To continuously detect this issue:
- Go to Cloud Guard (Identity & Security → Cloud Guard).
- Make sure Cloud Guard status is Enabled.
- Under Detector Recipes, open your active recipe (often the default Oracle-managed one, or your clone).
- Find the detector for IAM API key age / rotation (name varies but is typically under IAM or Identity security checks).
- Ensure it is:
- Enabled
- Severity set appropriately (e.g., High/Medium)
- (Optional) Under Responder Recipes, configure responders/notifications (email, pager, etc.) for this detector so you are alerted when a key is older than 90 days.
Ongoing practice: Repeat this process for all users with API keys; integrate it into a 90‑day rotation schedule, or rely on Cloud Guard alerts to trigger rotation.
Using CLI
Below are the minimal, CLI-focused steps to remediate “OCI IAM API Keys Should Be Rotated Every 90 Days” by rotating the keys and (optionally) setting up monitoring.
1. Prerequisites
- OCI CLI installed and configured (
oci setup configalready done). - You know the User OCID whose API keys you want to rotate (could be yourself or a service user).
If you don’t know the user OCID (for your own account):
oci iam user list --all --compartment-id <tenancy_ocid> \
--query "data[?\"name\"=='<your_username>'].id | [0]" --raw-output
2. List Existing API Keys and Check Age
oci iam user api-key list \
--user-id <user_ocid> \
--query 'data[].{"keyId": "key-id", "timeCreated": "time-created"}' \
--output table
If any timeCreated is older than 90 days, you should rotate that key.
3. Generate a New RSA Key Pair Locally
mkdir -p ~/.oci/keys
cd ~/.oci/keys
# Generate new key pair (adjust file names as needed)
openssl genrsa -out new_api_key.pem 2048
openssl rsa -pubout -in new_api_key.pem -out new_api_key_public.pem
4. Upload the New Public Key to OCI (Create New API Key)
oci iam user api-key upload \
--user-id <user_ocid> \
--key-file new_api_key_public.pem \
--query 'data."key-id"' \
--raw-output
This returns the new key-id which you can record for reference.
5. Update Your OCI CLI Config to Use the New Private Key
Edit your OCI config file (typically ~/.oci/config):
nano ~/.oci/config
Update (or add) the profile you use to include the new key:
[DEFAULT]
user=<user_ocid>
fingerprint=<new_key_fingerprint_from_console_or_list>
tenancy=<tenancy_ocid>
region=<region_identifier>
key_file=~/.oci/keys/new_api_key.pem
You can get fingerprints for keys via:
oci iam user api-key list --user-id <user_ocid> \
--query 'data[].{"keyId":"key-id","fingerprint":"fingerprint"}' \
--output table
Test that CLI works with the new key:
oci iam compartment list --compartment-id <tenancy_ocid> --limit 1
6. Delete the Old API Key
List keys again to find the old key-id:
oci iam user api-key list --user-id <user_ocid> \
--query 'data[].{"keyId":"key-id","timeCreated":"time-created"}' \
--output table
Delete the old key:
oci iam user api-key delete \
--user-id <user_ocid> \
--fingerprint <old_key_fingerprint> \
--force
Or using key-id:
oci iam user api-key delete \
--user-id <user_ocid> \
--key-id <old_key_id> \
--force
7. (Optional) Monitoring: Detect Keys Older Than 90 Days
You can periodically run a script using OCI CLI to detect keys older than 90 days and send alerts via Monitoring/Notifications.
Example: list keys with creation time filter using JMESPath and date comparison in a shell script:
THRESHOLD_DAYS=90
CUTOFF_DATE=$(date -u -d "-${THRESHOLD_DAYS} days" +%s)
oci iam user api-key list --user-id <user_ocid> \
--query 'data[].{"keyId":"key-id","timeCreated":"time-created"}' \
--raw-output | jq -r '.[] | @base64' | while read row; do
_jq() { echo ${row} | base64 --decode | jq -r ${1}; }
KEY_ID=$(_jq '.keyId')
TIME_CREATED=$(_jq '.timeCreated')
CREATED_EPOCH=$(date -u -d "$TIME_CREATED" +%s)
if [ "$CREATED_EPOCH" -lt "$CUTOFF_DATE" ]; then
echo "API key $KEY_ID is older than ${THRESHOLD_DAYS} days."
# Integrate here with OCI Notifications / email / Slack etc.
fi
done
You can run this via a scheduled job (cron, OCI DevOps pipeline, or external scheduler) and alert when old keys are found.
These steps remediate the finding by rotating OCI IAM API keys via OCI CLI and optionally allow you to monitor and alert on keys older than 90 days.
Using Python
Below is a simple, practical way to monitor and enforce a “rotate every 90 days” policy for OCI IAM API keys using Python and the OCI SDK.
You’ll:
- Use the OCI Python SDK to list users and their API keys
- Calculate key age
- Flag keys older than 90 days (log, email, or push metrics)
- Optionally, auto-delete old keys (if your process supports it)
1. Prerequisites
- Install the OCI Python SDK:
pip install oci
- Create/verify an OCI config file (usually
~/.oci/config) with a profile:
[DEFAULT]
user=ocid1.user.oc1..aaaa...
fingerprint=xx:xx:xx:...
key_file=/path/to/oci_api_key.pem
tenancy=ocid1.tenancy.oc1..aaaa...
region=us-ashburn-1
- Make sure the user or instance principal running the script has these IAM permissions in a policy (at least at tenancy or compartment scope you care about):
Allow group SecurityAdmins to inspect users in tenancy
Allow group SecurityAdmins to inspect api-keys in tenancy
Allow group SecurityAdmins to manage api-keys in tenancy # only if you want auto-delete
2. Python Script: Detect API Keys Older Than 90 Days
This script:
- Lists all IAM users
- Lists each user’s API keys
- Flags keys older than 90 days
- (Optional) deletes them if
AUTO_DELETE_OLD_KEYS = True
import oci
from datetime import datetime, timezone, timedelta
# === CONFIG ===
PROFILE_NAME = "DEFAULT" # profile from ~/.oci/config
MAX_AGE_DAYS = 90
AUTO_DELETE_OLD_KEYS = False # set True if you want to auto-delete
DRY_RUN = True # if deleting, keep True to test first
def main():
# Load config
config = oci.config.from_file("~/.oci/config", PROFILE_NAME)
identity_client = oci.identity.IdentityClient(config)
tenancy_id = config["tenancy"]
cutoff = datetime.now(timezone.utc) - timedelta(days=MAX_AGE_DAYS)
print(f"Checking API keys older than {MAX_AGE_DAYS} days (before {cutoff.isoformat()})")
# List all users in the tenancy
users = oci.pagination.list_call_get_all_results(
identity_client.list_users,
compartment_id=tenancy_id
).data
for user in users:
user_ocid = user.id
user_name = user.name
# List API keys for each user
api_keys = identity_client.list_api_keys(user_ocid).data
for key in api_keys:
key_id = key.key_id
time_created = key.time_created # datetime with timezone
age_days = (datetime.now(timezone.utc) - time_created).days
if time_created < cutoff:
print(
f"[STALE] User: {user_name} ({user_ocid}), "
f"Key: {key_id}, Created: {time_created}, Age: {age_days} days"
)
if AUTO_DELETE_OLD_KEYS:
if DRY_RUN:
print(f" -> DRY RUN: would delete key {key_id}")
else:
delete_api_key(identity_client, user_ocid, key_id)
else:
# Uncomment if you want to log all keys
# print(f"[OK] User: {user_name}, Key: {key_id}, Age: {age_days} days")
pass
def delete_api_key(identity_client, user_ocid, key_id):
print(f" -> Deleting key {key_id} for user {user_ocid}")
identity_client.delete_api_key(
user_id=user_ocid,
fingerprint=key_id # for API keys, key_id is the fingerprint
)
if __name__ == "__main__":
main()
Notes:
time_createdis returned in UTC with timezone.- For IAM API keys,
key_idis the fingerprint and is used asfingerprintindelete_api_key. - Keep
DRY_RUN=Truewhile testing to avoid accidental deletion.
3. Integrating with “Monitoring”
Pick how you want to consume this check:
Option A: Run on a Schedule (cron / CI)
Run the script daily via cron on a bastion server or in a CI pipeline (GitHub Actions, Jenkins, etc.):
Example cron (run every night at 01:00):
0 1 * * * /usr/bin/python3 /path/to/check_oci_api_keys.py >> /var/log/oci_api_key_check.log 2>&1
You can then:
- Send email/Slack when
[STALE]appears in log. - Or export output as JSON and push to a logging system.
Option B: Use an OCI Function + Logging / Notifications
- Package this script logic as an OCI Function (Python runtime).
- Write stale key findings to:
- OCI Logging (using
loggingmodule) - or push notifications via OCI Notifications to email/Slack.
- OCI Logging (using
High-level steps:
- Create function application in your compartment.
- Deploy Python function with above logic (adapt to use instance principal or resource principal).
- Create a scheduled job using OCI Events + Functions (Event rule with schedule, e.g.,
cron(0 1 * * ? *)). - Function writes to Logging or calls Notifications.
4. (Optional) Enforcing Rotation, Not Just Deletion
To truly “rotate” instead of just delete, you need a process:
- Notify user whose keys are > N days old.
- User (or automation) creates a new key pair and uploads public key or uses CLI to create new API key.
- Verify new key works.
- Script deletes old key once new is in place and younger than threshold.
You can enhance the script to:
- Only delete keys if user has at least one “young” key.
- Or send email only, and have manual rotation performed.
5. Summary
- Use the OCI Python SDK (
oci.identity.IdentityClient) to list users andlist_api_keys. - Compare
time_createdtonow - 90 days. - Log/alert or auto-delete keys older than 90 days.
- Schedule the script via cron, CI, or OCI Functions/Events to continuously monitor and enforce your rotation policy.
Using Terraform
# OCI IAM API keys cannot be rotated or time-limited via Terraform.
# The oci/oci provider does not expose a resource or argument that:
# - Sets an expiry/rotation interval for API keys, or
# - Rotates an existing API key on a schedule.
# API keys are created/managed as user credentials outside Terraform,
# so rotation every 90 days must be handled operationally:
#
# 1. In the OCI Console:
# - Go to Identity & Security -> Users.
# - Select the user -> API Keys.
# - Add a new API key (download private key & config).
# - Update any workloads using the old key to use the new key.
# - Delete the old API key.
#
# 2. Or with OCI CLI or automation (scripts, CI pipelines, etc.)
# to:
# - Create new API keys,
# - Update consuming apps’ configs,
# - Delete keys older than 90 days.
#
# For “OCI IAM Monitoring”, Terraform can at most:
# - Tag users or keys (where supported) and you then monitor age externally,
# - Or wire up alarms/logging that detect keys older than 90 days.
# But the actual key rotation remains a runtime/manual process.
# Because Terraform cannot manage or rotate oci-identitymanagement-iam-apikey
# credentials directly, `terraform plan` will show **no changes** related to
# key rotation; all rotation behavior must be implemented outside Terraform.