Skip to main content

OCI IAM Users Should Have MFA Enabled

More Info:

All active IAM users should have Multi-Factor Authentication (MFA) enabled. MFA significantly reduces the risk of account compromise from phishing, credential stuffing, and password reuse attacks.

Risk Level

High

Address

Compliance, Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • AWS Startup Security Baseline
  • AWS Well Architected Framework
  • 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
  • ISO 27001
  • 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
  • PCI
  • Reserve Bank of India (RBI) Master Direction – Information Technology Framework
  • SOC2
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Using Console

Below are concise, console-based steps to remediate “OCI IAM Users Should Have MFA Enabled” by enforcing MFA for users, so that any IAM Monitoring/Cloud Guard detector for non‑MFA users will clear.

Note: OCI now uses Identity Domains for IAM. Steps differ slightly for “local users” (older model) vs identity-domain users. I’ll outline both; use the one that matches what you see in your console.


1. For Identity Domains (Most Current Tenancies)

A. Enroll Users in MFA

  1. Sign in to the OCI Console as an administrator.
  2. Open the Navigation menuIdentity & SecurityDomains.
  3. Click the Identity Domain where your users reside (often the default domain).
  4. In the domain left menu, go to User ManagementUsers.
  5. Click a user you want to remediate.
  6. Scroll to or open the Security / Multi-Factor Authentication section:
    • If “MFA Devices” or “Factors” are present, ensure at least one factor is configured (e.g., TOTP/Authenticator app, SMS if available).
    • If not configured, inform the user to:
      • Sign in to OCI.
      • Click their user avatar (top right)Profile.
      • Under Multi-Factor Authentication, click Add Device or similar.
      • Register an authenticator app (Google Authenticator, Microsoft Authenticator, etc.) following the QR code + 6‑digit code steps.

Users must complete this themselves; you can only enforce MFA and, in some cases, reset MFA.


B. Enforce MFA with Sign‑On Policy (Tenancy‑Wide / Group‑Based)

  1. Still in the Identity Domain, in the left menu go to SecuritySign-on Policies.
  2. Either:
    • Edit the Default Sign-on Policy, or
    • Click Create sign-on policy to make a new one (recommended if you want gradual rollout).
  3. In the policy:
    • Add a Rule (or edit an existing one) that applies to:
      • Users: all users, or target a specific Group (e.g., admins) using conditions.
    • In the Actions section, set Prompt for second factor (MFA) = Required.
    • Optionally, configure:
      • Conditions like IP range, device, network, etc. if you want conditional MFA.
  4. Click Save or Create and ensure the policy is Enabled.
  5. Test with a non‑admin test account:
    • Log out, log in with the test user.
    • Confirm that, after password, the user is required to set up or use MFA.

Once MFA is enforced, any IAM Monitoring / Cloud Guard detectors for “user without MFA” will begin to show these users as compliant once they complete enrollment.


2. For Older “Local Users” (No Identity Domains UI)

If your tenancy still shows Identity → Users directly, use these steps:

A. Enroll MFA for Local Users

  1. In the OCI Console, click your user avatar (top right)User Settings.
  2. Under Multi-Factor Authentication, click Enable Multi-Factor Authentication or Add Device.
  3. Follow the prompts to set up:
    • An authenticator app (scan QR code, enter 6‑digit code).
  4. Each local user must repeat these steps for their own account.

Admins cannot completely finish MFA setup on behalf of users; users must scan and confirm.

B. Monitor / Enforce (Cloud Guard / IAM Monitoring)

To support the “OCI IAM Users Should Have MFA Enabled” rule:

  1. Go to Navigation menuIdentity & SecurityCloud Guard.
  2. Ensure Cloud Guard is Enabled in your region.
  3. Open your Detector Recipe (or create one) and verify that:
    • The relevant detector for IAM user without MFA (names vary; look under IAM / Authentication) is Enabled and Attached to your target (tenancy / compartment).
  4. For any flagged user in Cloud Guard → Problems:
    • Notify the user to follow the MFA enablement steps above.
    • After they enable MFA and re‑authenticate, the problem will eventually move to Resolved state.

3. Quick Checklist

  • MFA enrollment instructions sent to all affected users.
  • Identity Domain Sign-on Policy created/updated to require MFA.
  • Policy tested with a non‑admin test user.
  • Cloud Guard / IAM Monitoring detector recipe enabled for “Users without MFA”.
  • Confirm that previously flagged users show as compliant after MFA enrollment.

If you tell me whether your tenancy uses Identity Domains (you see “Domains” in the menu) or only “Identity → Users”, I can give you an even more exact click‑path for your specific layout.

Using CLI

Below is how you can remediate “OCI IAM Users Should Have MFA Enabled” using OCI CLI, focused on monitoring and identifying non‑MFA users (which is what Cloud Guard / IAM monitoring rules usually need).

Enabling MFA itself always requires a user interaction (scanning QR / entering OTP), so you cannot fully enable MFA purely by CLI; you can only prepare and enforce it and monitor which users are non‑compliant.


