meshStack

meshStack

  • User Docs
  • Administrator Docs
  • API Docs
  • Release Notes
  • Feedback

›Identity & Access

Getting Started

  • How to get started with meshStack
  • AWS S3 Quickstart Guide
  • AKS Platform Quickstart Guide
  • AKS Developer Platform Guide

Concepts

  • Overview
  • Administration Roles
  • Onboarding
  • meshWorkspaces
  • meshProjects
  • meshTenants
  • Replication Configuration
  • Delete Tenants
  • meshUsers
  • meshPlatforms
  • Landing Zones
  • Open Service Brokers (OSB)
  • Guide: Emergency Users
  • Managing Tags
  • Policies
  • Unmanaged Tenants
  • meshStack Settings
  • Workspace Services
  • API Users
  • DNS and SSL Certificates
  • Customizing
  • Product Feedback Collection

Identity & Access

  • Identity and Access Management
  • Identity Provider
  • Identity Lookup
  • Authorization
  • User & Group LDAP Synchronisation
  • User & Group SCIM Synchronisation

Building Blocks

  • Building Blocks
  • Private Runners
  • Terraform/OpenTofu state managed by meshStack
  • Permission Delegation on AWS
  • Connecting meshStack and a Pipeline

Metering & Billing

  • Cost Management
  • Configuration

Amazon Web Services

  • Integration
  • Landing Zones
  • Metering
  • SSO Setup
  • Reserved Instances & Savings Plans Guide

Microsoft Azure

  • Integration
  • Landing Zones
  • Metering

Google Cloud Platform

  • Integration
  • Landing Zones
  • Metering

Cloud Foundry

  • Integration
  • Metering

Kubernetes

  • Integration
  • Landing Zones
  • Metering

GitHub

  • Pipeline Automation
  • Repository Provisioning

OpenShift

  • Integration
  • Landing Zones
  • Metering

OpenStack

  • Integration
  • Metering

OSB Services

  • Integration
  • Metering
  • meshcloud OSB API Profile
  • Tenant Services
  • Tutorial: Implement a Broker

Operations

  • Managed Service
  • Email
  • Logging & Auditing
  • Monitoring & Telemetry
  • Backup
  • Security FAQ

Guides

  • How to integrate a meshPlatform into meshStack
  • How to manually integrate AWS as meshPlatform
  • How to manually integrate Azure as meshPlatform
  • How to manually integrate GCP as meshPlatform
  • How to create your own platform
  • How to manage partner level permissions
  • How to use scoped API keys
  • How to setup and manage a Building block
Edit

User & Group LDAP Synchronisation

meshStack supports importing users and groups into meshStack from a source that supports the LDAP protocol, for example, Microsoft Active Directory. The Simple Paged Results Control is used to do a paginated LDAP query to fetch the users and groups. Because of this, it is required that the LDAP server supports the Simple Paged Results Control. Other than importing users and groups, meshStack also has the capability to assign a workspace role or partner role to the imported group. The entities read via LDAP are imported to meshStack via the meshStack API. At the moment, we only support the import of three kinds of meshObjects: meshUser, meshGroup and meshWorkspaceGroupBinding. The other meshObjects, such as meshProjectUserBindings can be created via the panel.

Configuration Reference

This section describes how to configure the LDAP group synchronization in meshStack.

The synchronization process is done in three parts.

  • Collect
  • Transform
  • Transport

Collect

In the "Collect" step, we connect to the LDAP server and fetch the LDAP entities. In order to do that, the configuration needs to contain the information required to establish a connection with the LDAP server. The configuration model is as follows.

Dhall Type
Example
let SourceConfiguration =
{-
url:
The LDAP connection URL, including the ldap protocol

base:
The base query from which all further searches should be performed

username:
The username of a technical user who can connect to the LDAP source to perform searches

password:
The password of the user above
-}

{ url : Text, base : Text, username : Text, password : Secret }
let example
: SourceConfiguration
= { url = "ldap://example.com:389"
, base = "dc=meshcloud,dc=io"
, username = "user"
, password = Secret.Raw "LDAP_PASSWORD"
}

