Configure OpenSearch SSO with Okta
ClusterNest Managed OpenSearch can delegate Dashboards login to Okta over either OIDC or SAML. Pick one - auth_type accepts only a single mode per cluster.
You'll need your cluster's OpenSearch Dashboards hostname before registering the app. Set opensearch_dashboards_custom_hostname so you know it upfront, or create the cluster first with auth_type = "internal" and note the generated opensearch_dashboards_url output before switching it over.
- OIDC
- SAML
OIDC
connect_url is your Okta domain's discovery endpoint (or a custom authorization server's, if you used one instead of default).
- Console
- Terraform
- In the Okta admin console, go to Applications > Create App Integration, choose OIDC - Web Application.
- Sign-in redirect URIs:
https://<dashboards-hostname>/auth/openid/login - Assign the app to the users or groups who should have access.
- Sign-in redirect URIs:
- On the app's General tab, note the Client ID and Client secret.
- To get a
groupsclaim into the ID token, go to Security > API > Authorization Servers, pick the server you're using (defaultfor the org authorization server), open the Claims tab, and add a claim namedgroups(Include in: ID Token, Value type: Groups, Filter: matches a regex, e.g..*).
In the ClusterNest console, open the cluster's create/edit form and set Authentication Type to OIDC, then fill in:
- Connect URL:
https://example.okta.com/.well-known/openid-configuration - Client ID / Client Secret: from the app's General tab
- Roles Key:
groups(leave blank if you skipped step 3)
Okta's official provider (okta/okta) creates the app and the groups claim in the same config as the ClusterNest cluster:
terraform {
required_providers {
okta = {
source = "okta/okta"
version = "~> 5.0"
}
clusternest = {
source = "tf.clusternest.com/clusternest/clusternest"
version = ">=1.1.0"
}
}
}
provider "okta" {
org_name = "example"
base_url = "okta.com"
api_token = var.okta_api_token
}
provider "clusternest" {
email = "[email protected]"
password = var.clusternest_app_password
}
locals {
dashboards_hostname = "opensearch-dashboards.example.com"
}
resource "okta_app_oauth" "opensearch" {
label = "OpenSearch Dashboards"
type = "web"
grant_types = ["authorization_code"]
response_types = ["code"]
redirect_uris = ["https://${local.dashboards_hostname}/auth/openid/login"]
}
resource "okta_auth_server_claim" "groups" {
auth_server_id = "default"
name = "groups"
value_type = "GROUPS"
claim_type = "IDENTITY"
value = ".*"
}
resource "clusternest_opensearch" "sso" {
name = "logs"
tier = "standard"
organization_id = 123
auth_type = "oidc"
oidc_config = {
connect_url = "https://example.okta.com/.well-known/openid-configuration"
client_id = okta_app_oauth.opensearch.client_id
client_secret = okta_app_oauth.opensearch.client_secret
roles_key = "groups"
}
opensearch_dashboards_custom_hostname = local.dashboards_hostname
}
okta_app_oauth.opensearch.client_secret is computed once the app is created - it lands in plain text in the state file, same as any Terraform-managed secret. Drop the okta_auth_server_claim resource and roles_key if you don't need role mapping, and assign the app to users/groups separately with okta_app_group_assignment or okta_app_user.
SAML
idp_metadata_url and idp_entity_id come straight from Okta's own setup instructions. Drop roles_key if you don't need role mapping (it defaults to an ADFS-style claim URI Okta never emits).
- Console
- Terraform
- In the Okta admin console, go to Applications > Create App Integration, choose SAML 2.0.
- On the Configure SAML step:
- Single sign-on URL:
https://<dashboards-hostname>/_opendistro/_security/saml/acs(leave "Use this for Recipient URL and Destination URL" checked) - Audience URI (SP Entity ID): the value you'll use as
sp_entity_idbelow - Name ID format: EmailAddress
- Under Attribute Statements or Group Attribute Statements, add an attribute (e.g.
groups, matching a regex) if you want role mapping.
- Single sign-on URL:
- Assign the app to the relevant users/groups, then open its Sign On tab and click View SAML setup instructions - it lists the Identity Provider metadata URL and the Identity Provider Issuer.
In the ClusterNest console, open the cluster's create/edit form and set Authentication Type to SAML, then fill in:
- IDP Metadata URL:
https://example.okta.com/app/exkabc123/sso/saml/metadata - IDP Entity ID:
http://www.okta.com/exkabc123 - SP Entity ID:
opensearch-dashboards - Roles Key:
groups(leave blank if you skipped the attribute statement)
okta_app_saml exposes the resulting metadata URL and entity ID as computed attributes, so they can be wired directly into the clusternest_opensearch resource:
terraform {
required_providers {
okta = {
source = "okta/okta"
version = "~> 5.0"
}
clusternest = {
source = "tf.clusternest.com/clusternest/clusternest"
version = ">=1.1.0"
}
}
}
provider "okta" {
org_name = "example"
base_url = "okta.com"
api_token = var.okta_api_token
}
provider "clusternest" {
email = "[email protected]"
password = var.clusternest_app_password
}
locals {
dashboards_hostname = "opensearch-dashboards.example.com"
}
resource "okta_app_saml" "opensearch" {
label = "OpenSearch Dashboards"
sso_url = "https://${local.dashboards_hostname}/_opendistro/_security/saml/acs"
recipient = "https://${local.dashboards_hostname}/_opendistro/_security/saml/acs"
destination = "https://${local.dashboards_hostname}/_opendistro/_security/saml/acs"
audience = "opensearch-dashboards"
subject_name_id_template = "$${user.email}"
subject_name_id_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
attribute_statements {
type = "GROUP"
name = "groups"
filter_type = "REGEX"
filter_value = ".*"
}
}
resource "clusternest_opensearch" "sso" {
name = "logs"
tier = "standard"
organization_id = 123
auth_type = "saml"
saml_config = {
idp_metadata_url = okta_app_saml.opensearch.metadata_url
idp_entity_id = okta_app_saml.opensearch.entity_url
sp_entity_id = "opensearch-dashboards"
roles_key = "groups"
}
opensearch_dashboards_custom_hostname = local.dashboards_hostname
}
Drop the attribute_statements block and roles_key if you don't need role mapping.
See the Terraform resource reference for the full field list.