v0.1.0-draft AI Drafted

Oracle HCM Cloud Hardening Guide

HR/Finance Last updated: 2025-12-14

Enterprise HR security for security profiles, HDL controls, and IDCS integration

Code Packs: Terraform

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 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.

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 (Baseline): Essential controls for all organizations
  • L2 (Hardened): Enhanced controls for security-sensitive environments
  • L3 (Maximum Security): 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 (Baseline) NIST 800-53: IA-2(1)

Description

Require SSO via Oracle IDCS or federated IdP with MFA enforcement.

Rationale

Why This Matters:

  • HCM contains sensitive PII and payroll data
  • Global workforce data exposure impacts multiple jurisdictions
  • Compensation data is high-value for social engineering

ClickOps Implementation

Step 1: Configure IDCS Federation

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

Step 2: Enable MFA

  1. Navigate to: IDCS → 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 (Baseline) NIST 800-53: AC-3, AC-6

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 (Baseline) NIST 800-53: AC-6(1)

Description

Implement data-level security using security profiles.

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 (Baseline) NIST 800-53: IA-5

Description

Harden REST API integrations for HCM data.

Rationale

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. Navigate to: IDCS → 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

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
  }
}

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 (Hardened) NIST 800-53: SC-8

Description

Secure bulk data operations via HDL.

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 (Baseline) NIST 800-53: SC-28

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 (Baseline) NIST 800-53: SI-12

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 (Baseline) NIST 800-53: AU-2, AU-3

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 (Hardened)

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
IDCS SSO
Security Profiles
Audit Policies
Custom Roles

Appendix B: References

Official Oracle Documentation:

API Documentation:

Compliance Frameworks:

  • SOC 1 Type II, SOC 2 Type II, SOC 3, ISO 27001, FedRAMP High (U.S. Government Regions), PCI DSS, HIPAA, CSA STAR — via Oracle Cloud Compliance

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
2025-12-14 0.1.0 draft Initial Oracle HCM Cloud hardening guide Claude Code (Opus 4.5)