Harness Hardening Guide
Software delivery platform hardening for Harness including SAML SSO, RBAC, secret management, and pipeline security
Overview
Harness is a leading software delivery platform providing CI/CD, feature flags, cloud cost management, and service reliability. As a platform managing deployments and infrastructure access, Harness security configurations directly impact software supply chain security.
Intended Audience
- Security engineers managing DevOps platforms
- Platform engineers configuring Harness
- DevOps teams managing pipelines
- GRC professionals assessing CI/CD 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 Harness security including SAML SSO, RBAC, secret management, and pipeline governance.
Table of Contents
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 Harness users.
Prerequisites
- Harness admin access
- SAML 2.0 compatible IdP
- Enterprise tier (for some features)
ClickOps Implementation
Step 1: Access Authentication Settings
- Navigate to: Account Settings → Authentication
- Select SAML Provider
Step 2: Configure SAML
- Click Add SAML Provider
- Configure IdP settings:
- Entity ID
- SSO URL
- Certificate
- Configure group mappings
Step 3: Test and Enable
- Test SSO authentication
- Configure SSO enforcement
- Document admin fallback
Time to Complete: ~1-2 hours
1.2 Enforce Two-Factor Authentication
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 6.5 |
| NIST 800-53 | IA-2(1) |
Description
Require 2FA for all Harness users.
ClickOps Implementation
Step 1: Enable 2FA Requirement
- Navigate to: Account Settings → Authentication
- Enable Two-Factor Authentication
- Configure enforcement policy
Step 2: Configure via IdP
- Enable MFA in identity provider
- Use phishing-resistant methods for admins
- All SSO users subject to IdP MFA
Code Implementation
Code Pack: Terraform
# Enforce two-factor authentication at the account level.
# Note: Harness 2FA enforcement is managed via Account Settings > Authentication
# in the UI. The Terraform provider manages this through account-level settings.
# The harness_platform_usergroup resources below ensure that all groups
# require SSO (which includes IdP-enforced MFA).
# Admin group with SSO-enforced MFA
resource "harness_platform_usergroup" "mfa_enforced_admins" {
identifier = "mfa_enforced_admins"
name = "MFA Enforced Administrators"
linked_sso_type = "SAML"
externally_managed = true
sso_linked = true
notification_configs {
type = "EMAIL"
send_email_to_all = true
}
}
# Service account for automation (exempt from interactive MFA, uses SAT)
resource "harness_platform_service_account" "automation" {
identifier = "hth_automation_sa"
name = "HTH Automation Service Account"
description = "Service account for automated operations -- authenticates via SAT, not interactive MFA"
email = "automation@harness.local"
account_id = var.harness_account_id
}
1.3 Configure IP Allowlisting
Profile Level: L2 (Hardened)
| Framework | Control |
|---|---|
| CIS Controls | 13.5 |
| NIST 800-53 | AC-17 |
Description
Restrict access to approved IP ranges.
ClickOps Implementation
Step 1: Configure IP Allowlist
- Navigate to: Account Settings → Security
- Enable IP allowlisting
- Add approved IP ranges
Code Implementation
Code Pack: Terraform
# IP allowlist restricts platform access to approved network ranges.
# Only applied at L2+ profile levels.
resource "harness_platform_ip_allowlist" "corporate" {
count = var.profile_level >= 2 && length(var.allowed_source_cidrs) > 0 ? 1 : 0
identifier = "hth_corporate_allowlist"
name = var.ip_allowlist_name
description = "Restrict access to approved corporate IP ranges (HTH Control 1.3)"
allowed_source_type = "IP_ADDRESS"
ip_address = var.allowed_source_cidrs[0]
enabled = true
}
# Additional allowlist entries for each CIDR beyond the first
resource "harness_platform_ip_allowlist" "corporate_additional" {
count = var.profile_level >= 2 ? max(length(var.allowed_source_cidrs) - 1, 0) : 0
identifier = "hth_corporate_allowlist_${count.index + 1}"
name = "${var.ip_allowlist_name} ${count.index + 2}"
description = "Additional corporate IP range ${count.index + 2} (HTH Control 1.3)"
allowed_source_type = "IP_ADDRESS"
ip_address = var.allowed_source_cidrs[count.index + 1]
enabled = true
}
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 Harness RBAC.
ClickOps Implementation
Step 1: Review Roles
- Navigate to: Account Settings → Access Control → Roles
- Review predefined roles:
- Account Admin
- Organization Admin
- Project Admin
- Pipeline Executor
- Create custom roles
Step 2: Configure Resource Groups
- Define resource groups
- Scope access to specific resources
- Apply least privilege
Step 3: Assign Permissions
- Assign roles to users/groups
- Use resource groups for scoping
- Regular access reviews
Code Implementation
Code Pack: Terraform
# Custom least-privilege roles for pipeline operators
resource "harness_platform_roles" "pipeline_executor" {
identifier = "hth_pipeline_executor"
name = "Pipeline Executor"
description = "Least-privilege role for executing pipelines without admin access (HTH Control 2.1)"
permissions = [
"core_pipeline_view",
"core_pipeline_execute",
"core_service_view",
"core_environment_view",
"core_connector_view"
]
allowed_scope_levels = ["project"]
}
# Read-only viewer role for auditors and observers
resource "harness_platform_roles" "viewer" {
identifier = "hth_viewer"
name = "Read-Only Viewer"
description = "Read-only role for auditors and observers (HTH Control 2.1)"
permissions = [
"core_pipeline_view",
"core_service_view",
"core_environment_view",
"core_connector_view",
"core_secret_view"
]
allowed_scope_levels = ["project"]
}
# Custom roles from variable input
resource "harness_platform_roles" "custom" {
for_each = var.custom_roles
identifier = each.key
name = each.value.name
description = "Custom role managed by HTH Code Pack (Control 2.1)"
permissions = each.value.permissions
allowed_scope_levels = each.value.allowed_scope_levels
}
# Resource group scoping pipeline resources at the project level
resource "harness_platform_resource_group" "project_pipelines" {
identifier = "hth_project_pipelines"
name = "Project Pipelines"
description = "Resource group scoped to pipeline resources within a project (HTH Control 2.1)"
account_id = var.harness_account_id
included_scopes {
filter = "INCLUDING_CHILD_SCOPES"
}
resource_filter {
include_all_resources = false
resources {
resource_type = "PIPELINE"
}
resources {
resource_type = "SERVICE"
}
resources {
resource_type = "ENVIRONMENT"
}
}
}
2.2 Configure Organization/Project Hierarchy
Profile Level: L2 (Hardened)
| Framework | Control |
|---|---|
| CIS Controls | 5.4 |
| NIST 800-53 | AC-6 |
Description
Use hierarchy for access isolation.
ClickOps Implementation
Step 1: Define Organization Structure
- Create organizations for business units
- Create projects within organizations
- Separate production and development
Step 2: Configure Scoped Access
- Assign users at appropriate level
- Use project-level access for least privilege
- Audit cross-project access
Code Implementation
Code Pack: Terraform
# Organizations for business unit isolation (L2+)
resource "harness_platform_organization" "org" {
for_each = var.profile_level >= 2 ? var.organizations : {}
identifier = each.key
name = each.value.name
description = each.value.description != "" ? each.value.description : "Organization managed by HTH Code Pack (Control 2.2)"
}
# Projects within organizations for environment isolation (L2+)
resource "harness_platform_project" "project" {
for_each = var.profile_level >= 2 ? var.projects : {}
identifier = each.key
name = each.value.name
org_id = each.value.org_id
color = each.value.color
depends_on = [harness_platform_organization.org]
}
# Resource group scoped to organization level for org-level access control
resource "harness_platform_resource_group" "org_scoped" {
for_each = var.profile_level >= 2 ? var.organizations : {}
identifier = "hth_org_${each.key}"
name = "${each.value.name} Resources"
description = "Organization-scoped resource group for ${each.value.name} (HTH Control 2.2)"
account_id = var.harness_account_id
org_id = each.key
included_scopes {
filter = "INCLUDING_CHILD_SCOPES"
org_id = each.key
}
resource_filter {
include_all_resources = true
}
depends_on = [harness_platform_organization.org]
}
2.3 Limit Admin Access
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 5.4 |
| NIST 800-53 | AC-6(1) |
Description
Minimize and protect administrator accounts.
ClickOps Implementation
Step 1: Inventory Admins
- Review account admins
- Document admin access
- Identify unnecessary privileges
Step 2: Apply Restrictions
- Limit account admin to 2-3 users
- Require 2FA/SSO for admins
- Monitor admin activity
Code Implementation
Code Pack: Terraform
# Restricted administrator user group -- limit to 2-3 members
resource "harness_platform_usergroup" "platform_admins" {
identifier = "hth_platform_admins"
name = var.admin_user_group_name
description = "Restricted platform administrator group -- limit to 2-3 members (HTH Control 2.3)"
notification_configs {
type = "EMAIL"
send_email_to_all = true
}
}
# Resource group for account-level admin operations
resource "harness_platform_resource_group" "account_admin" {
identifier = "hth_account_admin"
name = "Account Administration"
description = "Resource group for account-level administrative operations (HTH Control 2.3)"
account_id = var.harness_account_id
included_scopes {
filter = "INCLUDING_CHILD_SCOPES"
}
resource_filter {
include_all_resources = true
}
}
# Bind the Account Admin role to the restricted admin group
resource "harness_platform_role_assignments" "admin_binding" {
identifier = "hth_admin_binding"
resource_group_identifier = harness_platform_resource_group.account_admin.id
role_identifier = "_account_admin"
principal {
identifier = harness_platform_usergroup.platform_admins.id
type = "USER_GROUP"
}
disabled = false
managed = false
}
3. Secret Management
3.1 Configure Secret Manager
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 3.11 |
| NIST 800-53 | SC-12 |
Description
Securely manage secrets for pipelines.
ClickOps Implementation
Step 1: Configure Secret Manager
- Navigate to: Account Settings → Connectors → Secrets Managers
- Configure preferred secret manager:
- Harness Built-in
- HashiCorp Vault
- AWS Secrets Manager
- Azure Key Vault
- GCP Secret Manager
Step 2: Migrate Secrets
- Migrate existing secrets
- Reference secrets in pipelines
- Never hardcode credentials
Code Implementation
Code Pack: Terraform
# HashiCorp Vault connector for external secret management
resource "harness_platform_connector_vault" "vault" {
count = var.secret_manager_type == "vault" ? 1 : 0
identifier = "hth_vault_connector"
name = "HashiCorp Vault"
description = "External secret manager -- HashiCorp Vault (HTH Control 3.1)"
url = var.vault_url
access_type = "TOKEN"
default = true
read_only = false
renewal_interval_minutes = var.vault_renew_interval_minutes
secret_engine_name = var.vault_secret_engine
secret_engine_version = 2
use_vault_agent = false
use_aws_iam = false
use_k8s_auth = false
auth_token = var.vault_token
}
# AWS Secrets Manager connector
resource "harness_platform_connector_aws_secret_manager" "aws" {
count = var.secret_manager_type == "aws" ? 1 : 0
identifier = "hth_aws_secrets_connector"
name = "AWS Secrets Manager"
description = "External secret manager -- AWS Secrets Manager (HTH Control 3.1)"
default = true
secret_name_prefix = "harness/"
region = "us-east-1"
credentials {
inherit_from_delegate = true
}
}
# GCP Secret Manager connector
resource "harness_platform_connector_gcp_secret_manager" "gcp" {
count = var.secret_manager_type == "gcp" ? 1 : 0
identifier = "hth_gcp_secrets_connector"
name = "GCP Secret Manager"
description = "External secret manager -- GCP Secret Manager (HTH Control 3.1)"
default = true
is_default = true
credentials {
inherit_from_delegate = true
}
}
3.2 Configure Secret Access
Profile Level: L2 (Hardened)
| Framework | Control |
|---|---|
| CIS Controls | 3.11 |
| NIST 800-53 | SC-12 |
Description
Control access to secrets.
ClickOps Implementation
Step 1: Scope Secrets
- Create secrets at appropriate level
- Use project-scoped secrets
- Limit organization/account secrets
Step 2: Configure Permissions
- Restrict secret creation
- Limit secret viewing
- Audit secret access
Code Implementation
Code Pack: Terraform
# Resource group scoped to secret management resources (L2+)
resource "harness_platform_resource_group" "secrets" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_secret_resources"
name = var.secret_resource_group_name
description = "Resource group limiting access to secret management resources (HTH Control 3.2)"
account_id = var.harness_account_id
included_scopes {
filter = "INCLUDING_CHILD_SCOPES"
}
resource_filter {
include_all_resources = false
resources {
resource_type = "SECRET"
}
resources {
resource_type = "CONNECTOR"
attribute_filter {
attribute_name = "category"
attribute_values = ["SECRET_MANAGER"]
}
}
}
}
# Role restricting secret operations to approved personnel (L2+)
resource "harness_platform_roles" "secret_operator" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_secret_operator"
name = var.secret_manager_role_name
description = "Role for managing secrets without broader platform access (HTH Control 3.2)"
permissions = [
"core_secret_view",
"core_secret_edit",
"core_secret_delete",
"core_connector_view"
]
allowed_scope_levels = ["account", "organization", "project"]
}
# User group for secret management personnel (L2+)
resource "harness_platform_usergroup" "secret_managers" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_secret_managers"
name = "Secret Managers"
description = "User group with scoped access to secret management resources (HTH Control 3.2)"
notification_configs {
type = "EMAIL"
send_email_to_all = true
}
}
# Bind secret operator role to the secret managers group (L2+)
resource "harness_platform_role_assignments" "secret_binding" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_secret_binding"
resource_group_identifier = harness_platform_resource_group.secrets[0].id
role_identifier = harness_platform_roles.secret_operator[0].id
principal {
identifier = harness_platform_usergroup.secret_managers[0].id
type = "USER_GROUP"
}
disabled = false
managed = false
}
4. Pipeline Security
4.1 Configure Pipeline Governance
Profile Level: L2 (Hardened)
| Framework | Control |
|---|---|
| CIS Controls | 16.1 |
| NIST 800-53 | SA-15 |
Description
Implement pipeline governance controls.
ClickOps Implementation
Step 1: Configure OPA Policies
- Navigate to: Account Settings → Governance
- Create OPA policies
- Enforce pipeline standards
Step 2: Configure Approval Gates
- Add manual approval stages
- Configure approval groups
- Require approvals for production
Code Implementation
Code Pack: Terraform
# Default OPA policy requiring approval stages in production pipelines (L2+)
resource "harness_platform_policy" "require_approval" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_require_prod_approval"
name = "Require Production Approval Stage"
rego = <<-REGO
package pipeline
deny[msg] {
input.pipeline.stages[_].stage.type == "Deployment"
input.pipeline.stages[_].stage.spec.environment.type == "Production"
not has_approval_stage
msg := "Production deployments must include an approval stage (HTH Control 4.1)"
}
has_approval_stage {
input.pipeline.stages[_].stage.type == "Approval"
}
REGO
}
# Policy set enforcing governance on pipeline save events (L2+)
resource "harness_platform_policyset" "pipeline_governance" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_pipeline_governance"
name = "HTH Pipeline Governance"
action = "onsave"
type = "pipeline"
enabled = true
policies {
identifier = harness_platform_policy.require_approval[0].id
severity = "error"
}
}
# Custom OPA governance policies from variable input (L2+)
resource "harness_platform_policy" "custom" {
for_each = var.profile_level >= 2 ? var.governance_policies : {}
identifier = each.key
name = each.value.name
rego = each.value.rego
}
# L3: Strict policy requiring signed artifacts in production pipelines
resource "harness_platform_policy" "require_artifact_verification" {
count = var.profile_level >= 3 ? 1 : 0
identifier = "hth_require_artifact_verification"
name = "Require Artifact Verification"
rego = <<-REGO
package pipeline
deny[msg] {
stage := input.pipeline.stages[_].stage
stage.type == "Deployment"
stage.spec.environment.type == "Production"
artifact := stage.spec.serviceConfig.serviceDefinition.spec.artifacts.primary
not artifact.spec.digest
msg := "Production deployments must reference artifacts by digest, not tag (HTH Control 4.1 L3)"
}
REGO
}
# L3: Policy set with strict enforcement including artifact verification
resource "harness_platform_policyset" "strict_governance" {
count = var.profile_level >= 3 ? 1 : 0
identifier = "hth_strict_pipeline_governance"
name = "HTH Strict Pipeline Governance (L3)"
action = "onrun"
type = "pipeline"
enabled = true
policies {
identifier = harness_platform_policy.require_approval[0].id
severity = "error"
}
policies {
identifier = harness_platform_policy.require_artifact_verification[0].id
severity = "error"
}
}
4.2 Configure Audit Trail
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 8.2 |
| NIST 800-53 | AU-2 |
Description
Enable and monitor audit logs.
ClickOps Implementation
Step 1: Access Audit Trail
- Navigate to: Account Settings → Audit Trail
- Review logged events
- Configure retention
Step 2: Monitor Events
- Pipeline executions
- Configuration changes
- Permission modifications
- Secret access
Code Implementation
Code Pack: Terraform
# Note: Harness audit trail is enabled by default for all accounts.
# This configuration creates a service account and role for audit access,
# and optionally configures streaming destinations for log retention.
# Dedicated audit viewer role for compliance and security teams
resource "harness_platform_roles" "audit_viewer" {
identifier = "hth_audit_viewer"
name = "Audit Trail Viewer"
description = "Read-only role for accessing audit trail data (HTH Control 4.2)"
permissions = [
"core_audit_view"
]
allowed_scope_levels = ["account"]
}
# User group for audit/compliance personnel
resource "harness_platform_usergroup" "auditors" {
identifier = "hth_auditors"
name = "Audit & Compliance Team"
description = "User group with read-only access to audit trail (HTH Control 4.2)"
notification_configs {
type = "EMAIL"
send_email_to_all = true
}
}
# Resource group scoped to audit resources
resource "harness_platform_resource_group" "audit_resources" {
identifier = "hth_audit_resources"
name = "Audit Trail Resources"
description = "Resource group for audit trail access (HTH Control 4.2)"
account_id = var.harness_account_id
included_scopes {
filter = "INCLUDING_CHILD_SCOPES"
}
resource_filter {
include_all_resources = false
resources {
resource_type = "AUDIT"
}
}
}
# Bind audit viewer role to auditors group
resource "harness_platform_role_assignments" "audit_binding" {
identifier = "hth_audit_binding"
resource_group_identifier = harness_platform_resource_group.audit_resources.id
role_identifier = harness_platform_roles.audit_viewer.id
principal {
identifier = harness_platform_usergroup.auditors.id
type = "USER_GROUP"
}
disabled = false
managed = false
}
# Service account for automated audit log retrieval
resource "harness_platform_service_account" "audit_exporter" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_audit_exporter"
name = "Audit Log Exporter"
description = "Service account for automated audit log retrieval and streaming (HTH Control 4.2)"
email = "audit-exporter@harness.local"
account_id = var.harness_account_id
}
# API key for the audit exporter service account (L2+)
resource "harness_platform_apikey" "audit_exporter_key" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_audit_exporter_key"
name = "Audit Exporter API Key"
apikey_type = "SERVICE_ACCOUNT"
parent_id = harness_platform_service_account.audit_exporter[0].id
account_id = var.harness_account_id
}
# Token for the audit exporter API key (L2+)
resource "harness_platform_token" "audit_exporter_token" {
count = var.profile_level >= 2 ? 1 : 0
identifier = "hth_audit_exporter_token"
name = "Audit Exporter Token"
apikey_id = harness_platform_apikey.audit_exporter_key[0].id
apikey_type = "SERVICE_ACCOUNT"
parent_id = harness_platform_service_account.audit_exporter[0].id
account_id = var.harness_account_id
}
5. Compliance Quick Reference
SOC 2 Trust Services Criteria Mapping
| Control ID | Harness Control | Guide Section |
|---|---|---|
| CC6.1 | SSO/2FA | 1.1 |
| CC6.2 | RBAC | 2.1 |
| CC6.7 | Secret management | 3.1 |
| CC7.2 | Audit trail | 4.2 |
NIST 800-53 Rev 5 Mapping
| Control | Harness Control | Guide Section |
|---|---|---|
| IA-2 | SSO | 1.1 |
| IA-2(1) | 2FA | 1.2 |
| AC-6 | RBAC | 2.1 |
| SC-12 | Secret management | 3.1 |
| AU-2 | Audit trail | 4.2 |
Appendix A: References
Official Harness Documentation:
- Trust Center
- Harness Security
- Developer Hub
- Security Hardening for CI
- SAML SSO Configuration
- RBAC Documentation
API & Developer Tools:
Compliance Frameworks:
- SOC 2 Type II, ISO 27001, ISO 27017, ISO 27018 – via Trust Center
Security Incidents:
- No major public security incidents identified as of February 2026.
Changelog
| Date | Version | Maturity | Changes | Author |
|---|---|---|---|---|
| 2025-02-05 | 0.1.0 | draft | Initial guide with SSO, RBAC, and secret management | Claude Code (Opus 4.5) |
Contributing
Found an issue or want to improve this guide?
- Report outdated information: Open an issue with tag
content-outdated - Propose new controls: Open an issue with tag
new-control - Submit improvements: See Contributing Guide