You also have to specify the filters that should be used when fetching users and groups from the LDAP server. Additionally, using the pageSize configuration parameter, specify the number of LDAP entities we should request in a single call to the server.

Dhall Type
Example
let LdapFilter =
{-
collectionType:
The type of the entity which is collected. Can either be PERSON or GROUP.

attributes:
A comma separated list of attributes that should be returned per LDAP entry.
These attributes can later be used to populate the value of a meshObject field.

base:
The base from which the query should be performed.

filter:
A filter that follows the LDAP search filter format.
-}

{ collectionType : CollectionType
, attributes : Text
, base : Text
, filter : Text
}

let CollectorConfiguration =
{-
pageSize:
The size of a single page that will be returned as a result of an LDAP search

sources:
A list of LdapFilter which will contain the information needed to search the LDAP source for groups or persons.
-}

{ pageSize : Natural, sources : List LdapFilter }
let example
: CollectorConfiguration
= { pageSize = 100
, sources =
[ { collectionType = CollectionType.GROUP
, attributes = "cn, uniqueMember, description"
, base = "ou=groups"
, filter = "(cn=*)"
}
, { collectionType = CollectionType.PERSON
, attributes = "entryDN, uid, sn, givenName, mail"
, base = "ou=people"
, filter = "(uid=*)"
}
]
: List LdapFilter
}

Transform

In the Transform step, the collected data is transformed into meshObjects.

An AttributeTransformation will specify an LDAP attribute and how to transform it before assigning to a meshObject field.

Dhall Type
let AttributeTransformation =
{-
An AttributeTransformation is used to define an attribute of an LDAP entry and how to transform it so that it
can be assigned to a field in a meshObject. There are two types of AttributeTransformations, Static and Regex.
-}

< Static : StaticAttributeTransformation
| IfNull : IfNullAttributeTransformation
| Regex : RegexAttributeTransformation
>

StaticAttributeTransformation

Dhall Type
Example
let StaticAttributeTransformation =
{-
A StaticAttributeTransformation simply takes an attribute and applies an optional postProcessor on it.

attribute:
The LDAP attribute that should be processed. For example "cn"

postProcessor:
Any post processing function that should be run on the mapped value. Can be one of UPPERCASE or LOWERCASE
-}

{ attribute : Text, postProcessor : Optional PostProcessor }
let example =
{ attribute = "cn", postProcessor = Some PostProcessor.LOWERCASE }

IfNullAttributeTransformation

Dhall Type
Example
let IfNullAttributeTransformation =
{-
A IfNullAttributeTransformation takes a nullable attribute.
If the value of this attribute is null for an entity it uses a replacement value.
After an attribute value is found, the transformation applies an optional postProcessor on the value.

attribute:
The LDAP attribute that should be looked up first. For example "mail"

ifNullAttribute:
The LDAP attribute that should be looked up if the value of the first attribute is null. For example "cn"

postProcessor:
Any post processing function that should be run on the mapped value. Can be one of UPPERCASE or LOWERCASE
-}

{ attribute : Text
, ifNullAttribute : Text
, postProcessor : Optional PostProcessor
}
let example =
{ attribute = "mail"
, ifNullAttribute = "cn"
, postProcessor = Some PostProcessor.LOWERCASE
}

RegexAttributeTransformation

Dhall Type
Example
let RegexAttributeTransformation =
{-
A RegexAttributeTransformation takes an attribute and matches the attribute against a list of regular expressions
until a match is found. If a match is found and the rule defines a value, the value will be used. If a value is not
set, the first matching group in the regular expression is used and the optional template is applied. If no
regular expressions match, the otherwise value will be assigned to the meshObject field.

rules:
A list of regex rules that the LDAP attributes will be tested against for a match.
The matching is performed sequentially until a match is found.
A single rule has the following structure
value:
This is an optional parameter. If it is defined and if the LDAP attribute matches the
regular expression, this value will be assigned as the value of the meshObject field.
regex:
The regular expression against which the LDAP attribute should be matched. If the value parameter
is not defined, the regular expression MUST contain a group and the first group will be assigned
as the value of the meshObject field.

template:
An optional template where the extracted value should be inserted into.
The format should follow the Java String.format contract.

otherwise:
An optional default value to be assigned if none of the rules match.
-}

