Configure Identity Provider
This article is for the team performing the Access Analyzer deployment. It covers the installer flags required to connect an identity provider at install time. If you are an application administrator setting up user accounts after the IdP connection is in place, see Identity Provider.
Related reading:
- Quick Install — Active Directory deployment using environment variables, end-to-end
- Installer Command Reference — full catalog of every installer flag and environment variable
- TLS Certificate Requirements — certificate formats, SAN rules, CA bundle preparation
Access Analyzer supports connecting an identity provider (IdP) so users authenticate through your organization's directory rather than with local credentials. IdP federation is optional — if you omit --idp-type at install time, Access Analyzer is deployed without Keycloak and uses local accounts only.
When --idp-type is configured, the installer automatically:
- Deploys Keycloak (v26.5.3) as part of the cluster
- Waits for Keycloak to become healthy
- Creates the IdP federation using the flags you provided
- Enables OIDC authentication in the Access Analyzer application
Before you begin
Confirm the following before running the installer with IdP flags:
- The Access Analyzer cluster system requirements are met — see Hardware and System Requirements
- TLS certificates are prepared and placed on the VM — see TLS Certificate Requirements
- You have collected the required credentials from the customer's IdP or directory administrator (see Identity Provider — Part 1)
- For LDAP/AD: the Access Analyzer server has network access to the LDAP server on port 636 (LDAPS) or 389 (LDAP)
- For a private CA certificate: you have the PEM file available on the server and will pass
--ca-bundle <path>to the installer
--hostname is required and must:
- Be a real DNS hostname (not an IP address — IPs will not work because the browser TLS handshake requires the hostname in the certificate's SAN).
- Be lowercase, and match lowercase in the certificate SAN list. Keycloak's OIDC issuer URL is derived from this value; a case mismatch between SAN and browser-normalized hostname produces HTTP 401 at sign-in.
- Resolve the same from client browsers and in-cluster pods. The installer configures the in-cluster rewrite automatically; the customer is responsible for the public DNS record or
/etc/hostsentry that client browsers use. - Avoid the
.localand.localhostTLDs — both break in-cluster DNS resolution and silently break OIDC login flows.
For full certificate format and preparation details, see TLS Certificate Requirements.
Choosing an IdP type
--idp-type value | Use case |
|---|---|
ad | Active Directory via LDAP (on-premises) |
ldap | Generic LDAP |
--idp-alias must match [A-Za-z0-9._-]+ — letters, digits, hyphens, underscores, and dots only. Spaces are not allowed. The alias is shown as the label on the login button.
Configure Active Directory
For a step-by-step end-to-end walkthrough using environment variables (recommended for most customers), see the Quick Install. The section below is the flag-level reference.
Required flags: --idp-type ad, --idp-alias, --ldap-url, --ldap-bind-dn, --ldap-users-dn
Optional: --ldap-email-attribute (default: mail)
Prompted secret: LDAP bind credential — entered interactively, never written to disk or logs
If your domain controller's LDAPS certificate is signed by an internal CA not in the OS trust store (typical for on-prem AD), pass the root CA cert via --ca-bundle. Without it, Keycloak's LDAPS handshake to the DC will fail with a TLS trust error. The CA that signed the DC's LDAPS certificate may be different from the CA that signed your Access Analyzer server's TLS certificate — verify the DC's cert chain specifically. See TLS Certificate Requirements for details on assembling the CA bundle.
export LICENSE_KEY='[YOUR_LICENSE_KEY]'
curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- \
--hostname aa2601.corp.example.com \
--tls-cert /opt/dspm-tls/aa2601.crt \
--tls-key /opt/dspm-tls/aa2601.key \
--ca-bundle /opt/dspm-tls/ca-bundle.crt \
--idp-type ad \
--idp-alias active-directory \
--ldap-url ldaps://dc.corp.example.com:636 \
--ldap-bind-dn "CN=svc-dspm,OU=ServiceAccounts,DC=corp,DC=example,DC=com" \
--ldap-users-dn "OU=Users,DC=corp,DC=example,DC=com"
Replace the LDAP URL with the customer's domain controller address (LDAPS on port 636 recommended). When prompted, enter the bind account password.
The ad type uses Active Directory–specific defaults: sAMAccountName for the username attribute and objectGUID for the UUID attribute.
Configure Generic LDAP
Use this type for OpenLDAP and other non-AD LDAP directories.
Required flags: --idp-type ldap, --idp-alias, --ldap-url, --ldap-bind-dn, --ldap-users-dn
Optional: --ldap-email-attribute (default: mail)
Prompted secret: LDAP bind credential
export LICENSE_KEY='[YOUR_LICENSE_KEY]'
curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- \
--hostname aa2601.corp.example.com \
--tls-cert /opt/dspm-tls/aa2601.crt \
--tls-key /opt/dspm-tls/aa2601.key \
--ca-bundle /opt/dspm-tls/ca-bundle.crt \
--idp-type ldap \
--idp-alias ldap \
--ldap-url ldaps://ldap.corp.example.com:636 \
--ldap-bind-dn "CN=svc-dspm,OU=ServiceAccounts,DC=corp,DC=example,DC=com" \
--ldap-users-dn "OU=Users,DC=corp,DC=example,DC=com"
As with the Active Directory section above, pass --ca-bundle with the root CA cert that signed the directory's LDAPS certificate when it is not in the OS trust store.
The ldap type uses generic LDAP defaults: uid for the username attribute and entryUUID for the UUID attribute.
Recover from a failed IdP configuration
If IdP configuration fails after the cluster is already running, use --configure-idp-only to retry without reinstalling K3s or ArgoCD:
curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- \
--configure-idp-only \
--idp-type ad \
--idp-alias active-directory \
--ldap-url ldaps://dc.corp.example.com:636 \
--ldap-bind-dn "CN=svc-dspm,OU=ServiceAccounts,DC=corp,DC=example,DC=com" \
--ldap-users-dn "OU=Users,DC=corp,DC=example,DC=com"
--configure-idp-only does not require --license-key. It skips all infrastructure provisioning steps and runs only the IdP configuration phase.
Next steps
After the installer completes IdP configuration, the application administrator must pre-provision user accounts in Access Analyzer before any users can sign in. See Identity Provider.
Manual configuration reference
The installer automates all of the following steps. Use this section only if you need to reconfigure or troubleshoot an IdP connection on a cluster that is already running, without re-running the installer.
Authenticate to the Keycloak Admin CLI
Run this step before any manual configuration. It authenticates the Keycloak Admin CLI inside the pod using the bootstrap credentials injected at deploy time.
kubectl exec -n access-analyzer statefulset/keycloak -- bash -c '
/opt/keycloak/bin/kcadm.sh config credentials \
--server http://localhost:8080/auth \
--realm master \
--user "$KC_BOOTSTRAP_ADMIN_USERNAME" \
--password "$KC_BOOTSTRAP_ADMIN_PASSWORD"'
The bootstrap admin credentials are read from environment variables already present in the pod. Don't pass them as command-line arguments — they would appear in Kubernetes audit logs.
Configure LDAP / Active Directory — manual
Required values: LDAP server URL, service account DN, service account password, users base DN
Step 1 — Create the LDAP User Federation component
LDAP_ID=$(kubectl exec -i -n access-analyzer statefulset/keycloak -- bash <<EOF
/opt/keycloak/bin/kcadm.sh create components -r dspm \
-s name=ldap \
-s providerType=org.keycloak.storage.UserStorageProvider \
-s providerId=ldap \
-s 'config.priority=["0"]' \
-s 'config.editMode=["READ_ONLY"]' \
-s 'config.vendor=["ad"]' \
-s 'config.connectionUrl=["<ldap-url>"]' \
-s 'config.bindDn=["<service-account-dn>"]' \
-s 'config.bindCredential=["<service-account-password>"]' \
-s 'config.usersDn=["<users-base-dn>"]' \
-s 'config.usernameLDAPAttribute=["sAMAccountName"]' \
-s 'config.rdnLDAPAttribute=["cn"]' \
-s 'config.uuidLDAPAttribute=["objectGUID"]' \
-s 'config.userObjectClasses=["person,organizationalPerson,user"]' \
-s 'config.searchScope=["2"]' \
-s 'config.importEnabled=["true"]' \
-s 'config.syncRegistrations=["false"]' \
-o --fields id | grep '"id"' | sed 's/.*"id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/'
EOF
)
Step 2 — Add the email attribute mapper
kubectl exec -n access-analyzer statefulset/keycloak -- \
/opt/keycloak/bin/kcadm.sh create components -r dspm \
-s name=email-mapper \
-s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper \
-s providerId=user-attribute-ldap-mapper \
-s "parentId=$LDAP_ID" \
-s '{"ldap.attribute":["mail"],"is.mandatory.in.ldap":["false"],"always.read.value.from.ldap":["false"],"read.only":["true"],"user.model.attribute":["email"]}'
Step 3 — Add the provider attribute mapper
kubectl exec -n access-analyzer statefulset/keycloak -- \
/opt/keycloak/bin/kcadm.sh create components -r dspm \
-s name=ldap-provider-attribute \
-s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper \
-s providerId=hardcoded-attribute-mapper \
-s "parentId=$LDAP_ID" \
-s '{"attribute.value":["ldap"],"user.model.attribute":["ldap_provider"]}'
Step 4 — Add the realm protocol mapper
kubectl exec -n access-analyzer statefulset/keycloak -- \
/opt/keycloak/bin/kcadm.sh create protocol-mappers/models -r dspm \
--body '{
"name": "ldap-identity-provider-claim",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "ldap_provider",
"claim.name": "identity_provider",
"jsonType.label": "String",
"id.token.claim": "true",
"access.token.claim": "true",
"userinfo.token.claim": "true"
}
}'
Verify the configuration — manual
LDAP (component check only):
TYPE=ldap ./scripts/verify-idp-config.sh
LDAP (with connectivity test):
TYPE=ldap \
LDAP_URL=<ldap-url> \
LDAP_BIND_DN=<service-account-dn> \
LDAP_BIND_CREDENTIAL=<service-account-password> \
./scripts/verify-idp-config.sh
Troubleshooting IdP configuration
IdP configuration runs as the final step of the installer, after Keycloak is healthy. A failure here means the cluster and applications are running correctly — only the identity federation is missing.
Check the installer log
The installer log contains the full kcadm.sh output:
grep -A 20 "Configuring IdP federation" /var/log/dspm-installer.log
Common error messages
| Message | Likely cause |
|---|---|
Failed to authenticate with Keycloak admin CLI | Keycloak pod not ready; check pod status below |
409 Conflict from kcadm.sh create | An IdP with this alias already exists in Keycloak |
PKIX path building failed in Keycloak logs (LDAP sign-ins fail silently) | CA bundle is missing the LDAPS DC's CA — see TLS Certificate Requirements |
Check Keycloak pod health
# Confirm the pod is running
kubectl get pods -n access-analyzer -l app=keycloak
# Check for recent errors in the Keycloak logs
kubectl logs -n access-analyzer statefulset/keycloak --tail=50
Retry using --configure-idp-only
If the cluster is healthy but IdP configuration failed, re-run the installer with --configure-idp-only. This skips K3s and ArgoCD entirely and retries only the Keycloak configuration:
curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- \
--configure-idp-only \
--hostname aa2601.corp.example.com \
--ca-bundle /opt/dspm-tls/ca-bundle.crt \
--idp-type <type> \
--idp-alias <alias> \
# ...same --idp-* flags used during the original install
--configure-idp-only does not require --license-key.
If retry fails with 409 Conflict
If a previous partial run created the IdP instance in Keycloak before failing (for example, during mapper creation), the retry fails with a 409 Conflict. Remove the partial IdP first using kcadm.sh inside the Keycloak pod.
Authenticate first:
kubectl exec -n access-analyzer statefulset/keycloak -- \
/opt/keycloak/bin/kcadm.sh config credentials \
--server http://localhost:8080/auth --realm master \
--user "$KC_BOOTSTRAP_ADMIN_USERNAME" \
--password "$KC_BOOTSTRAP_ADMIN_PASSWORD"
For LDAP or AD IdPs (child mappers cascade-delete automatically):
LDAP_ID=$(kubectl exec -n access-analyzer statefulset/keycloak -- \
/opt/keycloak/bin/kcadm.sh get components -r dspm \
-q name=<alias> \
-q type=org.keycloak.storage.UserStorageProvider \
--fields id -c \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d[0]['id'] if d else '')")
kubectl exec -n access-analyzer statefulset/keycloak -- \
/opt/keycloak/bin/kcadm.sh delete components/"${LDAP_ID}" -r dspm
Replace <alias> with the value that was passed to --idp-alias during the failed install. Then re-run --configure-idp-only.