Skip to main content

Configure SCIM provisioning

Use System for Cross-domain Identity Management (SCIM) to provision directory users, groups, memberships, and deactivation from your identity provider. Stacklok Enterprise implements SCIM 2.0 (RFC 7644) as a service provider.

SCIM records display their source in the console. Update these records in the identity provider. To provision users from Okta without exposing an inbound SCIM endpoint, see Provision Okta users without a public SCIM endpoint.

Declare the issuer first

Add the provider under enterprise-manager.directory.issuers in the platform chart and create a Secret containing a random bearer token:

kubectl create secret generic directory-scim-token-okta \
-n <NAMESPACE> \
--from-literal=token="$(openssl rand -base64 32)"

Declare the issuer:

values.yaml
enterprise-manager:
directory:
# Absolute base URL for the SCIM endpoints. Set this whenever any issuer is
# configured: some providers reject relative URLs.
scimExternalBaseURL: 'https://<PLATFORM_HOST>'
issuers:
- id: 'okta-prod'
issuer_url: 'https://<TENANT>.okta.com'
audience: 'enterprise-manager'
binding_claim: 'uid'
scim_bearer_token_ref:
namespace: '<NAMESPACE>'
name: 'directory-scim-token-okta'
key: 'token'
FieldValue
idA short name you choose. It becomes a path segment, so keep it URL-safe
issuer_urlYour provider's OIDC discovery base URL, HTTPS only
audienceThe audience your provider puts in admin tokens
binding_claimThe claim carrying the stable per-user identifier: uid for Okta, oid for Entra
scim_bearer_token_refThe Secret you just created

provisioning_attribute is optional and defaults to externalId, the SCIM attribute whose value must match binding_claim. Change it only if your provider carries that identifier somewhere else.

The endpoint

The issuer's id determines its base URL:

https://<PLATFORM_HOST>/scim/<ISSUER_ID>/v2

Configure the identity provider with this base URL and the bearer token from the Secret. Standard discovery endpoints and the /Users and /Groups collections are available beneath the base path.

Give each additional provider its own issuers entry, id, and Secret.

What is supported

CapabilitySupportedNotes
Users and GroupsYesCreate, read, replace, delete
PATCHYesAdd, replace, and remove operations
FilteringYesUp to 200 results per request
SortingYessortBy and sortOrder
Bulk operationsNoReturns not-implemented; providers fall back to individual requests
ETagsNo
Password changeNoCredentials stay with your identity provider

Providers read these capabilities from /ServiceProviderConfig. Large initial syncs use individual requests because the service does not support SCIM bulk operations.

How records are matched

The directory matches a user by external identifier and issuer. Use a stable provider identifier so email or name changes update the existing record.

Group membership can reference both users and other groups, so a nested group structure in your provider arrives as subgroups here.

Set it up

  1. Declare the issuer and create its token Secret, then upgrade the release so the endpoint exists.
  2. Create the SCIM application, or enable provisioning on your existing single-sign-on application, in your identity provider.
  3. Set the base URL to https://<PLATFORM_HOST>/scim/<ISSUER_ID>/v2, using the id you chose.
  4. Supply the same bearer token you put in the Secret.
  5. Enable user provisioning and deactivation, then group provisioning.
  6. Push an initial sync, then confirm in the console under User management that users and groups appear with a SCIM source.

Start with a small test group to validate mappings before a full sync.

Create groups from user attributes

Stacklok Enterprise can create directory groups from attributes stored in SCIM user profiles, independent of your identity provider. Use this when properties such as department or costCenter define groups for connector access, budgets, or reporting.

Configure your identity provider's application profile mapping to include each attribute as a JSON string. Then add its SCIM attribute path to the existing issuer's group_variables list:

values.yaml
enterprise-manager:
directory:
scimExternalBaseURL: 'https://<PLATFORM_HOST>'
issuers:
- id: 'okta-prod'
issuer_url: 'https://<TENANT>.okta.com'
audience: 'enterprise-manager'
binding_claim: 'uid'
scim_bearer_token_ref:
namespace: '<NAMESPACE>'
name: 'directory-scim-token-okta'
key: 'token'
group_variables:
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department'
- 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:costCenter'

Use the path where the attribute appears in the stored SCIM user document, not the source profile property's display name. In your identity provider, inspect the application's profile mapping to find the target SCIM attribute. For Okta, open the application's Provisioning > To App mappings or inspect its okta_profile_mapping Terraform resource.

A top-level core attribute uses its attribute name. For example, this SCIM content uses userName:

Core user attribute
{
"userName": "alex@example.com"
}

An extension attribute uses its complete schema URN and attribute name. Standard organizational properties such as department and costCenter commonly appear in the enterprise user extension:

Enterprise extension attribute
{
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"department": "Marketing"
}
}

The corresponding path is urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department. Paths are case-sensitive and must match the keys stored in the SCIM user profile.

The variable-group reconciler does not provide a discovery log for attribute paths. Its skip logs identify only paths that are already present in group_variables. Use the identity provider's application profile mapping and schema as the source of truth. For Okta, use the target application's Provisioning > To App mappings or its okta_profile_mapping Terraform resource.

logRawOktaAPIData can confirm that Okta returned an expected profile value, but it does not identify the final stored SCIM path. Raw responses also contain sensitive identity data, so do not enable this setting solely to discover attribute paths.

The Enterprise Manager reconciles these groups hourly. For every distinct, non-empty string value on an active user, it creates a group and maintains its membership. It trims surrounding whitespace and folds letter case, so Marketing, marketing, and Marketing produce one group. Missing, null, empty, non-string, and longer-than-256-byte values produce no membership.

Choose attributes with a bounded set of organizational values. A per-user attribute such as userName creates one group per user. Administrators can use derived groups like other directory groups but cannot edit their names or membership directly.

When a value disappears or you remove a variable from configuration, the group is emptied. Empty groups remain for 90 days before deletion, preserving their stable identity and governance references during the grace period.

After upgrading the platform release, wait for the next hourly reconciliation. Open User management in the console and confirm that each expected value has a group containing the active users with that profile value.

After provisioning

Connector grants and budgets reference the provisioned directory groups. Define a stable naming convention before rollout and update references after renaming a group.

If you use cluster authorization policy, align SCIM directory groups with the OIDC group claims used in policy. See Directory groups and OIDC claim groups.

Next steps

Troubleshooting

Your provider cannot authenticate

Confirm that the token matches the Secret named in scim_bearer_token_ref. Check the Secret namespace and remove trailing newlines from the value.

The endpoint is not found

Use the issuer id from enterprise-manager.directory.issuers in the path and confirm that the release includes your updated values.

Groups provisioned by the identity provider are missing

Enable group provisioning after the initial user sync.

Groups from user attributes are missing

Confirm that group_variables is on the correct issuer and that the Enterprise Manager restarted after the configuration change. Verify that an active user's SCIM profile contains a non-empty string at the configured, case-sensitive path.

User deactivation does not take effect

Configure the provider to send deactivation.

Duplicate users appear

Check whether the external identifier changed in the provider. Reconcile the records there, then resync.