Oracle HCM Cloud Hardening Guide
Enterprise HR security for security profiles, HDL controls, and IDCS integration
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
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
- Navigate to: Setup and Maintenance → Security Console
- Configure Identity Provider
- Enable: Enforce SSO
Step 2: Enable MFA
- Navigate to: IDCS → Security → MFA
- Configure:
- MFA factors (TOTP, Push, FIDO2)
- Enrollment policies
- Sign-on policies
Code Implementation
Code Pack: Terraform
# 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
- Navigate to: Setup and Maintenance → Manage Data Role and Security Profiles
- Create data roles with security profiles
- Assign to users via role provisioning
Code Implementation
Code Pack: Terraform
# 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
- Navigate to: Setup and Maintenance → Manage HCM Data Roles
- Configure:
- Person Security Profiles (who can be viewed)
- Organization Security Profiles (which orgs)
- Position Security Profiles
Step 2: Restrict Sensitive Data
- Limit compensation visibility
- Restrict payroll data access
- Configure country-specific restrictions
Code Implementation
Code Pack: Terraform
# 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
- Navigate to: IDCS → Applications → Add Application
- Create confidential application
- Configure:
- Allowed grant types (authorization_code preferred)
- Allowed scopes (minimum required)
- Redirect URIs (exact match)
Step 2: Scope Restrictions
Code Pack: Terraform
# 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
# 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
- Limit users with HDL privileges
- Require approval for bulk operations
- Enable detailed logging
Step 2: Secure File Transfer
- Use encrypted connections only
- Validate file integrity
- Monitor for bulk extracts
Code Implementation
Code Pack: Terraform
# 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
- Configure field-level security
- Mask sensitive fields (SSN, Bank Account)
- Enable audit for sensitive data access
Code Implementation
Code Pack: Terraform
# 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
- Navigate to: Setup and Maintenance → Manage Personal Data Removal
- Configure retention periods by data type
- Enable automated purge
Step 2: GDPR Compliance
- Configure data subject access requests
- Enable consent management
- Document processing activities
Code Implementation
Code Pack: Terraform
# 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
- Navigate to: Setup and Maintenance → Manage Audit Policies
- Enable audit for:
- User authentication events
- Data access (read/write)
- Security configuration changes
Step 2: Configure Audit Retention
- Set retention period (minimum 1 year)
- Export to SIEM
- Enable alerting
Detection Focus
Code Pack: Terraform
# 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
# 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:
- Oracle Cloud Compliance
- Oracle Corporate Security Practices
- Oracle HCM Cloud Documentation
- Best Practices for HCM Data Roles and Security Profiles
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) |