⚡ NOTICE |
---|
I originally developed ldap2azure for my vocational school to simplify the management of Office 365 user accounts there. They now use a different solution and I no longer have any use for the project. Unfortunately, I also lack the time to further maintain ldap2azure. Therefore I will archive the project for the time being. However, feel free to fork it if you are interested in it! |
ldap2azure is a simple tool for automatically synchronizing and updating users from any standard LDAP to an Azure Active Directory.
ldap2azure ensures that all changes to LDAP objects are automatically synchronized to Azure AD. All properties of a user can be assembled from a mixture of fixed values and placeholders if required, making the synchronization very flexible.
ldap2azure can create simple user objects for the use with a SAML 2.0 identity provider such as Keycloak.
ldaps2azure is not designed to synchronize complete directory structures including groups, group memberships and resources, or users including their password hashes. A synchronization into the other direction, i.e. from Azure into an LDAP, is also not intended.
If your environment requires such functionality, or you use Microsoft Active Directory, take a look at Azure AD Connect instead.
The path of the configuration file is defined in the environment variable LDAP2AZURE_CONFIG. The specified folder must contain the configuration file with the name "config.json".
If the environment variable is not set, the configuration is searched as a fallback in the folder where the .jar file is located.
Below is an example configuration that synchronizes users from an Samba 4 Active Directory:
{
"general": {
"syncCronExpression": "0 0/30 * ? * * *"
},
"msGraph": {
"msGraphTenantId": "<your-tenant-id-here>",
"msGraphClientId": "<your-client-id-here>",
"msGraphClientSecret": "<your-client-secret-here>",
"usageLocation": "DE",
"deleteBehavior": "SOFT"
},
"ldap": {
"ldapUrl": "ldaps://dc1.example.com",
"ldapBindUser": "CN=ServiceUser,CN=Users,DC=example,DC=com",
"ldapBindPassword": "VerySecurePassword1234",
"ldapSearchBase": "CN=Users,DC=example,DC=com",
"ldapSearchFilter": "(&(objectClass=user)(memberof=CN=AzureSyncUser,CN=Groups,DC=example,DC=com))",
"ldapAttributes": [
{
"attributeName": "givenName",
"binary": false
},
{
"attributeName": "sn",
"binary": false
},
{
"attributeName": "displayName",
"binary": false
},
{
"attributeName": "sAMAccountName",
"binary": false
},
{
"attributeName": "objectGUID",
"binary": true
}
],
"ignoreSSLErrors": false
},
"userBuildPattern": {
"givenNamePattern": "{givenName}",
"surnamePattern": "{sn}",
"displayNamePattern": "{displayName}",
"onPremisesImmutableIdPattern": "{objectGUID}",
"mailNicknamePattern": "{sAMAccountName}",
"userPrincipalNamePattern": "{sAMAccountName}@example.com"
},
"autoLicensing": {
"featureEnabled": true,
"defaultLicenseSkuIDs": [
"19dceafd-77c1-4db5-b36b-3cc602144b04"
]
},
"web": {
"featureEnabled": true,
"keystorePassword": "SomePassword1234"
}
}
All sections of the config file are explained in detail below.
The "general" section contains all parameters that are not directly required for querying, processing and changing data.
Key | Description | Default value | Example value |
---|---|---|---|
syncCronExpression | Cron expression, when the SyncJob should be executed | none | 0 0/30 * ? * * * |
debuggingEnabled | (Optional) If true enables an integrated H2 console on port 8082 to debug the internal database | false | true |
databaseJDBCUrl | (Optional) JDBC url for the use of an external database such as MySQL. If not set the internal H2 database is used. | Internal H2 database | mysql://user:password@localhost/ldap2azure?useSSL=false |
The "msGraph" section contains all information required to connect to the Microsoft Graph API. The application under which ldap2azure runs must be a daemon application and have the Microsoft Graph permission
Directory.ReadWrite.All
and User.ReadWrite.All
.
More about the creation of a Microsoft Graph daemon application can be found here.
Key | Description | Default value | Example value |
---|---|---|---|
msGraphTenantId | ID of the Azure AD tenant, ldap2azure connects to. Used for authentication. | none | 7a53db06-b010-4aef-ba79-337d9d2f29bb |
msGraphClientId | ID of the Microsoft Graph Application that should be used | none | 641e2b36-0bde-46af-b896-545532c0ba03 |
msGraphClientSecret | Secret, which was generated for the application in Azure AD | none | Vo:MfG.AHK[eIwO?QhpdQ5mz0p8cG3L- |
usageLocation | Two character location code of the country new user accounts will be used in | none | DE |
deleteBehavior | (Optional) If set to HARD, users will be deleted completely if they are removed from the source ldap. If set to SOFT they will be moved to the recycling bin instead and will be deleted by Azure AD after 30 days | SOFT | HARD |
The "ldap" section contains all information on how and which data is retrieved from the source LDAP.
If an LDAPS connection is used and the server only uses a self-signed certificate, this certificate must be added to the default Java Keystore for the connection to work correctly.
Alternatively, any certificate can be accepted in test environments. However, it is strongly recommended not to do this in production environments.
Key | Description | Default value | Example value |
---|---|---|---|
ldapUrl | Connection string used to connect to the source LDAP server | none | ldaps://dc1.example.com |
ldapBindUser | Identity that is used to bind to the source LDAP server | none | CN=ServiceUser,CN=Users,DC=example,DC=com |
ldapBindPassword | Password used to authenticate as the bind user | none | SomeSecurePassword1234 |
ldapSearchBase | DN of the base container in which the users to be synchronized are located | none | CN=Users,DC=example,DC=com |
ldapSearchFilter | LDAP filter to narrow down the objects to be synchronized | none | (&(objectClass=user)(memberof=CN=AzureSyncUser,CN=Groups,DC=example,DC=com)) |
ignoreSSLErrors | (Optional) If true, certificate errors are ignored for LDAPS connections | false | true |
ldapAttributes | Array containing the LDAP attributes to be loaded, which can later be used in the pattern configuration | none | see below |
Defines an attribute in the source LDAP, which can later be used in the pattern configuration.
Key | Description | Example value |
---|---|---|
attributeName | Name of the attribute in the source ldap | objectGUID |
binary | Set whether the attribute is binary. If so, it will be converted to a Base64 encoded string | true |
The "userBuildPattern" section contains the templates according to which the Azure user objects are created. Both fixed values and placeholders for values read from the LDAP can be used. A mixture of both is of course also possible.
An exemplary configuration which uses placeholders combined with fixed values is shown in the example configuration file above.
Key | Description | Example value |
---|---|---|
givenNamePattern | Template for composing the given name of a user | {givenName} |
surnamePattern | Template for composing the surname name of a user | {sn} |
displayNamePattern | Template for composing the display name of a user | {displayName} |
onPremisesImmutableIdPattern | Template for composing the on premises immutable id of a user. This value must be unique throughout your Azure AD. For a Federation with a SAML 2.0 Identity Provider, this value must be returned as NameID. | {objectGUID} |
mailNicknamePattern | Template for composing the mail nickname of a user | {sAMAccountName} |
userPrincipalNamePattern | Template for composing the user principal name of a user. This value must be unique throughout your Azure AD. | {sAMAccountName}@example.com |
ldap2azure offers the possibility to automatically assign a license to new users that are being synchronized. This feature is optional, but recommended for an automated workflow.
Key | Description | Default value | Example value |
---|---|---|---|
featureEnabled | (Optional) Can be set true to enable the function or false to disable it | false | true |
defaultLicenseSkuIDs | (Optional) Array of GUIDs of the licenses to be used by default. More can be read here | Empty array | ["05e9a617-0261-4cee-bb44-138d3ef5d965"] |
ldap2azure is equipped with a RESTful API and the possibility to provide a web frontend.
Once the feature is enabled, ldap2azure will create a default api user the first time it is started. The credentials are displayed in the console or log.
To provide a frontend, it must be located in a folder called web-frontend
in the same folder as the JAR file of ldap2azure. The web-frontend
folder must also contain at least an index.html
file. If this is the case, it is automatically mounted at application startup.
My personal implementation of a frontend can be found on my GitHub account: ldap2azure-frontend
The documentation of the RESTful API is available here.
Key | Description | Default value | Example value |
---|---|---|---|
featureEnabled | (Optional) Can be set true to enable the function or false to disable it | false | true |
httpPort | (Optional) Sets the port under which the API and the management interface can be reached via HTTP | 8080 | 80 |
httpsPort | (Optional) Sets the port under which the API and the management interface can be reached via HTTPs | 8443 | 443 |
keystorePassword | (Optional) Password for the Java keystore that holds the HTTPs certificate | changeit | SomePassword1234 |
redirectHttp | (Optional) Set if HTTP requests should be redirected to HTTPs instead | true | false |
If you want to provide HTTPs, you need to create a Java keystore named ldap2azure.jks
in the same folder as the JAR file of ldap2azure.
If you have a certificate in PEM format, the keystore can be created as follows:
openssl pkcs12 -export -in cert.pem -inkey privkey.pem -out ldap2azure.pkcs12
keytool -importkeystore -destkeystore ldap2azure.jks -srckeystore ldap2azure.pkcs12 -srcstoretype PKCS12
If you use a different password for the keystore than the default "changeit", you have to set it via the keystorePassword
entry in the "webConfig" section.
By default, logs are stored in the "log" subdirectory of the directory you are running ldap2azure from. The log files are automatically rotated every 24 hours and archived as .gz files. All logs older than 30 days are automatically deleted. Log files are also deleted if the log folder exceeds 3 GB in size.
The path for log files can be adjusted with the parameter "-DLOG_DIR=/path/to/logs"
The name for log files can be adjusted with the parameter "-DLOG_NAME=myCustomLogName"
- Maven - Dependency Management
- H2 - Java SQL database (Used as in memory cache)
- OrmLite - Lightweight Object Relational Mapping Java Package
- Jackson-Databind - FasterXML Jackson object mapper
- Microsoft Graph SDK for Java - SDK for the Microsoft Graph API
- MSAL4J - Microsoft Authentication Library (MSAL) for Java
- Quartz - Quartz Job Scheduler
- LOGBack - Java Logging Framework
This project is licensed under the GNU General Public License v3.0 - see the LICENSE.md file for details