1. Prerequisites

  • OCI CLI installed and configured (oci setup config done).
  • Permissions to:
    • inspect/read users in the tenancy.
    • inspect/read MFA devices (for non–identity-domain IAM).
    • Or read identity domains and users (for identity domains).

Run once to confirm region and tenancy:

oci iam compartment list --all

If this returns compartments, CLI is working.


2. Detect IAM Users Without MFA (Traditional “local IAM” Tenancy)

2.1. List all IAM users

TENANCY_OCID="<your_tenancy_ocid>"

oci iam user list \
--compartment-id "$TENANCY_OCID" \
--all \
--query "data[].{name:\"name\", id:\"id\", lifecycle_state:\"lifecycle-state\"}" \
--output table

Filter for active users only:

oci iam user list \
--compartment-id "$TENANCY_OCID" \
--all \
--query "data[?\"lifecycle-state\"=='ACTIVE'].{name:\"name\", id:\"id\"}" \
--output json > users.json

2.2. For each user, check whether a TOTP MFA device exists

jq -r '.[].id' users.json | while read USER_OCID; do
MFA_COUNT=$(oci iam mfa-totp-device list \
--user-id "$USER_OCID" \
--query "data | length(@)" \
--output json)

if [ "$MFA_COUNT" -eq 0 ]; then
USER_NAME=$(oci iam user get --user-id "$USER_OCID" \
--query "data.name" --raw-output)
echo "User WITHOUT MFA: $USER_NAME ($USER_OCID)"
fi
done

This gives you a list of IAM users that do not have an MFA TOTP device associated.

You can store that list:

jq -r '.[].id' users.json | while read USER_OCID; do
MFA_COUNT=$(oci iam mfa-totp-device list \
--user-id "$USER_OCID" \
--query "data | length(@)" \
--output json)

if [ "$MFA_COUNT" -eq 0 ]; then
USER_NAME=$(oci iam user get --user-id "$USER_OCID" \
--query "data.name" --raw-output)
echo "{\"userName\":\"$USER_NAME\",\"userId\":\"$USER_OCID\"}" >> users_without_mfa.jsonl
fi
done

3. Detect Users Without MFA in an Identity Domain

If your tenancy uses identity domains (recommended modern setup):

3.1. List identity domains

oci iam identity-domain list \
--compartment-id "$TENANCY_OCID" \
--all \
--query "data[].{name:\"display-name\", id:\"id\"}" \
--output table

Pick the domain id:

DOMAIN_OCID="<your_identity_domain_ocid>"

3.2. List users in the identity domain

oci iam identity-domain user list \
--identity-domain-id "$DOMAIN_OCID" \
--all \
--query "resources[?active==true].{id:id, userName:userName}" \
--output json > domain_users.json

3.3. Check MFA factor enrollment per user

In identity domains, MFA status is reflected in urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User or factor-related attributes. A simple way is to fetch per user:

jq -r '.[].id' domain_users.json | while read USER_ID; do
USER_JSON=$(oci iam identity-domain user get \
--identity-domain-id "$DOMAIN_OCID" \
--user-id "$USER_ID" \
--output json)

MFA_ENABLED=$(echo "$USER_JSON" | \
jq -r '.["urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User"].mfaEnabled // false')

if [ "$MFA_ENABLED" != "true" ]; then
USER_NAME=$(echo "$USER_JSON" | jq -r '.userName')
echo "User WITHOUT MFA: $USER_NAME ($USER_ID)"
fi
done

(If mfaEnabled is not present in your domain, you may need to inspect the idcs extension schema for factors like mfaFactors/devices and adapt the jq filter.)


4. Enforce MFA Requirement via Policies (Preventive Control)

You cannot “flip” MFA on for a user via CLI, but you can enforce that interactive sign‑ins use MFA:

4.1. For identity domains – enable MFA requirement on sign‑on policy

  1. Identify the sign‑on policy:
oci iam identity-domain security-setting list \
--identity-domain-id "$DOMAIN_OCID" \
--all \
--output json

Look for mfaSettings or similar. If your domain has specific sign-on policies, list them:

oci iam identity-domain sign-on-policy list \
--identity-domain-id "$DOMAIN_OCID" \
--all \
--output json
  1. Update the sign-on policy to require MFA (example only – structure can vary):
SIGNON_POLICY_ID="<sign_on_policy_id>"

oci iam identity-domain sign-on-policy update \
--identity-domain-id "$DOMAIN_OCID" \
--sign-on-policy-id "$SIGNON_POLICY_ID" \
--from-json '{
"schemas":["urn:ietf:params:scim:schemas:oracle:idcs:SignOnPolicy"],
"rules":[
{
"name":"Require MFA",
"condition":"true",
"actions":[ { "type":"MFA", "require":"true" } ]
}
]
}'

Adjust JSON to match your existing rules rather than overwriting blindly.


In Cloud Guard or IAM Security posture checks:

  1. Use the above CLI scripts in a scheduled job (e.g. OCI Functions, OCI DevOps, or an external system) to:

    • Generate a list of users without MFA.
    • Push metrics to OCI Monitoring / logs to Logging or send notifications via Notifications service.
  2. Create alarms or Cloud Guard custom detectors that trigger on:

    • Logs (e.g. “user_without_mfa” entries).
    • Or a metric you emit (e.g. iam.non_mfa_users.count).