StaticAttributeTransformation
⩓ { rules : List { regex : Text, value : Optional Text }
, otherwise : Optional Text
, template : Optional Text
}
let example =
{-
The following example takes the 'cn' attribute and if the attribute matches the first rule,
will assign whatever follows the "MESHCLOUD-ROLE-" as the value of the meshObject field. If the attribute matches
the second rule, will assign the value "Platform Operator" and if none of the rules match, assigns the
value "Workspace Member".
-}

{ attribute = "cn"
, postProcessor = None PostProcessor
, rules =
[ { regex = "MESHCLOUD-ROLE-(.+)", value = None Text }
, { regex = "MESHCLOUD-OPERATOR"
, value = Some "Platform Operator"
}
]
, template = None Text
, otherwise = Some "Workspace Member"
}

LDAP entities to meshObjects transformation

Using AttributeTransformations, you can specify how to transform LDAP entities into meshObjects as follows.

Dhall Type
Example
let UserAttributesTransformations =
{-
distinguishedNameAttribute:
The 'distinguished name' attribute key for a user entity in LDAP. This attribute value should match the users
referred to in the 'members' attribute of the groupAttributesTransformations.

name, email, firstName, lastName, euid
For each of these meshUser fields, specify which LDAP attribute should be transformed and assigned to the field.

tags:
How to tag the meshUser object.
Specify the tag keys and for each key, which LDAP attribute should be transformed and assigned as the tag value.
-}

{ distinguishedNameAttribute : Text
, name : AttributeTransformation
, email : AttributeTransformation
, firstName : AttributeTransformation
, lastName : AttributeTransformation
, euid : AttributeTransformation
, tags : List TagMapping
}

let GroupAttributesTransformations =
{-
distinguishedNameAttribute:
The 'distinguished name' attribute key for a user entity in LDAP. This attribute value should match the users
referred to in the 'members' attribute of the groupAttributesTransformations.

name, ownedByWorkspace, displayName, egid
For each of these meshUser fields, specify which LDAP attribute should be transformed and assigned to the field.

tags:
How to tag the meshUser object.
Specify the tag keys and for each key, which LDAP attribute should be transformed and assigned as the tag value.
-}

{ membersAttribute : Text
, name : AttributeTransformation
, ownedByWorkspace : AttributeTransformation
, displayName : AttributeTransformation
, egid : AttributeTransformation
, tags : List TagMapping
}

let GroupBindingAttributesTransformations =
{-
roleName:
Specify which LDAP attribute should be transformed and assigned to the 'roleName' field of the meshWorkspace user group
-}

{ roleName : AttributeTransformation }

let TransformConfiguration =
{-
Specifies how LDAP entities should be transformed into meshObjects.
There are three types of meshObjects that are imported. meshUsers, meshWorkspaceUserGroups
and meshWorkspaceGroupBindings.

includeAllUsers:
If set to true all meshUsers found in the LDAP are sent to meshstack.
If set to false only users that have at least one group assignment are sent to meshstack.

userAttributesTransformations:
Specifies how an LDAP user entity should be transformed into a meshUser.

groupAttributesTransformations:
Specifies how an LDAP group entity should be transformed into a meshWorkspace user group.

groupBindingAttributesTransformations:
Specifies how a meshWorkspaceGroupBinding meshObject should be constructed from an LDAP group entity.

-}

