Configure OpenSearch SSO with Microsoft Entra ID
ClusterNest Managed OpenSearch can delegate Dashboards login to Microsoft Entra ID (Azure AD) over OIDC or SAML. A cluster takes several auth sources side by side, with at most one SAML source and one OIDC source offered on Dashboards.
You'll need your cluster's OpenSearch Dashboards hostname before registering the app. Set dashboards_custom_hostname so you know it upfront, or create the cluster first without an auth source and note the generated opensearch_dashboards_url output before adding it.
- OIDC
- SAML
OIDC
Set roles_key to "roles" if you use App roles, or "groups" if you use a group claim (and are prepared to map by object ID - Azure's default group claim emits object IDs, not names). Drop it to skip role mapping entirely.
- Console
- Terraform
- In the Entra admin center, go to App registrations > New registration.
- Redirect URI: platform Web,
https://<dashboards-hostname>/auth/openid/login
- Redirect URI: platform Web,
- Go to Certificates & secrets > New client secret, note the value (it's only shown once).
- Note the app's Application (client) ID and your Directory (tenant) ID, both on the app's Overview page.
- For role mapping, either add App roles (App registration > App roles, then assign users/groups under Enterprise applications > Users and groups) so they land in a
rolesclaim, or go to Token configuration > Add groups claim to emit group membership instead.
In the ClusterNest console, open the cluster's create/edit form and add an OIDC source under Authentication. Choose a Name (it becomes the text of the Dashboards button, "Login with" followed by this name), tick Offer on OpenSearch Dashboards, then fill in:
- Connect URL:
https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration - Client ID / Client Secret: from the app's Overview / Certificates & secrets pages
- Roles Key:
roles(orgroups; leave blank to skip role mapping)
The official hashicorp/azuread provider covers app registration end to end, wired into the same config as the ClusterNest cluster:
terraform {
required_providers {
azuread = {
source = "hashicorp/azuread"
version = "~> 3.0"
}
clusternest = {
source = "tf.clusternest.com/clusternest/clusternest"
version = ">=1.1.0"
}
}
}
provider "azuread" {}
provider "clusternest" {
email = "[email protected]"
password = var.clusternest_app_password
}
data "azuread_client_config" "current" {}
locals {
dashboards_hostname = "opensearch-dashboards.example.com"
}
resource "azuread_application" "opensearch" {
display_name = "OpenSearch Dashboards"
owners = [data.azuread_client_config.current.object_id]
web {
redirect_uris = ["https://${local.dashboards_hostname}/auth/openid/login"]
}
app_role {
allowed_member_types = ["User"]
description = "OpenSearch Dashboards users"
display_name = "opensearch-user"
id = "7c3f5e0a-6b1a-4e2a-9c1a-1f5a6b2e9d10"
value = "opensearch-user"
}
}
resource "azuread_service_principal" "opensearch" {
client_id = azuread_application.opensearch.client_id
owners = [data.azuread_client_config.current.object_id]
}
resource "azuread_application_password" "opensearch" {
application_id = azuread_application.opensearch.id
}
resource "clusternest_opensearch" "sso" {
name = "logs"
tier = "standard"
organization_id = 123
auth_sources = [
{
name = "azure"
type = "oidc"
connect_url = "https://login.microsoftonline.com/${data.azuread_client_config.current.tenant_id}/v2.0/.well-known/openid-configuration"
client_id = azuread_application.opensearch.client_id
client_secret = azuread_application_password.opensearch.value
roles_key = "roles"
dashboards_login = true
},
]
dashboards_custom_hostname = local.dashboards_hostname
}
app_role.id must be a UUID you generate yourself (uuidgen, or Terraform's random_uuid resource) - it's an opaque identifier, not a meaningful value. Assign users/groups to that role with azuread_app_role_assignment if you're using it, or drop the whole app_role block and use a group claim (roles_key = "groups") instead.
SAML
roles_key defaults to an ADFS-style claim URI - if you add a group claim under Attributes & Claims, set roles_key to its attribute name; otherwise leave it unset.
- Console
- Terraform
- In the Entra admin center, go to Enterprise applications > New application > Create your own application, choose "Integrate any other application you don't find in the gallery (Non-gallery)".
- Open the new app's Single sign-on page, select SAML, and edit Basic SAML Configuration:
- Identifier (Entity ID): the value you'll use as
sp_entity_idbelow - Reply URL (Assertion Consumer Service URL):
https://<dashboards-hostname>/_opendistro/_security/saml/acs
- Identifier (Entity ID): the value you'll use as
- Under Attributes & Claims, adjust the Unique User Identifier (Name ID) if needed, and add a group claim if you want role mapping - note the claim's attribute name.
- Under SAML Certificates, copy the App Federation Metadata Url as
idp_metadata_url. The Microsoft Entra Identifier shown in the "Set up <app>" section (https://sts.windows.net/<tenant-id>/) is youridp_entity_id. - Under Users and groups, assign the users/groups who should have access - Enterprise applications aren't reachable by anyone until assigned.
In the ClusterNest console, open the cluster's create/edit form and add a SAML source under Authentication. Choose a Name (it becomes the text of the Dashboards button, "Login with" followed by this name), then fill in:
- IDP Metadata URL: the App Federation Metadata Url from step 4
- IDP Entity ID:
https://sts.windows.net/<tenant-id>/ - SP Entity ID:
opensearch-dashboards - Roles Key: only if you added a group claim in step 3
The azuread provider can create the app and service principal, but not the SAML claims/Reply URL config (hashicorp/terraform-provider-azuread#806) - finish steps 2-3 from the Console tab by hand.
terraform {
required_providers {
azuread = {
source = "hashicorp/azuread"
version = "~> 3.0"
}
clusternest = {
source = "tf.clusternest.com/clusternest/clusternest"
version = ">=1.1.0"
}
}
}
provider "azuread" {}
provider "clusternest" {
email = "[email protected]"
password = var.clusternest_app_password
}
data "azuread_client_config" "current" {}
resource "azuread_application" "opensearch" {
display_name = "OpenSearch Dashboards"
owners = [data.azuread_client_config.current.object_id]
feature_tags {
enterprise = true
}
}
resource "azuread_service_principal" "opensearch" {
client_id = azuread_application.opensearch.client_id
owners = [data.azuread_client_config.current.object_id]
preferred_single_sign_on_mode = "saml"
}
# Finish SAML setup (Identifier, Reply URL, claims) in the Enterprise application's
# Single sign-on page in the console - see the Console tab - then fill in the
# metadata URL and issuer it gives you below.
resource "clusternest_opensearch" "sso" {
name = "logs"
tier = "standard"
organization_id = 123
auth_sources = [
{
name = "azure"
type = "saml"
idp_metadata_url = "https://login.microsoftonline.com/<tenant-id>/federationmetadata/2007-06/federationmetadata.xml?appid=${azuread_application.opensearch.client_id}"
idp_entity_id = "https://sts.windows.net/<tenant-id>/"
sp_entity_id = "opensearch-dashboards"
},
]
dashboards_custom_hostname = "opensearch-dashboards.example.com"
}
See the Terraform resource reference for the full field list.