v0.1.0-draft AI Drafted

Splunk Cloud Hardening Guide

Security Last updated: 2025-02-05

SIEM platform hardening for Splunk Cloud including SAML SSO, role-based access control, and data security

Code Packs: Terraform

Overview

Splunk is a leading SIEM and observability platform used by thousands of organizations for security monitoring, log analysis, and operational intelligence. As a platform that aggregates sensitive security and operational data, Splunk security configurations directly impact data protection.

Intended Audience

  • Security engineers managing SIEM platforms
  • IT administrators configuring Splunk Cloud
  • SOC analysts securing log infrastructure
  • GRC professionals assessing SIEM security

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 Splunk Cloud Platform security including SAML SSO, role-based access control, data security, and search security.


Table of Contents

  1. Authentication & SSO
  2. Access Controls
  3. Data Security
  4. Monitoring & Compliance
  5. Compliance Quick Reference

1. Authentication & SSO

1.1 Configure SAML Single Sign-On

Profile Level: L1 (Baseline)

Framework Control
CIS Controls 6.3, 12.5
NIST 800-53 IA-2, IA-8

Description

Configure SAML SSO to centralize authentication for Splunk Cloud users.

Prerequisites

  • Administrator access with change_authentication capability
  • SAML 2.0 compliant IdP with SHA-256 signatures
  • Contact Splunk Cloud Support to enable SAML

ClickOps Implementation

Step 1: Request SAML Enablement

  1. Contact Splunk Cloud Support
  2. Request SAML 2.0 enablement
  3. Once enabled, access SP metadata at: [yourSiteUrl]/saml/spmetadata

Step 2: Access SAML Configuration

  1. Navigate to: SettingsAuthentication Methods
  2. Under External, click SAML
  3. Click Configure Splunk to use SAML

Step 3: Configure SAML Settings

  1. Enter IdP settings:
    • Single Sign-on URL
    • IdP Certificate Chain (in order: root → intermediate → leaf)
    • Issuer ID
    • Entity ID
  2. Supported IdPs: PingIdentity, Okta, Microsoft Azure, ADFS, OneLogin

Step 4: Configure IdP

  1. IdP must provide: role, realName, mail attributes

Time to Complete: ~2 hours

Code Pack: Terraform
hth-splunk-1.1-configure-saml-sso.tf View source on GitHub ↗
# Configure SAML SSO authentication for centralized identity management.
# Requires SAML to be enabled by Splunk Cloud Support first.
# The splunk_configs_conf resource writes to authentication.conf.

# Enable SAML authentication method
resource "splunk_configs_conf" "auth_saml_settings" {
  count = var.saml_idp_url != "" ? 1 : 0

  name = "authentication/authentication"

  variables = {
    "authType"    = "SAML"
    "authSettings" = "hth_saml"
  }
}

# Configure the SAML stanza with IdP settings
resource "splunk_configs_conf" "auth_saml_idp" {
  count = var.saml_idp_url != "" ? 1 : 0

  name = "authentication/hth_saml"

  variables = {
    "fqdn"                        = replace(replace(var.splunk_url, "https://", ""), ":8089", "")
    "idpSSOUrl"                   = var.saml_idp_url
    "idpCertPath"                 = var.saml_idp_cert_path
    "entityId"                    = var.saml_entity_id
    "signAuthnRequest"            = "true"
    "signedAssertion"             = "true"
    "attributeQuerySoapPassword"  = ""
    "attributeQueryRequestSigned" = "true"
    "redirectAfterLogoutToUrl"    = var.saml_idp_url
    "nameIdFormat"                = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
    "ssoBinding"                  = "HTTPPost"
    "sloBinding"                  = "HTTPPost"
    "role"                        = "role"
    "realName"                    = "realName"
    "mail"                        = "mail"
  }

  depends_on = [splunk_configs_conf.auth_saml_settings]
}

1.2 Configure Local Admin Fallback

Profile Level: L1 (Baseline)

Framework Control
CIS Controls 5.4
NIST 800-53 AC-6

Description

Maintain local admin access for emergency recovery.

ClickOps Implementation

Step 1: Create Local Admin

  1. Create locally defined account with admin role
  2. This provides recovery option if SAML fails

Step 2: Document Local Login URL

  1. Local login: [yourSiteUrl]/en-US/account/login?loginType=splunk
  2. Document for emergency procedures

Step 3: Protect Local Credentials

  1. Use strong password (20+ characters)
  2. Store in password vault
Code Pack: Terraform
hth-splunk-1.2-configure-local-admin-fallback.tf View source on GitHub ↗
# Maintain a local admin account for emergency recovery when SAML is down.
# This account should use a strong password (20+ chars) stored in a vault.
# Local login URL: https://<instance>/en-US/account/login?loginType=splunk

