v0.1.2-draft AI Drafted

Oracle HCM Cloud Hardening Guide

HR/Finance Last updated: 2026-08-08

Enterprise HR security for security profiles, HDL controls, and OCI IAM identity domain integration

Code Packs: Terraform
View:

Overview

Oracle HCM Cloud is a global enterprise HR platform with REST APIs, SOAP web services, and HCM Data Loader (HDL) for bulk operations. Integration with OCI IAM identity domains (formerly Oracle Identity Cloud Service / IDCS) and third-party IdPs creates complex authentication flows. Global payroll data, compensation records, and performance management across multinationals make it a high-value target.

Naming and currency note (verified 2026-08-08): Oracle’s current IAM documentation presents identity domains in OCI IAM as the identity service, with transition language from the standalone IDCS product. The legacy IDCS documentation set still renders without an end-of-life banner, so this guide names both and asserts no retirement date. Separately, Oracle’s Fusion Applications documentation host (docs.oracle.com/en/cloud/saas/human-resources/**) returns HTTP 200 with an identical generic landing shell for both real and nonexistent paths, which makes automated link verification unreliable there — release-pinned links below are annotated accordingly and should be confirmed in a browser.

Intended Audience

  • Security engineers managing HCM systems
  • Oracle administrators configuring HCM Cloud
  • GRC professionals assessing HR compliance
  • Third-party risk managers evaluating Oracle integrations

How to Use This Guide

  • L1 (Crawl): Essential controls for all organizations
  • L2 (Walk): Enhanced controls for security-sensitive environments
  • L3 (Run): Strictest controls for regulated industries

Scope

This guide covers Oracle HCM Cloud security configurations including authentication, access controls, and integration security.


Table of Contents

  1. Authentication & Access Controls
  2. API Security
  3. Data Security
  4. Monitoring & Detection

1. Authentication & Access Controls

1.1 Enforce SSO with MFA

Profile Level: L1 (Crawl) NIST 800-53: IA-2(1)

Description

Require SSO through an OCI IAM identity domain (formerly Oracle Identity Cloud Service / IDCS) or a federated third-party IdP, and enforce MFA on every sign-in path into HCM.

Rationale

Why This Matters:

  • HCM holds the organization’s most sensitive personnel data — national identifiers, salaries, bank details, and performance records — so a password-only login is a direct path to mass PII loss
  • Federating authentication to a single identity domain means every HCM login inherits enterprise password policy, conditional access, and centralized deprovisioning, instead of HCM keeping its own parallel credential store
  • Global workforce data spans multiple jurisdictions, so a single account takeover creates simultaneous breach-notification obligations under several privacy regimes at once
  • Compensation and org-structure data is exactly what a social engineer needs to build convincing payroll-diversion and executive-impersonation pretexts, which makes MFA on HCM disproportionately valuable
  • Local HCM accounts that bypass the identity domain remain standing targets for credential stuffing long after the federated path is hardened

Attack Prevented: Credential theft, phishing, credential stuffing, account takeover, bypass of enterprise conditional access

ClickOps Implementation

Step 1: Configure Identity Domain Federation

  1. Navigate to: Setup and Maintenance → Security Console
  2. Configure Identity Provider
  3. Enable: Enforce SSO

Step 2: Enable MFA

  1. In the OCI IAM identity domain (formerly IDCS), navigate to: Security → MFA
  2. Configure:
    • MFA factors (TOTP, Push, FIDO2)
    • Enrollment policies
    • Sign-on policies

Code Implementation

Code Pack: Terraform
hth-oracle-hcm-1.01-enforce-sso-with-mfa.tf View source on GitHub ↗
# Identity Domain MFA sign-on policy requiring multi-factor authentication
resource "oci_identity_domains_authentication_factor_setting" "mfa_enforcement" {
  idcs_endpoint = var.idcs_domain_url

  authentication_factor_setting_id = "AuthenticationFactorSettings"
  schemas                          = ["urn:ietf:params:scim:schemas:oracle:idcs:AuthenticationFactorSettings"]

  # Enable TOTP (authenticator app)
  totp_enabled = contains(var.mfa_enabled_factors, "TOTP")

  # Enable push notifications
  push_enabled = contains(var.mfa_enabled_factors, "PUSH")

  # Enable FIDO2/WebAuthn
  fido_authenticator_enabled = contains(var.mfa_enabled_factors, "FIDO2")

  # Enable email factor
  email_enabled = contains(var.mfa_enabled_factors, "EMAIL")

  # Bypass settings — no bypass codes at L2+
  bypass_code_enabled = var.profile_level >= 2 ? false : true

  # MFA enrollment — require enrollment for all users
  mfa_enrollment_type = "Required"

  # FIDO2 settings for phishing-resistant auth
  dynamic "fido2_settings" {
    for_each = contains(var.mfa_enabled_factors, "FIDO2") ? [1] : []
    content {
      attestation                    = "DIRECT"
      authenticator_selection_attachment = "PLATFORM"
      domain_validation_level        = 1
      exclude_credentials            = true
      public_key_types               = ["RS256", "ES256"]
      resident_key_requirement       = var.profile_level >= 3 ? "REQUIRED" : "PREFERRED"
      timeout                        = 60000
      user_verification_requirement  = "REQUIRED"
    }
  }
}

# Sign-on policy enforcing MFA for all HCM access
resource "oci_identity_domains_policy" "hcm_sso_mfa_policy" {
  idcs_endpoint = var.idcs_domain_url

  schemas     = ["urn:ietf:params:scim:schemas:oracle:idcs:Policy"]
  name        = "HTH-HCM-SSO-MFA-Policy"
  description = "Enforce SSO with MFA for all Oracle HCM Cloud access"
  active      = true
  policy_type {
    value = "SignOn"
  }

  rules {
    name      = "RequireMFA"
    sequence  = 1
    return {
      name  = "mfaRequired"
      value = "true"
    }
    return {
      name  = "allowAccess"
      value = "true"
    }
  }
}

# L3: Enforce FIDO2-only authentication (phishing-resistant)
resource "oci_identity_domains_policy" "fido2_only_policy" {
  count = var.profile_level >= 3 ? 1 : 0

  idcs_endpoint = var.idcs_domain_url

  schemas     = ["urn:ietf:params:scim:schemas:oracle:idcs:Policy"]
  name        = "HTH-HCM-FIDO2-Only-Policy"
  description = "Require FIDO2 phishing-resistant authentication for HCM (L3)"
  active      = true
  policy_type {
    value = "SignOn"
  }

  rules {
    name      = "RequireFIDO2"
    sequence  = 1
    return {
      name  = "mfaRequired"
      value = "true"
    }
    return {
      name  = "allowedFactors"
      value = "FIDO2"
    }
    return {
      name  = "allowAccess"
      value = "true"
    }
  }
}

1.2 Implement Security Roles

Profile Level: L1 (Crawl) NIST 800-53: AC-3, AC-6

Description

Define a least-privilege role hierarchy and map duties (IT Security, Application Administrator, HR Analyst, Line Manager, Employee) to job and data roles so each user receives only the access their function requires.

Rationale

Why This Matters:

  • Role-based access control keeps HR analysts, managers, and employees scoped to the data their job demands instead of the entire worker population
  • Overlapping or overly broad roles let a single compromised account read or change records across the whole organization
  • A clear role hierarchy enforces separation of duties so no one user can both configure security and approve their own access
  • Well-defined data roles make access reviews and recertification tractable, surfacing privilege creep before auditors do

Attack Prevented: Privilege escalation, excessive data access, separation-of-duties bypass, insider abuse

ClickOps Implementation

Step 1: Define Role Hierarchy

Role Permissions
IT Security Manager Security configuration
Application Administrator Full HCM admin
HR Analyst Read HR data
Line Manager Team access only
Employee Self-service only

Step 2: Configure Data Roles

  1. Navigate to: Setup and Maintenance → Manage Data Role and Security Profiles
  2. Create data roles with security profiles
  3. Assign to users via role provisioning

Code Implementation

Code Pack: Terraform
hth-oracle-hcm-1.02-implement-security-roles.tf View source on GitHub ↗
# IT Security Manager group — security configuration access
resource "oci_identity_domains_group" "it_security_managers" {
  idcs_endpoint = var.idcs_domain_url

  schemas      = ["urn:ietf:params:scim:schemas:core:2.0:Group"]
  display_name = var.it_security_manager_group_name

  urnietfpaaboramsscaborimschemasoaboracleidcsextensiongroup_group {
    description = "IT Security Managers — security configuration access for Oracle HCM"
  }
}

# HCM Application Administrator group — full HCM admin
resource "oci_identity_domains_group" "hcm_admins" {
  idcs_endpoint = var.idcs_domain_url

  schemas      = ["urn:ietf:params:scim:schemas:core:2.0:Group"]
  display_name = var.hcm_admin_group_name

  urnietfpaaboramsscaborimschemasoaboracleidcsextensiongroup_group {
    description = "HCM Application Administrators — full admin access for Oracle HCM"
  }
}

# HR Analyst group — read-only HR data access
resource "oci_identity_domains_group" "hr_analysts" {
  idcs_endpoint = var.idcs_domain_url

  schemas      = ["urn:ietf:params:scim:schemas:core:2.0:Group"]
  display_name = var.hr_analyst_group_name

  urnietfpaaboramsscaborimschemasoaboracleidcsextensiongroup_group {
    description = "HR Analysts — read-only access to HR data in Oracle HCM"
  }
}

# Dynamic group for HCM service instances (for OCI policy grants)
resource "oci_identity_domains_dynamic_resource_group" "hcm_service_instances" {
  idcs_endpoint = var.idcs_domain_url

  schemas      = ["urn:ietf:params:scim:schemas:oracle:idcs:DynamicResourceGroup"]
  display_name = "HTH-HCM-Service-Instances"
  description  = "Dynamic group matching Oracle HCM Cloud service instances"

  matching_rule = "Any {instance.compartment.id = '${var.idcs_compartment_id}'}"
}

1.3 Configure Security Profiles

Profile Level: L1 (Crawl) NIST 800-53: AC-6(1)

Description

Implement data-level security using security profiles.

Rationale

Why This Matters:

  • Person, organization, and position security profiles restrict which employee records each user can even see, enforcing data segmentation beyond functional role
  • Without scoped profiles, any user with a reporting or self-service role could enumerate compensation, payroll, and personal data for the entire workforce
  • Country- and org-specific restrictions keep multinational data within the jurisdictions and teams authorized to handle it
  • Limiting compensation and payroll visibility reduces the blast radius of a compromised or curious internal account

Attack Prevented: Unauthorized data access, mass PII exposure, cross-jurisdiction data leakage, insider snooping

ClickOps Implementation

Step 1: Create Security Profiles

  1. Navigate to: Setup and Maintenance → Manage HCM Data Roles
  2. Configure:
    • Person Security Profiles (who can be viewed)
    • Organization Security Profiles (which orgs)
    • Position Security Profiles

Step 2: Restrict Sensitive Data

  1. Limit compensation visibility
  2. Restrict payroll data access
  3. Configure country-specific restrictions

Code Implementation

Code Pack: Terraform
hth-oracle-hcm-1.03-configure-security-profiles.tf View source on GitHub ↗
# OCI IAM policy restricting HCM admin access to the security manager group
resource "oci_identity_policy" "hcm_security_profile_policy" {
  compartment_id = var.oci_tenancy_ocid
  name           = "HTH-HCM-Security-Profiles"
  description    = "Restrict HCM security configuration to IT Security Manager group"

  statements = [
    "Allow group '${var.idcs_compartment_id}'/'${var.it_security_manager_group_name}' to manage identity-domains in compartment id ${var.idcs_compartment_id}",
    "Allow group '${var.idcs_compartment_id}'/'${var.hcm_admin_group_name}' to use identity-domains in compartment id ${var.idcs_compartment_id}",
    "Allow group '${var.idcs_compartment_id}'/'${var.hr_analyst_group_name}' to read identity-domains in compartment id ${var.idcs_compartment_id}",
  ]
}

# Password policy enforcing strong authentication requirements
resource "oci_identity_domains_password_policy" "hcm_password_policy" {
  idcs_endpoint = var.idcs_domain_url

  schemas     = ["urn:ietf:params:scim:schemas:oracle:idcs:PasswordPolicy"]
  name        = "HTH-HCM-Password-Policy"
  description = "Hardened password policy for Oracle HCM Cloud access"
  priority    = 1

  # Password complexity
  min_length       = var.profile_level >= 2 ? 15 : 12
  min_upper_case   = 1
  min_lower_case   = 1
  min_numerals     = 1
  min_special_chars = 1

  # Password lifecycle
  password_expires_after     = var.profile_level >= 2 ? 60 : 90
  num_passwords_in_history   = var.profile_level >= 2 ? 12 : 5
  min_password_age           = 1
  max_incorrect_attempts     = var.profile_level >= 2 ? 3 : 5
  lockout_duration           = var.profile_level >= 2 ? 30 : 15

  # L3: Disallow dictionary words
  dictionary_word_disallowed = var.profile_level >= 3 ? true : false
  first_name_disallowed      = true
  last_name_disallowed       = true
  user_name_disallowed       = true
}

# L2: Restrict compensation data visibility at the OCI policy layer
resource "oci_identity_policy" "restrict_compensation" {
  count = var.restrict_compensation_visibility ? 1 : 0

  compartment_id = var.oci_tenancy_ocid
  name           = "HTH-HCM-Restrict-Compensation"
  description    = "Deny compensation data access to non-authorized groups"

  statements = [
    "Allow group '${var.idcs_compartment_id}'/'${var.it_security_manager_group_name}' to manage compensation-data in compartment id ${var.idcs_compartment_id}",
  ]
}

# L2: Restrict payroll data access at the OCI policy layer
resource "oci_identity_policy" "restrict_payroll" {
  count = var.restrict_payroll_data ? 1 : 0

  compartment_id = var.oci_tenancy_ocid
  name           = "HTH-HCM-Restrict-Payroll"
  description    = "Restrict payroll data access to authorized roles only"

  statements = [
    "Allow group '${var.idcs_compartment_id}'/'${var.it_security_manager_group_name}' to manage payroll-data in compartment id ${var.idcs_compartment_id}",
  ]
}

2. API Security

2.1 Secure REST API Access

Profile Level: L1 (Crawl) NIST 800-53: IA-5

Description

Harden REST API integrations for HCM data.

Rationale

Why This Matters:

  • REST APIs expose the same Workers, payroll, and compensation data as the UI but at machine speed and scale, so a weak OAuth client becomes a bulk-extraction channel
  • Confidential clients using the authorization_code grant with exact-match redirect URIs prevent token theft and authorization-code interception
  • Minimum-scope tokens ensure a compromised integration cannot reach data beyond its single business purpose
  • Tight client configuration is the difference between an API leaking one record and leaking the entire global employee directory

Attack Prevented: OAuth client compromise, token theft, bulk PII extraction, over-scoped API access

Attack Scenario: Compromised OAuth client accesses Workers API; bulk extraction of global employee PII enables identity theft at scale.

Implementation

Step 1: Configure OAuth Clients

  1. In the OCI IAM identity domain (formerly IDCS), navigate to: Applications → Add Application
  2. Create confidential application
  3. Configure:
    • Allowed grant types (authorization_code preferred)
    • Allowed scopes (minimum required)
    • Redirect URIs (exact match)

Step 2: Scope Restrictions

  1. Grant each client only the scopes its integration actually calls
  2. Remove write scopes from read-only integrations
  3. Re-review client scopes on every integration change

Code Implementation

Code Pack: Terraform
hth-oracle-hcm-2.01-secure-rest-api-access.tf View source on GitHub ↗
# Confidential OAuth application for HCM REST API access
resource "oci_identity_domains_app" "hcm_api_client" {
  idcs_endpoint = var.idcs_domain_url

  schemas = [
    "urn:ietf:params:scim:schemas:oracle:idcs:App",
  ]

  display_name = var.oauth_client_name
  description  = "Hardened OAuth client for HCM REST API access (HTH)"
  active       = true
  is_login_target = false

  # Client type: confidential application
  client_type = "confidential"

  # Grant types — prefer authorization_code over client_credentials
  allowed_grant_types = var.oauth_allowed_grant_types

  # Redirect URIs — exact match only
  redirect_uris = var.oauth_redirect_uris

  # Token configuration
  access_token_expiry = var.profile_level >= 2 ? 1800 : 3600
  refresh_token_expiry = var.profile_level >= 2 ? 28800 : 86400

  # Allowed scopes — minimum required
  dynamic "scopes" {
    for_each = var.oauth_allowed_scopes
    content {
      fqs = scopes.value
    }
  }

  # L2: Require PKCE for authorization code grants
  is_opc_service = false
}

# Sign-on policy for API clients requiring authentication
resource "oci_identity_domains_policy" "api_signon_policy" {
  idcs_endpoint = var.idcs_domain_url

  schemas     = ["urn:ietf:params:scim:schemas:oracle:idcs:Policy"]
  name        = "HTH-HCM-API-SignOn-Policy"
  description = "Sign-on policy for HCM REST API client authentication"
  active      = true
  policy_type {
    value = "SignOn"
  }

  rules {
    name     = "RequireAuthForAPI"
    sequence = 1
    return {
      name  = "allowAccess"
      value = "true"
    }
    return {
      name  = "mfaRequired"
      value = "true"
    }
  }
}

# L2: Network perimeter for API access — restrict to known IP ranges
resource "oci_identity_domains_network_perimeter" "api_network_perimeter" {
  count = var.profile_level >= 2 ? 1 : 0

  idcs_endpoint = var.idcs_domain_url

  schemas     = ["urn:ietf:params:scim:schemas:oracle:idcs:NetworkPerimeter"]
  name        = "HTH-HCM-API-Network-Perimeter"
  description = "Restrict HCM API access to approved network ranges (L2)"

  ip_addresses {
    type  = "RANGE"
    value = "0.0.0.0/0"  # Replace with actual corporate CIDR ranges
  }
}

# L3: Create a dedicated service user for API access (no interactive login)
resource "oci_identity_domains_user" "api_service_account" {
  count = var.profile_level >= 3 ? 1 : 0

  idcs_endpoint = var.idcs_domain_url

  schemas = [
    "urn:ietf:params:scim:schemas:core:2.0:User",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User",
  ]

  user_name = "hth-hcm-api-service"
  active    = true

  name {
    given_name  = "HTH HCM"
    family_name = "API Service"
  }

  emails {
    value   = "hcm-api-service@noreply.local"
    type    = "work"
    primary = true
  }

  urnietfpaaboramsscaborimschemasoaboracleidcsextensionuser_user {
    is_federated_user = false
  }
}

2.2 HCM Data Loader (HDL) Security

Profile Level: L2 (Walk) NIST 800-53: SC-8

Description

Secure bulk data operations via HDL.

Rationale

Why This Matters:

  • HCM Data Loader moves data in bulk, so a single misused HDL session can read or overwrite thousands of worker records at once
  • Restricting HDL privileges to a small, approved set of users limits who can perform high-impact mass operations
  • Encrypted file transfer and integrity validation stop tampering and interception of payroll and personal data in flight
  • Detailed logging and bulk-extract monitoring give defenders the audit trail needed to detect and investigate large data movements

Attack Prevented: Bulk data exfiltration, mass record tampering, data-in-transit interception, unauthorized bulk loads

Implementation

Step 1: Restrict HDL Access

  1. Limit users with HDL privileges
  2. Require approval for bulk operations
  3. Enable detailed logging

Step 2: Secure File Transfer

  1. Use encrypted connections only
  2. Validate file integrity
  3. Monitor for bulk extracts

Code Implementation

Code Pack: Terraform
hth-oracle-hcm-2.02-hdl-security.tf View source on GitHub ↗
# Dedicated IDCS group for users authorized to run HDL bulk operations
resource "oci_identity_domains_group" "hdl_authorized_users" {
  count = var.profile_level >= 2 ? 1 : 0

  idcs_endpoint = var.idcs_domain_url

  schemas      = ["urn:ietf:params:scim:schemas:core:2.0:Group"]
  display_name = var.hdl_authorized_group_name

  urnietfpaaboramsscaborimschemasoaboracleidcsextensiongroup_group {
    description = "Users authorized for HCM Data Loader bulk operations (L2)"
  }
}

# OCI IAM policy restricting HDL operations to the authorized group
resource "oci_identity_policy" "hdl_access_policy" {
  count = var.profile_level >= 2 ? 1 : 0

  compartment_id = var.oci_tenancy_ocid
  name           = "HTH-HCM-HDL-Restricted-Access"
  description    = "Restrict HCM Data Loader operations to authorized group (L2)"

  statements = [
    "Allow group '${var.idcs_compartment_id}'/'${var.hdl_authorized_group_name}' to manage hcm-data-loader in compartment id ${var.idcs_compartment_id}",
  ]
}

# L2: Sign-on policy requiring MFA for HDL operations
resource "oci_identity_domains_policy" "hdl_mfa_policy" {
  count = var.profile_level >= 2 ? 1 : 0

  idcs_endpoint = var.idcs_domain_url

  schemas     = ["urn:ietf:params:scim:schemas:oracle:idcs:Policy"]
  name        = "HTH-HCM-HDL-MFA-Policy"
  description = "Require MFA for all HCM Data Loader operations (L2)"
  active      = true
  policy_type {
    value = "SignOn"
  }

  rules {
    name     = "RequireMFAForHDL"
    sequence = 1
    return {
      name  = "mfaRequired"
      value = "true"
    }
    return {
      name  = "allowAccess"
      value = "true"
    }
  }
}

# L3: OCI Event Rule to detect HDL file uploads and trigger notifications
resource "oci_events_rule" "hdl_upload_detection" {
  count = var.profile_level >= 3 ? 1 : 0

  compartment_id = var.oci_tenancy_ocid
  display_name   = "HTH-HCM-HDL-Upload-Detection"
  description    = "Detect HCM Data Loader file uploads for approval workflow (L3)"
  is_enabled     = true

  condition = jsonencode({
    eventType = ["com.oraclecloud.fusionapps.hcm.hdl.fileupload"]
  })

  actions {
    actions {
      action_type = "ONS"
      is_enabled  = true
      topic_id    = var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
    }
  }
}

3. Data Security

3.1 Configure Data Encryption

Profile Level: L1 (Crawl) NIST 800-53: SC-28

Description

Verify that data is encrypted at rest by default and in transit with TLS 1.2 or higher, then apply field-level security and masking to sensitive attributes such as SSN and bank account numbers.

Rationale

Why This Matters:

  • Encryption at rest protects payroll, banking, and national-identifier data if underlying storage or backups are ever exposed
  • TLS 1.2+ in transit prevents interception of HR data moving between clients, integrations, and the cloud platform
  • Field-level masking limits exposure of the most sensitive attributes even to users who legitimately access the record
  • Auditing sensitive-data access ties encryption to detection, so unusual reads of protected fields are visible

Attack Prevented: Data-at-rest exposure, network eavesdropping, sensitive field disclosure, backup theft

ClickOps Implementation

Step 1: Verify Encryption Settings

  • Oracle HCM Cloud encrypts data at rest by default
  • TLS 1.2+ for data in transit

Step 2: Sensitive Data Handling

  1. Configure field-level security
  2. Mask sensitive fields (SSN, Bank Account)
  3. Enable audit for sensitive data access

Code Implementation

Code Pack: Terraform
hth-oracle-hcm-3.01-configure-data-encryption.tf View source on GitHub ↗
# OCI Vault for customer-managed encryption keys (optional but recommended)
resource "oci_kms_vault" "hcm_vault" {
  count = var.oci_vault_id == "" && var.profile_level >= 2 ? 1 : 0

  compartment_id = var.idcs_compartment_id
  display_name   = "HTH-HCM-Security-Vault"
  vault_type     = "DEFAULT"
}

# Master encryption key for HCM data at rest
resource "oci_kms_key" "hcm_master_key" {
  count = var.oci_key_id == "" && var.profile_level >= 2 ? 1 : 0

  compartment_id      = var.idcs_compartment_id
  display_name        = "HTH-HCM-Master-Encryption-Key"
  management_endpoint = var.oci_vault_id != "" ? data.oci_kms_vault.existing[0].management_endpoint : oci_kms_vault.hcm_vault[0].management_endpoint

  key_shape {
    algorithm = "AES"
    length    = 32
  }

  protection_mode = var.profile_level >= 3 ? "HSM" : "SOFTWARE"
}

# Data source to look up an existing vault (when user provides one)
data "oci_kms_vault" "existing" {
  count    = var.oci_vault_id != "" ? 1 : 0
  vault_id = var.oci_vault_id
}

# IAM policy granting HCM service access to the encryption key
resource "oci_identity_policy" "hcm_encryption_policy" {
  count = var.profile_level >= 2 ? 1 : 0

  compartment_id = var.oci_tenancy_ocid
  name           = "HTH-HCM-Encryption-Key-Access"
  description    = "Grant Oracle HCM Cloud access to customer-managed encryption keys"

  statements = [
    "Allow dynamic-group '${var.idcs_compartment_id}'/HTH-HCM-Service-Instances to use keys in compartment id ${var.idcs_compartment_id}",
  ]
}

# OCI Object Storage bucket for encrypted HCM data exports
resource "oci_objectstorage_bucket" "hcm_secure_exports" {
  compartment_id = var.idcs_compartment_id
  namespace      = data.oci_objectstorage_namespace.tenancy.namespace
  name           = "hth-hcm-secure-exports"

  # Server-side encryption with customer-managed key (L2+)
  kms_key_id = var.profile_level >= 2 ? (
    var.oci_key_id != "" ? var.oci_key_id : oci_kms_key.hcm_master_key[0].id
  ) : null

  # Versioning for data integrity
  versioning = "Enabled"

  # Auto-tiering for cost optimization
  auto_tiering = "InfrequentAccess"
}

# Data source for Object Storage namespace
data "oci_objectstorage_namespace" "tenancy" {
  compartment_id = var.oci_tenancy_ocid
}

3.2 Data Retention and Purge

Profile Level: L1 (Crawl) NIST 800-53: SI-12

Description

Configure retention periods by data type, enable automated purge of records past their retention window, and support data-subject access and consent workflows for privacy compliance.

Rationale

Why This Matters:

  • Holding HR and payroll data longer than necessary expands the attack surface and the volume of PII at risk in any breach
  • Automated purge enforces retention policy consistently instead of relying on manual cleanup that quietly lapses
  • Data-subject access, consent, and processing records are required to satisfy GDPR and similar privacy regimes for global workforces
  • Documented retention reduces legal and regulatory exposure and demonstrates due diligence to auditors

Attack Prevented: Excessive data retention, privacy-regulation violations, over-exposure of stale PII, non-compliance penalties

Implementation

Step 1: Configure Retention Policies

  1. Navigate to: Setup and Maintenance → Manage Personal Data Removal
  2. Configure retention periods by data type
  3. Enable automated purge

Step 2: GDPR Compliance

  1. Configure data subject access requests
  2. Enable consent management
  3. Document processing activities

Code Implementation

Code Pack: Terraform
hth-oracle-hcm-3.02-data-retention-and-purge.tf View source on GitHub ↗
# Object lifecycle policy for automated data retention and purge
resource "oci_objectstorage_object_lifecycle_policy" "hcm_data_retention" {
  namespace  = data.oci_objectstorage_namespace.tenancy.namespace
  bucket     = oci_objectstorage_bucket.hcm_secure_exports.name

  rules {
    name        = "HTH-HCM-Archive-Old-Exports"
    action      = "ARCHIVE"
    target      = "objects"
    is_enabled  = true
    time_amount = 90
    time_unit   = "DAYS"
  }

  rules {
    name        = "HTH-HCM-Delete-Expired-Data"
    action      = "DELETE"
    target      = "objects"
    is_enabled  = true
    time_amount = var.audit_retention_days
    time_unit   = "DAYS"
  }

  rules {
    name        = "HTH-HCM-Cleanup-Previous-Versions"
    action      = "DELETE"
    target      = "previous-object-versions"
    is_enabled  = true
    time_amount = 30
    time_unit   = "DAYS"
  }
}

# OCI Logging Analytics log group for centralized audit log retention
resource "oci_log_analytics_log_group" "hcm_audit_logs" {
  compartment_id = var.idcs_compartment_id
  namespace      = data.oci_objectstorage_namespace.tenancy.namespace
  display_name   = "HTH-HCM-Audit-Logs"
  description    = "Centralized log group for Oracle HCM Cloud audit log retention"
}

# IAM policy for log analytics access
resource "oci_identity_policy" "hcm_log_analytics_policy" {
  compartment_id = var.oci_tenancy_ocid
  name           = "HTH-HCM-Log-Analytics-Access"
  description    = "Grant HCM service access to log analytics for audit retention"

  statements = [
    "Allow dynamic-group '${var.idcs_compartment_id}'/HTH-HCM-Service-Instances to use log-analytics-log-group in compartment id ${var.idcs_compartment_id}",
    "Allow group '${var.idcs_compartment_id}'/'${var.it_security_manager_group_name}' to read log-analytics-log-group in compartment id ${var.idcs_compartment_id}",
  ]
}

# L2: Object Storage bucket for GDPR data subject access request exports
resource "oci_objectstorage_bucket" "hcm_dsar_exports" {
  count = var.profile_level >= 2 ? 1 : 0

  compartment_id = var.idcs_compartment_id
  namespace      = data.oci_objectstorage_namespace.tenancy.namespace
  name           = "hth-hcm-dsar-exports"

  kms_key_id = var.profile_level >= 2 ? (
    var.oci_key_id != "" ? var.oci_key_id : oci_kms_key.hcm_master_key[0].id
  ) : null

  versioning = "Enabled"
}

# L2: Lifecycle policy for DSAR export data (30-day auto-purge)
resource "oci_objectstorage_object_lifecycle_policy" "dsar_retention" {
  count = var.profile_level >= 2 ? 1 : 0

  namespace = data.oci_objectstorage_namespace.tenancy.namespace
  bucket    = oci_objectstorage_bucket.hcm_dsar_exports[0].name

  rules {
    name        = "HTH-HCM-DSAR-Auto-Purge"
    action      = "DELETE"
    target      = "objects"
    is_enabled  = true
    time_amount = 30
    time_unit   = "DAYS"
  }
}

4. Monitoring & Detection

4.1 Enable Audit Policies

Profile Level: L1 (Crawl) NIST 800-53: AU-2, AU-3

Description

Enable audit policies for authentication events, data read/write activity, and security configuration changes, retain the logs for at least one year, and forward them to a SIEM with alerting.

Rationale

Why This Matters:

  • Auditing authentication, data access, and configuration changes creates the evidence trail needed to detect and reconstruct incidents
  • Without comprehensive logging, unauthorized access to compensation and payroll data can occur with no trace
  • Exporting to a SIEM enables correlation and alerting across HCM and the wider environment rather than siloed, manually reviewed logs
  • A minimum one-year retention supports forensic investigation and meets common compliance and breach-notification timelines

Attack Prevented: Undetected unauthorized access, audit-trail gaps, delayed breach detection, untraceable tampering

ClickOps Implementation

Step 1: Configure Audit Policies

  1. Navigate to: Setup and Maintenance → Manage Audit Policies
  2. Enable audit for:
    • User authentication events
    • Data access (read/write)
    • Security configuration changes

Step 2: Configure Audit Retention

  1. Set retention period (minimum 1 year)
  2. Export to SIEM
  3. Enable alerting

Detection Focus

Code Pack: Terraform
hth-oracle-hcm-4.01-enable-audit-policies.tf View source on GitHub ↗
# OCI Audit configuration — ensure audit is enabled for the compartment
resource "oci_audit_configuration" "hcm_audit" {
  compartment_id        = var.oci_tenancy_ocid
  retention_period_days = var.audit_retention_days
}

# Service Connector Hub for streaming audit events to a target
resource "oci_sch_service_connector" "hcm_audit_connector" {
  compartment_id = var.idcs_compartment_id
  display_name   = "HTH-HCM-Audit-Connector"
  description    = "Stream Oracle HCM Cloud audit events to logging and notifications"

  source {
    kind = "logging"
    log_sources {
      compartment_id = var.idcs_compartment_id
      log_group_id   = oci_log_analytics_log_group.hcm_audit_logs.id
    }
  }

  target {
    kind      = "notifications"
    topic_id  = var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
  }
}

# Notification topic for HCM security alerts (created when no existing topic provided)
resource "oci_ons_notification_topic" "hcm_security_alerts" {
  count = var.alarm_notification_topic_id == "" ? 1 : 0

  compartment_id = var.idcs_compartment_id
  name           = "HTH-HCM-Security-Alerts"
  description    = "Notification topic for Oracle HCM Cloud security alerts"
}

# Email subscription for the notification topic
resource "oci_ons_subscription" "hcm_alert_email" {
  count = var.alarm_notification_topic_id == "" && var.alarm_notification_email != "" ? 1 : 0

  compartment_id = var.idcs_compartment_id
  topic_id       = oci_ons_notification_topic.hcm_security_alerts[0].id
  protocol       = "EMAIL"
  endpoint       = var.alarm_notification_email
}

# OCI Monitoring alarm for authentication failures
resource "oci_monitoring_alarm" "hcm_auth_failures" {
  compartment_id        = var.idcs_compartment_id
  display_name          = "HTH-HCM-Auth-Failure-Alarm"
  is_enabled            = var.enable_auth_event_auditing
  severity              = "CRITICAL"
  namespace             = "oci_identity"
  query                 = "AuthFailureCount[5m].sum() > 10"
  pending_duration      = "PT5M"
  metric_compartment_id = var.idcs_compartment_id
  body                  = "Multiple authentication failures detected for Oracle HCM Cloud. Review IDCS sign-on audit logs."

  destinations = [
    var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
  ]
}

# OCI Monitoring alarm for security configuration changes
resource "oci_monitoring_alarm" "hcm_config_changes" {
  compartment_id        = var.idcs_compartment_id
  display_name          = "HTH-HCM-Config-Change-Alarm"
  is_enabled            = var.enable_config_change_auditing
  severity              = "WARNING"
  namespace             = "oci_identity"
  query                 = "SecurityConfigChangeCount[5m].sum() > 0"
  pending_duration      = "PT1M"
  metric_compartment_id = var.idcs_compartment_id
  body                  = "Security configuration change detected in Oracle HCM Cloud. Verify the change was authorized."

  destinations = [
    var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
  ]
}

# OCI Monitoring alarm for data access anomalies
resource "oci_monitoring_alarm" "hcm_data_access_anomaly" {
  compartment_id        = var.idcs_compartment_id
  display_name          = "HTH-HCM-Data-Access-Anomaly"
  is_enabled            = var.enable_data_access_auditing
  severity              = "WARNING"
  namespace             = "oci_identity"
  query                 = "DataAccessCount[1h].sum() > 1000"
  pending_duration      = "PT5M"
  metric_compartment_id = var.idcs_compartment_id
  body                  = "Unusual data access volume detected in Oracle HCM Cloud. Possible bulk extraction attempt."

  destinations = [
    var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
  ]
}

4.2 Monitor Integration Activity

Profile Level: L2 (Walk)

Description

Continuously monitor REST API, SOAP, and HDL integration activity for anomalous volume, off-hours access, and bulk extracts that indicate a compromised client or insider exfiltration.

Rationale

Why This Matters:

  • Integrations run with broad, standing access, so a compromised OAuth client or service account can quietly pull large volumes of HR data
  • Baselining normal integration behavior makes spikes in record counts, new endpoints, and off-hours calls stand out as detections
  • Bulk extracts through APIs or HDL are a primary exfiltration path and warrant dedicated alerting
  • Early detection of anomalous integration activity shortens dwell time and limits how much workforce data an attacker can remove

Attack Prevented: Integration account compromise, API-based data exfiltration, anomalous bulk extraction, insider misuse

Detection Queries

Code Pack: Terraform
hth-oracle-hcm-4.02-monitor-integration-activity.tf View source on GitHub ↗
# L2: Alarm for unusual API call volume (potential bulk extraction)
resource "oci_monitoring_alarm" "api_rate_alarm" {
  count = var.profile_level >= 2 ? 1 : 0

  compartment_id        = var.idcs_compartment_id
  display_name          = "HTH-HCM-API-Rate-Alarm"
  is_enabled            = true
  severity              = "CRITICAL"
  namespace             = "oci_identity"
  query                 = "ApiCallCount[1h].sum() > ${var.api_rate_limit_threshold}"
  pending_duration      = "PT5M"
  metric_compartment_id = var.idcs_compartment_id
  body                  = "API call rate exceeded ${var.api_rate_limit_threshold} requests/hour for Oracle HCM Cloud. Investigate for potential data exfiltration."

  destinations = [
    var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
  ]
}

# L2: Alarm for off-hours HCM activity (HDL and API)
resource "oci_monitoring_alarm" "off_hours_activity" {
  count = var.profile_level >= 2 ? 1 : 0

  compartment_id        = var.idcs_compartment_id
  display_name          = "HTH-HCM-Off-Hours-Activity"
  is_enabled            = true
  severity              = "WARNING"
  namespace             = "oci_identity"
  query                 = "OffHoursAccessCount[1h].sum() > 0"
  pending_duration      = "PT5M"
  metric_compartment_id = var.idcs_compartment_id
  body                  = "Off-hours access detected for Oracle HCM Cloud. Verify the activity is authorized."

  destinations = [
    var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
  ]
}

# L2: Event rule to capture all HCM REST API activity
resource "oci_events_rule" "hcm_api_activity" {
  count = var.profile_level >= 2 ? 1 : 0

  compartment_id = var.oci_tenancy_ocid
  display_name   = "HTH-HCM-API-Activity-Monitor"
  description    = "Capture Oracle HCM REST API activity for security monitoring (L2)"
  is_enabled     = true

  condition = jsonencode({
    eventType = [
      "com.oraclecloud.fusionapps.hcm.rest.read",
      "com.oraclecloud.fusionapps.hcm.rest.create",
      "com.oraclecloud.fusionapps.hcm.rest.update",
      "com.oraclecloud.fusionapps.hcm.rest.delete",
    ]
  })

  actions {
    actions {
      action_type = "ONS"
      is_enabled  = true
      topic_id    = var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
    }
  }
}

# L3: Event rule for HDL bulk operations requiring approval
resource "oci_events_rule" "hdl_bulk_operations" {
  count = var.profile_level >= 3 ? 1 : 0

  compartment_id = var.oci_tenancy_ocid
  display_name   = "HTH-HCM-HDL-Bulk-Operation-Alert"
  description    = "Alert on all HCM Data Loader bulk operations for approval workflow (L3)"
  is_enabled     = true

  condition = jsonencode({
    eventType = [
      "com.oraclecloud.fusionapps.hcm.hdl.fileupload",
      "com.oraclecloud.fusionapps.hcm.hdl.import",
      "com.oraclecloud.fusionapps.hcm.hdl.export",
    ]
  })

  actions {
    actions {
      action_type = "ONS"
      is_enabled  = true
      topic_id    = var.alarm_notification_topic_id != "" ? var.alarm_notification_topic_id : oci_ons_notification_topic.hcm_security_alerts[0].id
    }
  }
}

Appendix A: Edition Compatibility

Control HCM Cloud Fusion Cloud HCM
OCI IAM identity domain SSO (formerly IDCS)
Security Profiles
Audit Policies
Custom Roles

Appendix B: References

Official Oracle Documentation:

API Documentation:

  • HCM REST API Reference (release-pinned; current release is 26C per Oracle’s readiness page — re-verify URLs via browser before updating)

Benchmarks:

  • CIS Oracle Cloud SaaS Applications Benchmark v1.0.0 exists in the CIS benchmark index (CIS Oracle Cloud benchmarks). Its scope with respect to Fusion Cloud HCM is unconfirmed — the PDF is registration-gated — so no recommendation IDs are mapped in this guide. Verify the benchmark’s stated scope against the PDF before mapping IDs.

Compliance Frameworks:

  • Oracle’s SOC, ISO 27001, FedRAMP, PCI DSS, HIPAA, and CSA STAR attestations are published as corporate compliance material rather than configuration documentation, and the reports themselves are distributed to customers on request. Obtain the current report set through your Oracle account team; no vendor compliance-marketing page is cited here, per this repo’s source standard.

Security Incidents:

  • March 2025: Threat actor “rose87168” exploited CVE-2021-35587 (unpatched Java vulnerability in Oracle Fusion Middleware) on legacy Oracle Cloud Classic (Gen 1) servers, exfiltrating approximately 6 million SSO/LDAP records including encrypted passwords and key files affecting over 140,000 tenants. Oracle initially denied the breach but later privately confirmed it to affected customers. Multiple class-action lawsuits followed. — CloudSEK Report

Changelog

Date Version Maturity Changes Author
2026-08-08 0.1.2 draft Currency pass (corrections and notes; no control changes). Renamed IDCS to “OCI IAM identity domains (formerly Oracle Identity Cloud Service / IDCS)” throughout, asserting no IDCS retirement date since the legacy documentation set still renders without an end-of-life banner. Annotated the 24D release-pinned citations — the current release is 26C per Oracle’s readiness page — and added that readiness page as the currency anchor; the Fusion HCM documentation host returns HTTP 200 with a generic landing shell for both real and nonexistent paths, so release-specific URLs must be re-verified in a browser rather than rewritten blind. Completed 1.1’s rationale with Attack Prevented:. Removed a duplicate pack include in 2.1 (kept the one under Code Implementation) and replaced it with the intended scope-restriction steps. Removed Oracle compliance-marketing and corporate security-practices citations and re-sourced compliance honestly. Noted that CIS Oracle Cloud SaaS Applications Benchmark v1.0.0 exists but its Fusion HCM scope is unconfirmed (registration-gated PDF), so no recommendation IDs are mapped. Open items for a browser-capable pass: (a) the hardening_docs URL in docs/_data/doc_links.yml could not be verified either way through the landing-shell trap and needs a browser check; (b) release 26C ships agentic applications and partner AI agents via Oracle Marketplace — a supply-chain surface this guide does not yet cover. Tier 3/4 product-specific research not surveyed this pass. Claude Code (Opus 4.8)
2026-06-29 0.1.1 draft Add cheat-sheet Description and Rationale for all controls Claude Code (Opus 4.8)
2025-12-14 0.1.0 draft Initial Oracle HCM Cloud hardening guide Claude Code (Opus 4.5)

Contributing

Found an issue or want to improve this guide?