This lets “IAM Monitoring” show non‑MFA users and raise alerts, and your sign‑on policy enforces MFA for future logins.


If you share whether you’re using classic IAM or identity domains, I can adjust the exact CLI and jq filters to match your environment.

Using Python

Below is a step‑by‑step approach to detect and remediate IAM users without MFA in OCI, using Python.


1. Prerequisites

  1. Install OCI Python SDK:

    pip install oci
  2. Configure OCI CLI credentials (SDK uses the same config):

    oci setup config

    Note the tenancy_ocid, user_ocid, fingerprint, key_file, and region.

  3. The user/instance you use for this script must have IAM permissions like:

    Allow group <group_name> to manage users in tenancy

2. What You Can Do via API

For each IAM user:

  • Inspect MFA status via user.capabilities.mfa_activated.
  • Allow/force the ability to use MFA via can_use_mfa (but the user must still enroll using an authenticator).

So remediation is:

  1. Detect users with mfa_activated == False.
  2. Ensure can_use_mfa == True for them.
  3. Optionally: notify or disable users who still don’t enroll after a grace period.

3. Basic Python Script – Detect & Enable MFA Capability

This script:

  • Lists all users in the tenancy.
  • Filters to those that are ACTIVE and do not have MFA activated.
  • Sets can_use_mfa = True for those users.
import oci

def get_identity_client(config_profile="DEFAULT"):
config = oci.config.from_file("~/.oci/config", config_profile)
return oci.identity.IdentityClient(config), config["tenancy"]

def list_all_users(identity_client, tenancy_ocid):
users = []
response = identity_client.list_users(tenancy_ocid, limit=1000)
users.extend(response.data)
while response.has_next_page:
response = identity_client.list_users(
tenancy_ocid,
limit=1000,
page=response.next_page
)
users.extend(response.data)
return users

def remediate_mfa(identity_client, users, dry_run=True):
for user in users:
# Only ACTIVE users
if user.lifecycle_state != "ACTIVE":
continue

caps = user.capabilities
mfa_activated = getattr(caps, "mfa_activated", None)
can_use_mfa = getattr(caps, "can_use_mfa", None)

# Skip if MFA is already active
if mfa_activated:
continue

# If can_use_mfa is already True, user just hasn’t enrolled
if can_use_mfa:
print(f"[INFO] {user.name} can use MFA but has not activated it yet.")
continue

print(f"[REMEDIATE] Enabling MFA capability for user: {user.name} ({user.id})")

if not dry_run:
update_details = oci.identity.models.UpdateUserCapabilitiesDetails(
can_use_mfa=True
)
identity_client.update_user_capabilities(
user_id=user.id,
update_user_capabilities_details=update_details
)

def main():
identity_client, tenancy_ocid = get_identity_client("DEFAULT")
users = list_all_users(identity_client, tenancy_ocid)

# 1) DRY RUN – see what would change
print("=== DRY RUN: users that will be updated ===")
remediate_mfa(identity_client, users, dry_run=True)

# 2) REAL RUN – uncomment when ready
# print("=== REAL RUN: applying changes ===")
# remediate_mfa(identity_client, users, dry_run=False)

if __name__ == "__main__":
main()

4. Turn This Into “Monitoring”

Option A – Cron / Scheduled Job

  1. Put this script on a bastion host or CI runner.

  2. Run periodically via cron, e.g.:

    crontab -e
    # Run every hour
    0 * * * * /usr/bin/python3 /path/to/oci_mfa_remediation.py >> /var/log/oci_mfa.log 2>&1
  3. Keep dry_run=True if you only want monitoring and logging, or False for auto‑remediation.

Option B – Log / Notification Integration

Extend the script to:

  • Send an email/Slack message when users without MFA are found.
  • Or write JSON output to a file/stream that another system ingests.

Example (very minimal) JSON print for SIEM ingestion:

import json

def report_non_mfa_users(users):
report = []
for user in users:
if user.lifecycle_state == "ACTIVE" and not user.capabilities.mfa_activated:
report.append({
"user_name": user.name,
"user_ocid": user.id,
"can_use_mfa": user.capabilities.can_use_mfa
})
print(json.dumps(report, indent=2))

# Call this in main() after listing users

For stricter enforcement:

  • Use IAM policies and conditional access (in identity domains) to require MFA for console access.
  • Combine with the script above to ensure can_use_mfa=True for all users and then disable or quarantine users who don’t enroll in MFA after some time.

If you tell me whether you want pure monitoring (no changes) or full auto‑remediation (change users + possibly disable non‑compliant), I can adapt the script precisely.

Using Terraform

Terraform cannot enable or enforce MFA on an oci_identity_user; MFA enrollment in OCI is a per-user, interactive operation that is not exposed as an argument on oci_identity_user or any related Terraform resource.

To remediate, you must:

  • In the OCI Console, go to Identity & Security → Users → [TARGET_USER].
  • Use Multi-Factor Authentication (or Manage MFA) to enroll an MFA device for that user and complete the second‑factor setup flow.