resource "splunk_authentication_users" "emergency_admin" {
  count = var.local_admin_password != "" ? 1 : 0

  name              = var.local_admin_username
  password          = var.local_admin_password
  force_change_pass = false
  roles             = ["admin"]
  email             = "security-team@example.com"
  realname          = "HTH Emergency Admin"
}

2. Access Controls

2.1 Configure Role-Based Access Control

Profile Level: L1 (Baseline)

Framework Control
CIS Controls 5.4
NIST 800-53 AC-6

Description

Implement least privilege using Splunk’s role model.

ClickOps Implementation

Step 1: Review Default Roles

  1. Navigate to: SettingsAccess ControlsRoles
  2. Review built-in roles:
    • admin: Full administrative access
    • power: Advanced search and alerting
    • user: Standard search access

Step 2: Create Custom Roles

  1. Click New Role
  2. Configure capabilities and index access
  3. Apply minimum necessary permissions

Step 3: Assign Roles

  1. Assign through SAML mapping (preferred)
  2. Limit admin role to 2-3 users
Code Pack: Terraform
hth-splunk-2.1-configure-rbac.tf View source on GitHub ↗
# Implement least-privilege RBAC using custom roles.
# Avoid assigning the built-in admin role directly to users.
# Map roles through SAML for centralized governance.

# Custom security analyst role with restricted capabilities
resource "splunk_authorization_roles" "security_analyst" {
  name = var.custom_analyst_role_name

  # Minimal capabilities for security analysts
  capabilities = [
    "search",
    "schedule_search",
    "list_inputs",
    "get_metadata",
    "get_typeahead",
    "rest_properties_get",
  ]

  # Index access restrictions
  imported_roles    = ["user"]
  default_app       = "search"
  search_indexes_allowed = var.analyst_allowed_indexes
  search_indexes_default = [var.analyst_default_index]
}

# Restricted power user role (L2+) with tighter capabilities
resource "splunk_authorization_roles" "restricted_power" {
  count = var.profile_level >= 2 ? 1 : 0

  name = "hth_restricted_power"

  capabilities = [
    "search",
    "schedule_search",
    "list_inputs",
    "get_metadata",
    "get_typeahead",
    "rest_properties_get",
    "rtsearch",
    "edit_search_schedule_priority",
  ]

  imported_roles    = ["user"]
  default_app       = "search"
  search_indexes_allowed = var.analyst_allowed_indexes
  search_indexes_default = [var.analyst_default_index]
}

# Read-only auditor role (L2+) for compliance reviewers
resource "splunk_authorization_roles" "auditor" {
  count = var.profile_level >= 2 ? 1 : 0

  name = "hth_auditor"

  capabilities = [
    "search",
    "get_metadata",
    "get_typeahead",
    "rest_properties_get",
    "list_settings",
  ]

  imported_roles    = ["user"]
  default_app       = "search"
  search_indexes_allowed = ["_audit", "_internal", var.audit_index_name]
  search_indexes_default = ["_audit"]
}

2.2 Configure Index Access

Profile Level: L1 (Baseline)

Framework Control
CIS Controls 3.3
NIST 800-53 AC-3

Description

Restrict access to indexes based on role.

ClickOps Implementation

Step 1: Review Index Permissions

  1. Edit each role
  2. Configure Indexes searched by default

Step 2: Restrict Sensitive Indexes

  1. Security logs in restricted index
  2. Grant access only to security team
Code Pack: Terraform
hth-splunk-2.2-configure-index-access.tf View source on GitHub ↗
# Create dedicated indexes for security data with appropriate access controls.
# Restrict sensitive indexes to the security team through role-based access.

# Dedicated security log index
resource "splunk_indexes" "security" {
  name               = var.security_index_name
  datatype           = "event"
  max_hot_buckets    = 10
  max_data_size      = var.security_index_max_data_size
  frozen_time_period_in_secs = var.security_index_frozen_time_period
}

# Audit trail index with extended retention (L1)
resource "splunk_indexes" "audit_trail" {
  name               = var.audit_index_name
  datatype           = "event"
  max_hot_buckets    = 6
  max_data_size      = var.security_index_max_data_size
  frozen_time_period_in_secs = var.audit_index_frozen_time_period
}

# Threat intelligence index (L2+)
resource "splunk_indexes" "threat_intel" {
  count = var.profile_level >= 2 ? 1 : 0

  name               = "threat_intel"
  datatype           = "event"
  max_hot_buckets    = 3
  max_data_size      = "auto"
  frozen_time_period_in_secs = 31536000  # 1 year
}

3. Data Security