{ includeAllUsers : Bool
, userAttributesTransformations : UserAttributesTransformations
, groupAttributesTransformations : GroupAttributesTransformations
, groupBindingAttributesTransformations :
GroupBindingAttributesTransformations
}
let example
: TransformConfiguration
= { includeAllUsers = False
, userAttributesTransformations =
{ distinguishedNameAttribute = "dn"
, name =
AttributeTransformation.Static
{ attribute = "cn", postProcessor = None PostProcessor }
, email =
AttributeTransformation.Static
{ attribute = "mail", postProcessor = None PostProcessor }
, firstName =
AttributeTransformation.Static
{ attribute = "givenName"
, postProcessor = None PostProcessor
}
, lastName =
AttributeTransformation.Static
{ attribute = "sn", postProcessor = None PostProcessor }
, euid =
AttributeTransformation.Static
{ attribute = "cn", postProcessor = None PostProcessor }
, tags = [] : List TagMapping
}
, groupAttributesTransformations =
{ membersAttribute = "member"
, name =
AttributeTransformation.Static
{ attribute = "cn"
, postProcessor = Some PostProcessor.LOWERCASE
}
, ownedByWorkspace =
AttributeTransformation.Regex
{ attribute = "cn"
, postProcessor = None PostProcessor
, rules =
[ { regex = "ADMIN-GROUP-.+"
, value = Some "default-partner"
}
, { regex = "GROUP-TEAM-(.+)", value = None Text }
]
, template = None Text
, otherwise = None Text
}
, displayName =
AttributeTransformation.Static
{ attribute = "cn", postProcessor = None PostProcessor }
, egid =
AttributeTransformation.Static
{ attribute = "dn", postProcessor = None PostProcessor }
, tags =
[ { tagKey = "environment"
, transformation =
AttributeTransformation.Regex
{ attribute = "cn"
, postProcessor = Some PostProcessor.LOWERCASE
, rules =
[ { regex = ".*-([A-Z]+)", value = None Text } ]
, template = Some "mesh-%s"
, otherwise = Some "mesh-dev"
}
}
]
}
, groupBindingAttributesTransformations.roleName
=
AttributeTransformation.Regex
{ attribute = "cn"
, postProcessor = None PostProcessor
, rules =
[ { regex = "MESHCLOUD-ADMIN-.*"
, value = Some "Partner Admin"
}
, { regex = "MESHCLOUD-OPERRATOR-.*"
, value = Some "Platform Operator"
}
]
, template = None Text
, otherwise = Some "Workspace Member"
}
}

Transport

The Transport configuration contains the parameters needed to call the meshObject API.

Dhall Type
Example
let TransportConfiguration =
{-
apiUser:
A meshStack ApiUser used to authenticate against the meshStack API.

chunkSize:
The number of meshObjects to synchronize in a single API request.
For typical meshStack implementations this should be between 10 and 100 objects.

dryRunOnly:
If set to true, no real request against the API is made but the API payload will
be logged instead for debugging purposes as INFO loglevel.

httpTimeoutSec:
Timeout in seconds for the HTTP requests send to the meshObject API.
-}

{ apiUser : ApiUser
, chunkSize : Natural
, dryRunOnly : Bool
, httpTimeoutSec : Natural
}
let example
: TransportConfiguration
= { chunkSize = 100
, httpTimeoutSec = 300
, dryRunOnly = False
, apiUser =
{ username = "identityconnectorapi"
, password =
Secret.Raw "EXTERNAL_IDENTITYCONNECTOR_MESH_API_PASSWORD"
, authorities =
[ Authority.EXTERNAL_MESH_OBJECT_IMPORT
, Authority.WORKSPACEOWNER_ASSIGN
]
}
}

Combined Configuration

The above configuration models are combined as follows to create the complete configuration.

Dhall Type
let LdapConfiguration =
{ source : SourceConfiguration
, collector : CollectorConfiguration
, transform : TransformConfiguration
, transport : TransportConfiguration
}
Last updated on 11/21/2024
← AuthorizationUser & Group SCIM Synchronisation →
  • Configuration Reference
    • Collect
    • Transform
    • Transport
    • Combined Configuration
meshStack
Docs
User DocumentationAdministrator DocumentationSecurity FAQ
Get in Touch
SupportWebsiteLinkedIn
More
Release NotesGitHub
Copyright © 2025 meshcloud GmbH