Grouper provisioning SCIM for Tableau
Grouper SCIM can provision groups, entities and memberships to Tableau.
External system
Go to settings in Tableau and enable SCIM, use the URL and the token
Groups
The displayName SCIM attribute for groups can be mapped to something in Grouper. If you want special chars perhaps use displayExtension. Otherwise the extension. The groups in Grouper can be in the same folder so there are no conflicts. Map the id as usual for SCIM
Entities
There is a bizarre Tableau name issue (in 2024, maybe fixed subsequently) where the user's first and last name is set in SAML but cannot be set in SCIM. These attributes can be mapped
id
email
familyName
givenName
userName
displayName
SampleConfig
provisioner.TableauProvisioner.addDisabledFullSyncDaemon = true
provisioner.TableauProvisioner.addDisabledIncrementalSyncDaemon = true
provisioner.TableauProvisioner.bearerTokenExternalSystemConfigId = Tableau
provisioner.TableauProvisioner.class = edu.internet2.middleware.grouper.app.scim2Provisioning.GrouperScim2Provisioner
provisioner.TableauProvisioner.customizeEntityCrud = true
provisioner.TableauProvisioner.customizeGroupCrud = true
provisioner.TableauProvisioner.customizeMembershipCrud = false
provisioner.TableauProvisioner.deleteEntities = false
provisioner.TableauProvisioner.deleteGroups = false
provisioner.TableauProvisioner.entityAttributeValueCache0entityAttribute = id
provisioner.TableauProvisioner.entityAttributeValueCache0has = true
provisioner.TableauProvisioner.entityAttributeValueCache0source = target
provisioner.TableauProvisioner.entityAttributeValueCache0type = entityAttribute
provisioner.TableauProvisioner.entityAttributeValueCache1entityAttribute = userName
provisioner.TableauProvisioner.entityAttributeValueCache1has = true
provisioner.TableauProvisioner.entityAttributeValueCache1source = target
provisioner.TableauProvisioner.entityAttributeValueCache1type = entityAttribute
provisioner.TableauProvisioner.entityAttributeValueCache2has = true
provisioner.TableauProvisioner.entityAttributeValueCache2source = grouper
provisioner.TableauProvisioner.entityAttributeValueCache2translationScript = ${subject.getAttributeValue('sn')}
provisioner.TableauProvisioner.entityAttributeValueCache2type = subjectTranslationScript
provisioner.TableauProvisioner.entityAttributeValueCache3has = true
provisioner.TableauProvisioner.entityAttributeValueCache3source = grouper
provisioner.TableauProvisioner.entityAttributeValueCache3translationScript = ${subject.getAttributeValue('givenName')}
provisioner.TableauProvisioner.entityAttributeValueCache3type = subjectTranslationScript
provisioner.TableauProvisioner.entityAttributeValueCacheHas = true
provisioner.TableauProvisioner.entityMatchingAttribute0name = userName
provisioner.TableauProvisioner.entityMatchingAttribute1name = id
provisioner.TableauProvisioner.entityMatchingAttributeCount = 2
provisioner.TableauProvisioner.groupAttributeValueCache0groupAttribute = id
provisioner.TableauProvisioner.groupAttributeValueCache0has = true
provisioner.TableauProvisioner.groupAttributeValueCache0source = target
provisioner.TableauProvisioner.groupAttributeValueCache0type = groupAttribute
provisioner.TableauProvisioner.groupAttributeValueCache1groupAttribute = displayName
provisioner.TableauProvisioner.groupAttributeValueCache1has = true
provisioner.TableauProvisioner.groupAttributeValueCache1source = target
provisioner.TableauProvisioner.groupAttributeValueCache1type = groupAttribute
provisioner.TableauProvisioner.groupAttributeValueCacheHas = true
provisioner.TableauProvisioner.groupMatchingAttribute0name = displayName
provisioner.TableauProvisioner.groupMatchingAttributeCount = 1
provisioner.TableauProvisioner.hasTargetEntityLink = true
provisioner.TableauProvisioner.hasTargetGroupLink = true
provisioner.TableauProvisioner.logAllObjectsVerbose = true
provisioner.TableauProvisioner.logCommandsAlways = true
provisioner.TableauProvisioner.makeChangesToEntities = true
provisioner.TableauProvisioner.numberOfEntityAttributes = 6
provisioner.TableauProvisioner.numberOfGroupAttributes = 2
provisioner.TableauProvisioner.operateOnGrouperEntities = true
provisioner.TableauProvisioner.operateOnGrouperGroups = true
provisioner.TableauProvisioner.operateOnGrouperMemberships = true
provisioner.TableauProvisioner.provisioningType = membershipObjects
provisioner.TableauProvisioner.scimType = generic
provisioner.TableauProvisioner.selectAllEntities = true
provisioner.TableauProvisioner.selectAllGroups = true
provisioner.TableauProvisioner.showAdvanced = true
provisioner.TableauProvisioner.startWith = this is start with read only
provisioner.TableauProvisioner.subjectSourcesToProvision = fischerLdapProd
provisioner.TableauProvisioner.targetEntityAttribute.0.insert = false
provisioner.TableauProvisioner.targetEntityAttribute.0.name = id
provisioner.TableauProvisioner.targetEntityAttribute.0.showAdvancedAttribute = true
provisioner.TableauProvisioner.targetEntityAttribute.0.showAttributeCrud = true
provisioner.TableauProvisioner.targetEntityAttribute.1.name = emailValue
provisioner.TableauProvisioner.targetEntityAttribute.1.translateExpression = ${grouperProvisioningEntity.getSubjectId() + '@isu.edu'}
provisioner.TableauProvisioner.targetEntityAttribute.1.translateExpressionType = translationScript
provisioner.TableauProvisioner.targetEntityAttribute.2.name = familyName
provisioner.TableauProvisioner.targetEntityAttribute.2.translateExpressionType = grouperProvisioningEntityField
provisioner.TableauProvisioner.targetEntityAttribute.2.translateFromGrouperProvisioningEntityField = entityAttributeValueCache2
provisioner.TableauProvisioner.targetEntityAttribute.3.name = givenName
provisioner.TableauProvisioner.targetEntityAttribute.3.translateExpressionType = grouperProvisioningEntityField
provisioner.TableauProvisioner.targetEntityAttribute.3.translateFromGrouperProvisioningEntityField = entityAttributeValueCache3
provisioner.TableauProvisioner.targetEntityAttribute.4.name = userName
provisioner.TableauProvisioner.targetEntityAttribute.4.translateExpression = ${grouperProvisioningEntity.getSubjectId() + '@isu.edu'}
provisioner.TableauProvisioner.targetEntityAttribute.4.translateExpressionType = translationScript
provisioner.TableauProvisioner.targetEntityAttribute.5.name = displayName
provisioner.TableauProvisioner.targetEntityAttribute.5.translateExpressionType = grouperProvisioningEntityField
provisioner.TableauProvisioner.targetEntityAttribute.5.translateFromGrouperProvisioningEntityField = name
provisioner.TableauProvisioner.targetGroupAttribute.0.insert = false
provisioner.TableauProvisioner.targetGroupAttribute.0.name = id
provisioner.TableauProvisioner.targetGroupAttribute.0.showAdvancedAttribute = true
provisioner.TableauProvisioner.targetGroupAttribute.0.showAttributeCrud = true
provisioner.TableauProvisioner.targetGroupAttribute.1.name = displayName
provisioner.TableauProvisioner.targetGroupAttribute.1.translateExpressionType = grouperProvisioningGroupField
provisioner.TableauProvisioner.targetGroupAttribute.1.translateFromGrouperProvisioningGroupField = displayExtension
provisioner.TableauProvisioner.updateEntities = false
provisioner.TableauProvisioner.updateGroups = false
We got this to work at SLAC... it was a simpler config. We only provision the entity attributes of id, email, userName. Here is our config:
provisioner.TableauScim.addDisabledFullSyncDaemon = true provisioner.TableauScim.addDisabledIncrementalSyncDaemon = true provisioner.TableauScim.bearerTokenExternalSystemConfigId = TableauCloudScim provisioner.TableauScim.class = edu.internet2.middleware.grouper.app.scim2Provisioning.GrouperScim2Provisioner provisioner.TableauScim.customizeGroupCrud = true provisioner.TableauScim.deleteGroupsIfGrouperDeleted = true provisioner.TableauScim.entityAttributeValueCache0entityAttribute = id provisioner.TableauScim.entityAttributeValueCache0has = true provisioner.TableauScim.entityAttributeValueCache0source = target provisioner.TableauScim.entityAttributeValueCache0type = entityAttribute provisioner.TableauScim.entityAttributeValueCacheHas = true provisioner.TableauScim.entityMatchingAttribute0name = userName provisioner.TableauScim.entityMatchingAttributeCount = 1 provisioner.TableauScim.groupAttributeValueCache0groupAttribute = id provisioner.TableauScim.groupAttributeValueCache0has = true provisioner.TableauScim.groupAttributeValueCache0source = target provisioner.TableauScim.groupAttributeValueCache0type = groupAttribute provisioner.TableauScim.groupAttributeValueCache1groupAttribute = displayName provisioner.TableauScim.groupAttributeValueCache1has = true provisioner.TableauScim.groupAttributeValueCache1source = target provisioner.TableauScim.groupAttributeValueCache1type = groupAttribute provisioner.TableauScim.groupAttributeValueCacheHas = true provisioner.TableauScim.groupMatchingAttribute0name = displayName provisioner.TableauScim.groupMatchingAttribute1name = id provisioner.TableauScim.groupMatchingAttributeCount = 2 provisioner.TableauScim.hasTargetEntityLink = true provisioner.TableauScim.hasTargetGroupLink = true provisioner.TableauScim.includeActiveOnGroupCreate = false provisioner.TableauScim.makeChangesToEntities = true provisioner.TableauScim.numberOfEntityAttributes = 3 provisioner.TableauScim.numberOfGroupAttributes = 2 provisioner.TableauScim.operateOnGrouperEntities = true provisioner.TableauScim.operateOnGrouperGroups = true provisioner.TableauScim.operateOnGrouperMemberships = true provisioner.TableauScim.provisioningType = membershipObjects provisioner.TableauScim.scimType = generic provisioner.TableauScim.selectAllEntities = true provisioner.TableauScim.showAdvanced = true provisioner.TableauScim.startWith = this is start with read only provisioner.TableauScim.subjectSourcesToProvision = slacPerson provisioner.TableauScim.targetEntityAttribute.0.insert = false provisioner.TableauScim.targetEntityAttribute.0.name = id provisioner.TableauScim.targetEntityAttribute.0.showAdvancedAttribute = true provisioner.TableauScim.targetEntityAttribute.0.showAttributeCrud = true provisioner.TableauScim.targetEntityAttribute.0.update = false provisioner.TableauScim.targetEntityAttribute.1.name = emailValue provisioner.TableauScim.targetEntityAttribute.1.translateExpressionType = grouperProvisioningEntityField provisioner.TableauScim.targetEntityAttribute.1.translateFromGrouperProvisioningEntityField = email provisioner.TableauScim.targetEntityAttribute.2.name = userName provisioner.TableauScim.targetEntityAttribute.2.translateExpressionType = grouperProvisioningEntityField provisioner.TableauScim.targetEntityAttribute.2.translateFromGrouperProvisioningEntityField = subjectId provisioner.TableauScim.targetGroupAttribute.0.insert = false provisioner.TableauScim.targetGroupAttribute.0.name = id provisioner.TableauScim.targetGroupAttribute.0.showAdvancedAttribute = true provisioner.TableauScim.targetGroupAttribute.0.showAttributeCrud = true provisioner.TableauScim.targetGroupAttribute.1.name = displayName provisioner.TableauScim.targetGroupAttribute.1.translateExpressionType = grouperProvisioningGroupField provisioner.TableauScim.targetGroupAttribute.1.translateFromGrouperProvisioningGroupField = extension provisioner.TableauScim.updateGroups = false