3.1 Configure Search Security

Profile Level: L1 (Baseline)

Framework Control
CIS Controls 3.3
NIST 800-53 AC-3

Description

Control what data users can search.

ClickOps Implementation

Step 1: Configure Search Restrictions

  1. Use role-based index restrictions
  2. Configure allowed sourcetypes

Step 2: Configure Search Quotas

  1. Configure search job quotas per role
  2. Prevent resource abuse
Code Pack: Terraform
hth-splunk-3.1-configure-search-security.tf View source on GitHub ↗
# Control what data users can search and enforce search quotas.
# Prevents resource abuse and limits data exposure.

# Search quota limits for standard users via limits.conf
resource "splunk_configs_conf" "search_limits_standard" {
  name = "limits/restapi"

  variables = {
    "maxresultrows" = "50000"
  }
}

# Configure search concurrency limits
resource "splunk_configs_conf" "search_scheduler_limits" {
  name = "limits/scheduler"

  variables = {
    "max_searches_perc"         = "50"
    "auto_summary_perc"         = "50"
    "max_action_results"        = "50000"
  }
}

# L2: Tighter search time window restrictions
resource "splunk_configs_conf" "search_limits_hardened" {
  count = var.profile_level >= 2 ? 1 : 0

  name = "limits/search"

  variables = {
    "max_searches_per_cpu"        = "1"
    "search_process_mode"         = "auto"
    "max_rt_search_multiplier"    = "1"
    "dispatch_dir_warning_size"   = "500"
  }
}

# L3: Maximum search restrictions
resource "splunk_configs_conf" "search_limits_maximum" {
  count = var.profile_level >= 3 ? 1 : 0

  name = "limits/searchresults"

  variables = {
    "maxresultrows"               = "10000"
    "max_count"                   = "10000"
    "compress_rawdata"            = "true"
  }
}

3.2 Configure Encryption

Profile Level: L1 (Baseline)

Framework Control
CIS Controls 3.11
NIST 800-53 SC-8, SC-28

Description

Ensure data encryption in transit and at rest.

ClickOps Implementation

Step 1: Verify Transit Encryption

  1. Splunk Cloud uses TLS by default

Step 2: Verify Storage Encryption

  1. Splunk Cloud encrypts data at rest
  2. Customer-managed keys available
Code Pack: Terraform
hth-splunk-3.2-configure-encryption.tf View source on GitHub ↗
# Ensure data encryption in transit and at rest.
# Splunk Cloud uses TLS by default; these settings harden the configuration.

# Enforce TLS on HTTP Event Collector
resource "splunk_global_http_event_collector" "hec_ssl" {
  disabled   = false
  enable_ssl = var.hec_enable_ssl
  port       = var.hec_port
}

# Enforce TLS settings in server.conf (L2+)
resource "splunk_configs_conf" "ssl_hardening" {
  count = var.profile_level >= 2 ? 1 : 0

  name = "server/sslConfig"

  variables = {
    "sslVersions"                 = "tls1.2"
    "sslVersionsForClient"        = "tls1.2"
    "cipherSuite"                 = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
    "ecdhCurves"                  = "prime256v1, secp384r1, secp521r1"
    "allowSslRenegotiation"       = "false"
    "requireClientCert"           = "false"
    "sslVerifyServerCert"         = "true"
    "sendStrictTransportSecurity" = "true"
  }
}

# Enforce TLS on web.conf for UI access (L2+)
resource "splunk_configs_conf" "web_ssl_hardening" {
  count = var.profile_level >= 2 ? 1 : 0

  name = "web/settings"

  variables = {
    "enableSplunkWebSSL"       = "true"
    "cipherSuite"              = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
    "ecdhCurves"               = "prime256v1, secp384r1, secp521r1"
    "sendStrictTransportSecurityHeader" = "true"
  }
}

# L3: Force TLS 1.3 only where supported
resource "splunk_configs_conf" "tls13_enforcement" {
  count = var.profile_level >= 3 ? 1 : 0

  name = "server/sslConfig"

  variables = {
    "sslVersions"          = "tls1.3"
    "sslVersionsForClient" = "tls1.3"
  }
}

4. Monitoring & Compliance

4.1 Configure Audit Logging

Profile Level: L1 (Baseline)

Framework Control
CIS Controls 8.2
NIST 800-53 AU-2

Description

Monitor administrative and security events.

ClickOps Implementation

Step 1: Access Audit Logs

  1. Search index=_audit
  2. Review authentication, configuration, and search events

Step 2: Create Audit Dashboards

  1. Build dashboard for audit events
  2. Monitor admin activities

Step 3: Configure Audit Alerts

  1. Alert on admin role changes
  2. Alert on failed authentications
Code Pack: Terraform
hth-splunk-4.1-configure-audit-logging.tf View source on GitHub ↗
# Monitor administrative and security events through the _audit index.
# Configure saved searches for audit alerting on critical actions.

# Enable audit trail forwarding to dedicated index
resource "splunk_configs_conf" "audit_trail_inputs" {
  name = "inputs/monitor:///opt/splunk/var/log/splunk/audit.log"

  variables = {
    "disabled"   = "false"
    "index"      = var.audit_index_name
    "sourcetype" = "splunk_audit"
  }
}

# Saved search: Alert on admin role changes (L1)
resource "splunk_saved_searches" "alert_role_changes" {
  name    = "HTH - Admin Role Changes"
  search  = "index=_audit action=edit_roles OR action=edit_user | stats count by user, action, info"

  is_scheduled  = true
  is_visible    = true
  cron_schedule = "*/15 * * * *"

  actions               = "email"
  action_email_to       = "security-team@example.com"
  action_email_subject  = "HTH Alert: Splunk Role Change Detected"

  alert_type            = "number of events"
  alert_comparator      = "greater than"
  alert_threshold       = "0"

  dispatch_earliest_time = "-15m"
  dispatch_latest_time   = "now"
}

# Saved search: Alert on failed authentications (L1)
resource "splunk_saved_searches" "alert_failed_auth" {
  name    = "HTH - Failed Authentication Attempts"
  search  = "index=_audit action=login status=failure | stats count by user, src | where count > 5"

  is_scheduled  = true
  is_visible    = true
  cron_schedule = "*/10 * * * *"

  actions               = "email"
  action_email_to       = "security-team@example.com"
  action_email_subject  = "HTH Alert: Multiple Failed Splunk Logins"

  alert_type            = "number of events"
  alert_comparator      = "greater than"
  alert_threshold       = "0"

  dispatch_earliest_time = "-10m"
  dispatch_latest_time   = "now"
}

# Saved search: Alert on configuration changes (L2+)
resource "splunk_saved_searches" "alert_config_changes" {
  count = var.profile_level >= 2 ? 1 : 0

  name    = "HTH - Configuration Changes"
  search  = "index=_internal sourcetype=splunkd component=ModifyConfig | stats count by user, action, object"

  is_scheduled  = true
  is_visible    = true
  cron_schedule = "*/30 * * * *"

  actions               = "email"
  action_email_to       = "security-team@example.com"
  action_email_subject  = "HTH Alert: Splunk Configuration Modified"

  alert_type            = "number of events"
  alert_comparator      = "greater than"
  alert_threshold       = "0"

  dispatch_earliest_time = "-30m"
  dispatch_latest_time   = "now"
}

# Saved search: Alert on search of sensitive indexes (L2+)
resource "splunk_saved_searches" "alert_sensitive_search" {
  count = var.profile_level >= 2 ? 1 : 0

  name    = "HTH - Sensitive Index Access"
  search  = "index=_audit action=search info=granted search=*${var.security_index_name}* NOT user=splunk-system-user | stats count by user, search"

  is_scheduled  = true
  is_visible    = true
  cron_schedule = "*/60 * * * *"

  actions               = "email"
  action_email_to       = "security-team@example.com"
  action_email_subject  = "HTH Alert: Sensitive Index Searched"

  alert_type            = "number of events"
  alert_comparator      = "greater than"
  alert_threshold       = "0"

  dispatch_earliest_time = "-60m"
  dispatch_latest_time   = "now"
}

5. Compliance Quick Reference

SOC 2 Trust Services Criteria Mapping

Control ID Splunk Control Guide Section
CC6.1 SSO/SAML 1.1
CC6.2 RBAC 2.1
CC6.7 Encryption 3.2
CC7.2 Audit logging 4.1

NIST 800-53 Rev 5 Mapping

Control Splunk Control Guide Section
IA-2 SSO 1.1
AC-3 Index access 2.2
AC-6 Least privilege 2.1
AU-2 Audit logging 4.1

Appendix A: References

Official Splunk Documentation:

API & Developer Tools:

Compliance Frameworks:

Security Incidents:

  • No major Splunk platform data breach publicly reported. In 2025, multiple Splunk Enterprise vulnerabilities were disclosed (CVE-2025-20371 SSRF, CVE-2025-20366 improper access control) requiring patches to versions 10.0.1+. These were product vulnerabilities, not breaches of Splunk’s hosted service.

Changelog

Date Version Maturity Changes Author
2025-02-05 0.1.0 draft Initial guide with SSO, RBAC, and data security Claude Code (Opus 4.5)

Contributing

Found an issue or want to improve this guide?