diff --git a/Dockerfile b/Dockerfile index 69f6bbc..2774364 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,21 +6,21 @@ RUN apt-get update && \ libfreetype6-dev \ libjpeg-dev \ libpng-dev && \ - rm -rf /var/lib/apt/lists/* && \ - ln -s /usr/lib/x86_64-linux-gnu/libldap.so /usr/lib/libldap.so && \ - ln -s /usr/lib/x86_64-linux-gnu/liblber.so /usr/lib/liblber.so + rm -rf /var/lib/apt/lists/* RUN docker-php-ext-configure gd \ --enable-gd-native-ttf \ --with-freetype-dir=/usr/include/freetype2 \ --with-png-dir=/usr/include \ --with-jpeg-dir=/usr/include && \ - docker-php-ext-install -j$(nproc) ldap gd + docker-php-ext-install -j$(nproc) gd && \ + libdir=$(find /usr -name "libldap.so*" | sed -e 's/\/usr\///' -e 's/\/libldap.so//') && \ + docker-php-ext-configure ldap --with-libdir=$libdir && \ + docker-php-ext-install -j$(nproc) ldap ADD https://github.com/PHPMailer/PHPMailer/archive/v6.2.0.tar.gz /tmp -RUN a2enmod rewrite ssl -RUN a2dissite 000-default default-ssl +RUN a2enmod rewrite ssl && a2dissite 000-default default-ssl EXPOSE 80 EXPOSE 443 diff --git a/README.md b/README.md index c978208..75a6828 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -LDAP User Manager --- +# LDAP User Manager This is a PHP LDAP account manager; a web-based GUI interface which allows you to quickly populate a new LDAP directory and easily manage user accounts and groups. It also has a self-service password change module. It's designed to work with OpenLDAP and to be run as a container. It complements OpenLDAP containers such as [*osixia/openldap*](https://hub.docker.com/r/osixia/openldap/). -Features ---- +*** + +## Features * Setup wizard: this will create the necessary structure to allow you to add users and groups and will set up an initial admin user that can log into the user manager. * Group creation and management. @@ -16,27 +16,27 @@ Features * Self-service password change: non-admin users can log in to change their password. * An optional form for people to request accounts (request emails are sent to an administrator). -Screenshots ---- +*** -**Initial setup: add an administrator account**: -![administrator_setup](https://user-images.githubusercontent.com/17613683/59344224-8bb8ae80-8d05-11e9-869b-d08a44f4939d.png) - -**Add a new group**: -![new_group](https://user-images.githubusercontent.com/17613683/59344242-95421680-8d05-11e9-9a72-1f55c06dd43d.png) - -**Manage group membership**: -![group_membership](https://user-images.githubusercontent.com/17613683/59344247-97a47080-8d05-11e9-8606-0bcc40471458.png) +## Screenshots **Edit accounts**: + ![account_overview](https://user-images.githubusercontent.com/17613683/59344255-9c692480-8d05-11e9-9207-051291bafd91.png) + +**Manage group membership**: + +![group_membership](https://user-images.githubusercontent.com/17613683/59344247-97a47080-8d05-11e9-8606-0bcc40471458.png) + + **Self-service password change**: + ![self_service_password_change](https://user-images.githubusercontent.com/17613683/59344258-9ffcab80-8d05-11e9-9dc2-27dfd373fcc8.png) +*** -Quick start ---- +## Quick start ``` docker run \ @@ -53,21 +53,21 @@ docker run \ -e "LDAP_ADMIN_BIND_PWD=secret"\ -e "LDAP_IGNORE_CERT_ERRORS=true" \ -e "EMAIL_DOMAIN=ldapusermanager.org" \ - wheelybird/ldap-user-manager:v1.5 + wheelybird/ldap-user-manager:v1.6 ``` Change the variable values to suit your environment. Now go to https://lum.example.com/setup. +*** -Configuration ---- +## Configuration Configuration is via environmental variables. Please bear the following in mind: * This tool needs to bind to LDAP as a user that has the permissions to modify everything under the base DN. * This interface is designed to work with a fresh LDAP server and should only be against existing, populated LDAP directories with caution and at your own risk. -Mandatory: ----- +### Mandatory: + * `LDAP_URI`: The URI of the LDAP server, e.g. `ldap://ldap.example.com` or `ldaps://ldap.example.com` @@ -79,10 +79,9 @@ Mandatory: * `LDAP_ADMINS_GROUP`: The name of the group used to define accounts that can use this tool to manage LDAP accounts. e.g. `admins` -Optional: ----- +### Optional: -**Organisation settings** +#### Organisation settings * `SERVER_HOSTNAME` (default: *ldapusername.org*): The hostname that this interface will be served from. @@ -91,7 +90,7 @@ Optional: * `SITE_NAME` (default: *{ORGANISATION_NAME} user manager*): Change this to replace the title in the menu, e.g. "My Company Account Management". -**LDAP settings** +#### LDAP settings * `LDAP_USER_OU` (default: *people*): The name of the OU used to store user accounts (without the base DN appended). @@ -103,18 +102,24 @@ Optional: * `LDAP_TLS_CACERT` (no default): If you need to use a specific CA certificate for TLS connections to the LDAP server (when `LDAP_REQUIRE_STARTTLS` is set) then assign the contents of the CA certificate to this variable. e.g. `-e LDAP_TLS_CACERT="$( The setup wizard is primarily designed to use with a new, empty LDAP directory, though it is possible to use it with existing directories as long as you ensure you use the correct advanced LDAP settings. + +Once you've set up the initial administrator account you can log into the user manager with it and start creating other accounts. Your username to log in with is (by default) whatever you set **System username** to. See [Account names](#account-names) below if you changed the default by setting `LDAP_ACCOUNT_ATTRIBUTE`. + +*** + +## Account names + +Your login ID is whatever the *account identifier* value is for your account. By default the user manager uses the **System username** as your login; this is actually the LDAP `uid` attribute. So if your system username is `test-person`, that's what you'll use to log in with. + +The `uid` is the attribute that's normally used as the login username for systems like Linux, FreeBSD, NetBSD etc., and so is a great choice if you're using LDAP to create server accounts. +Other services or software might use the *Common Name* (`cn`) attribute, which is normally a person's full name. So you might therefore log in as `Test Person`. + +The account identifier is what uniquely identifies the account, so you can't create multiple accounts where the account identifier is the same. +You should ensure your LDAP clients use the same account identifier attribute when authenticating users. + +If you're using LDAP for server accounts then you'll find there are normally constraints on how many cahracters and the type of characters you're allowed to use. The user manager will validate user and group names against `USERNAME_REGEX`. If you don't need to be so strict then you can disable these checks by setting `ENFORCE_SAFE_SYSTEM_NAMES` to `FALSE`. + +*** + +## HTTPS certificates +When `NO_HTTPS` is set to **FALSE** (the default), the user manager expects to find SSL files at `/opt/ssl/server.key` and `/opt/ssl/server.crt`. These certificates should match `SERVER_HOSTNAME`. If these files aren't found then the startup script will create self-signed certificates based on `SERVER_HOSTNAME`. To use your own key and certificate then you need to bind-mount a directory containing them to `/opt/ssl`. You can also add a certificate chain file (the Apache `SSLCertificateChainFile` option) if needed - name it `chain.pem` and place it in the same directory as `server.key` and `server.crt` . For example, if your key and certificate files are in `/home/myaccount/ssl` you can bind-mount that folder by adding this line to the docker run example above, just after the last line starting with `-e`: ``` @@ -183,20 +223,10 @@ For example, if your key and certificate files are in `/home/myaccount/ssl` you ``` -Initial setup ---- +*** -Ideally you'll be using this against an empty LDAP directory. You can use the setup utility to create the LDAP structures that this user manager needs in order to create accounts and groups. Go to `https://{SERVER_HOSTNAME}/setup` to get started (replace `{SERVER_HOSTNAME}` with whatever you set `SERVER_HOSTNAME` to in the Docker run command). +## Sending emails -The log in password is the admin user's password (what `LDAP_ADMIN_BIND_DN` was set to). - -The setup utility will create the user and account trees, records that store the last UID and GID used when creating a user account or group, a group for admins and the initial admin account. - -![initial_setup](https://user-images.githubusercontent.com/17613683/59344213-865b6400-8d05-11e9-9d86-381d59671530.png) - - -Sending emails ---- When you create an account you'll have an option to send an email to the person you created the account for. The email will give them their new username, password and a link to the self-service password change utility. @@ -205,10 +235,11 @@ If you haven't passed in those settings or if the account you've created has no When the account is created you'll be told if the email was sent or not but be aware that just because your SMTP server accepted the email it doesn't mean that it was able to deliver it. If you get a message saying the email wasn't sent then check the logs for the error. You can increase the log level (`SMTP_LOG_LEVEL`) to above 0 in order to see SMTP debug logs. -Username format ---- +*** -When entering the user's first and last names a bit of JavaScript automatically generates the username. The way it generates is it based on a template format defined by `USERNAME_FORMAT`. This is basically a string in which predefined macros are replaced by the formatted first and/or last name. +## Username format + +When entering a person's name the system username is automatically filled-in based on a template. The template is defined in `USERNAME_FORMAT` and is a string containing predefined macros that are replaced with the relevant value. The default is `{first_name}-{last_name}` with which *Jonathan Testperson*'s username would be *jonathan-testperson*. Currently the available macros are: @@ -217,27 +248,44 @@ Currently the available macros are: * `{last_name}`: the last name in lowercase * `{last_name_initial}`: the first initial of the last name in lowercase -Anything else in the `USERNAME_FORMAT` string is left as defined, but the username is also checked for validity against `USERNAME_REGEX`. This is to ensure that there aren't any characters forbidden by other systems (i.e. email or Linux/Unix accounts). - +Anything else in the `USERNAME_FORMAT` string is left unmodified. If `ENFORCE_SAFE_SYSTEM_NAMES` is set then the username is also checked for validity against `USERNAME_REGEX`. This is to ensure that there aren't any characters forbidden when using LDAP to create server or email accounts. + If `EMAIL_DOMAIN` is set then the email address field will be automatically updated in the form of `username@email_domain`. Entering anything manually in that field will stop the automatic update of the email field. +*** -Using the RFC2307BIS schema ---- +## Extra objectClasses and attributes -The user manager will attempt detect if your LDAP server has the RFC2307BIS schema available and, if it does, use it when creating groups. This will allow you to use `memberOf` in LDAP searches which gives you an easy way to check if a user is a member of a group. For example: `(&(objectClass=posixAccount)(memberof=cn=somegroup,ou=groups,dc=ldapusermanager,dc=org))`. See [this guide](https://unofficialaciguide.com/2019/07/31/ldap-schemas-for-aci-administrators-rfc2307-vs-rfc2307bis/) for more information. +If you need to use this user manager with an existing LDAP directory and your account records need additional objectClasses and attributes then you can add them via `LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES` and `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES`. -With OpenLDAP this schema isn't normally available by default; you need to configure your server to use the **RFC2307BIS** schema when setting up your directory. +`LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES` is a comma-separated list of objectClasses to add when creating the account record. For example, `LDAP_ACCOUNT_ADDITIONAL_OBJECTCLASSES=ldappublickey,couriermailaccount`. + +To add extra fields for new attributes you need to pass a comma-separated string of the attributes and optionally the label for the attribute (which will be shown on the user form) and a default value to `LDAP_ACCOUNT_ADDITIONAL_ATTRIBUTES` separated by colons (`:`). +The format for configuring an attribute is: `attribute1:label1,default_value1,attribute2:label2:default_value2`. If you don't supply a label then the form field will be labelled with the attribute name. +An example (for the couriermailaccount objectClass) would be: `mailbox:Mailbox:domain.com,quota:Mail quota:20` -If for some reason you do have the schema available but it isn't being detected then you can force it's use by setting `FORCE_RFC2307BIS` to `TRUE`. +ObjectClasses often have attributes that must have a value, so you should definitely set a default for those attributes. + +This is advanced stuff and the user manager doesn't attempt to validate any objectClasses or any attributes, labels or default values you pass in. It's up to you to ensure that your LDAP server has the appropriate schemas and that the labels and values are sane. + +*** + +## Using the RFC2307BIS schema + + +Using the **RFC2307BIS** will allow you to use `memberOf` in LDAP searches which gives you an easy way to check if a user is a member of a group. For example: `(&(objectClass=posixAccount)(memberof=cn=somegroup,ou=groups,dc=ldapusermanager,dc=org))`. + +OpenLDAP will use the RFC2307 (NIS) schema by default; you'll need to configure your server to use the **RFC2307BIS** schema when setting up your directory. See [this guide](https://unofficialaciguide.com/2019/07/31/ldap-schemas-for-aci-administrators-rfc2307-vs-rfc2307bis/) for more information regarding RFC2307 vs RFC2307BIS. +Setting up RFC2307BIS is way beyond the scope of this README, but if you plan on using [osixia/openldap](https://github.com/osixia/docker-openldap) as your LDAP server then you can easily enable the RFC2307BIS schema by setting `LDAP_RFC2307BIS_SCHEMA` to `true` during the initial setup. + +The user manager will attempt detect if your LDAP server has the RFC2307BIS schema available and, if it does, use it when creating groups. This will allow you to use `memberOf` in LDAP searches which gives you an easy way to check if a user is a member of a group. For example: `(&(objectClass=posixAccount)(memberof=cn=somegroup,ou=groups,dc=ldapusermanager,dc=org))`. + +If for some reason you do have the schema available but it isn't being detected then you can force the user manager to use it by setting `FORCE_RFC2307BIS` to `TRUE`. **Note**: if you force-enable using RFC2307BIS but your LDAP server doesn't have that schema available then creating and adding users to groups won't work and the user manager will throw errors. - -If you plan on using [osixia/openldap](https://github.com/osixia/docker-openldap) as your LDAP server you can enable the RFC2307BIS schema by setting `LDAP_RFC2307BIS_SCHEMA` to `true` during the initial setup. +*** - -Testing with an LDAP container --- +## Testing with an OpenLDAP container This will set up an OpenLDAP container you can use to test the user manager against. It uses the RFC2307BIS schema. ``` diff --git a/helm/ldap-user-manager/Chart.yaml b/helm/ldap-user-manager/Chart.yaml deleted file mode 100644 index f77bee8..0000000 --- a/helm/ldap-user-manager/Chart.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -description: A helm chart for ldap-user-manager -name: ldap-user-manager -version: 0.0.1 # Will be replaced during build -sources: -- https://github.com/wheelybird/ldap-user-manager -maintainers: -- name: Abhishek Srivastava - email: abhishekguitarist@gmail.com diff --git a/helm/ldap-user-manager/templates/deployment.yaml b/helm/ldap-user-manager/templates/deployment.yaml deleted file mode 100644 index ca25143..0000000 --- a/helm/ldap-user-manager/templates/deployment.yaml +++ /dev/null @@ -1,139 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: ldap-user-manager - labels: - app: ldap-user-manager - chart: ldap-user-manager-v0.9.34 - release: ldap-user-manager - heritage: Tiller -spec: - selector: - matchLabels: - app: ldap-user-manager - release: ldap-user-manager - template: - metadata: - labels: - app: ldap-user-manager - release: ldap-user-manager - spec: - containers: - - name: ldap-user-manager - image: {{ .Values.image.repository | quote }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - ports: - - name: http - containerPort: {{ .Values.service.httpPort }} - protocol: TCP - - name: https - containerPort: {{ .Values.service.httpsPort }} - protocol: TCP - resources: - limits: - cpu: {{ .Values.resources.limits.cpu | quote }} - memory: {{ .Values.resources.limits.memory | quote }} - requests: - cpu: {{ .Values.resources.requests.cpu | quote }} - memory: {{ .Values.resources.requests.memory | quote }} - env: - - name: LDAP_URI - value: {{ .Values.ldap.URI | quote }} - - name: LDAP_BASE_DN - value: {{ .Values.ldap.baseDN | quote }} - - name: LDAP_ADMIN_BIND_DN - value: {{ .Values.ldap.adminBindDN | quote }} - - name: LDAP_ADMIN_BIND_PWD - value: {{ .Values.ldap.adminBindPassword | quote }} - - name: LDAP_ADMINS_GROUP - value: {{ .Values.ldap.adminGroups | quote }} - {{- if .Values.ldap.userOU }} - - name: LDAP_USER_OU - value: {{ .Values.ldap.userOU | quote }} - {{- end }} - - {{- if .Values.ldap.groupOU }} - - name: LDAP_GROUP_OU - value: {{ .Values.ldap.groupOU | quote }} - {{- end }} - - {{- if .Values.ldap.groupMemAttr }} - - name: LDAP_GROUP_MEMBERSHIP_ATTRIBUTE - value: {{ .Values.ldap.groupMemAttr | quote }} - {{- end }} - - {{- if .Values.ldap.groupMemUID }} - - name: LDAP_GROUP_MEMBERSHIP_USES_UID - value: {{ .Values.ldap.groupMemUID | quote }} - {{- end }} - - {{- if .Values.ldap.defaultGroup }} - - name: DEFAULT_USER_GROUP - value: {{ .Values.ldap.defaultGroup | quote }} - {{- end }} - - {{- if .Values.ldap.userShell }} - - name: DEFAULT_USER_SHELL - value: {{ .Values.ldap.userShell | quote }} - {{- end }} - - {{- if .Values.ldap.emailDomain }} - - name: EMAIL_DOMAIN - value: {{ .Values.ldap.emailDomain | quote }} - {{- end }} - - {{- if .Values.ldap.usernameFormat }} - - name: USERNAME_FORMAT - value: {{ .Values.ldap.usernameFormat | quote }} - {{- end }} - - {{- if .Values.ldap.usernameRegex }} - - name: USERNAME_REGEX - value: {{ .Values.ldap.usernameRegex | quote }} - {{- end }} - - {{- if .Values.ldap.loginTimeout }} - - name: LOGIN_TIMEOUT_MINS - value: {{ .Values.ldap.loginTimeout | quote }} - {{- end }} - - {{- if .Values.ldap.nisSchema }} - - name: LDAP_USES_NIS_SCHEMA - value: {{ .Values.ldap.nisSchema | quote }} - {{- end }} - - {{- if .Values.cert.startTLS }} - - name: LDAP_REQUIRE_STARTTLS - value: {{ .Values.cert.startTLS | quote }} - {{- end }} - - {{- if .Values.ldap.cacert }} - - name: LDAP_TLS_CACERT - value: {{ .Values.cert.cacert | quote }} - {{- end }} - - {{- if .Values.ldap.hostname }} - - name: SERVER_HOSTNAME - value: {{ .Values.service.hostname | quote }} - {{- end }} - - {{- if .Values.ldap.noHttps }} - - name: NO_HTTPS - value: {{ .Values.service.noHttps | quote }} - {{- end }} - - {{- if .Values.ldap.siteName }} - - name: SITE_NAME - value: {{ .Values.service.siteName | quote }} - {{- end }} - - {{- if .Values.service.ldapDebug }} - - name: LDAP_DEBUG - value: {{ .Values.service.ldapDebug | quote }} - {{- end }} - - {{- if .Values.service.sessionDebug }} - - name: SESSION_DEBUG - value: {{ .Values.service.sessionDebug | quote }} - {{- end }} diff --git a/helm/ldap-user-manager/templates/service.yaml b/helm/ldap-user-manager/templates/service.yaml deleted file mode 100644 index 88e9dfc..0000000 --- a/helm/ldap-user-manager/templates/service.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: ldap-user-manager - labels: - app: ldap-user-manager - chart: ldap-user-manager-v0.0.1 - release: ldap-user-manager - heritage: Tiller -spec: - ports: - - port: {{ .Values.service.httpPort }} - targetPort: 80 - protocol: TCP - name: http - - port: {{ .Values.service.httpsPort }} - targetPort: 443 - protocol: TCP - name: https - type: {{ .Values.service.type }} - selector: - app: ldap-user-manager - release: ldap-user-manager diff --git a/helm/ldap-user-manager/values.yaml b/helm/ldap-user-manager/values.yaml deleted file mode 100644 index 7a4cb0b..0000000 --- a/helm/ldap-user-manager/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -image: - pullPolicy: "IfNotPresent" - repository: "wheelybird/ldap-user-manager:v1.0" - -service: - httpPort: 5556 - httpsPort: 5557 - # Optional: - # The hostname that this interface will be served from. - hostname: "lum.mycompany.com" - ldapDebug: "TRUE" - sessionDebug: "TRUE" - - # If you set this to TRUE then the server will run in HTTP mode, without any encryption. This is insecure and should only be used for testing. - noHttps: "FALSE" - # Change this to replace the title in the menu. e.g. "My Company" - siteName: "ldapusermanager.com" - type: LoadBalancer - -resources: - requests: - cpu: "50m" - memory: "64Mi" - limits: - cpu: "50m" - memory: "64Mi" - -ldap: - # The URI of the LDAP server. e.g. ldap://ldap.example.com or ldaps://ldap.example.com - URI: "ldap://my-openldap:389" - # The base DN for your organisation. e.g. *dc=example,dc=com` - baseDN: "dc=example,dc=org" - # The DN for the user with permission to modify all records under LDAP_BASE_DN. e.g. cn=admin,dc=example,dc=com - adminBindDN: "cn=admin,dc=example,dc=org" - # The password for LDAP_ADMIN_BIND_DN - adminBindPassword: "admin" - # The name of the group used to define accounts that can use this tool to manage LDAP accounts. e.g. admins - adminGroups: "admins" - - # Optional params - # The name of the OU used to store user accounts (without the base DN appended). - # userOU: "people" - # The name of the OU used to store groups (without the base DN appended). - # groupOU: "groups" - - # The attribute used when adding a user to a group. - # groupMemAttr: "memberUID" - - # If TRUE then the entry for a member of a group will be just the username. Otherwise it's the member's full DN. - # groupMemUID: "" - # The group that new accounts are automatically added to when created. - # NOTE: If this group doesn't exist then a group is created with the same name as the username and the user is added to that group. - - # defaultGroup: "" - # The shell that will be launched when the user logs into a server. - - # userShell: "" - # If set then the email address field will be automatically populated in the form of username@email_domain). - # emailDomain: "" - # The template used to dynamically generate usernames. See the Usernames section below. - - # usernameFormat: "" - # The regular expression used to ensure a username (and group name) is valid. See the Usernames section below. - - # usernameRegex: "" - # How long before an idle session will be timed out. - - loginTimeout: "30" - nisSchema: "TRUE" - -cert: - # Optional - - # If TRUE then a TLS connection is required for this interface to work. - # If set to FALSE then the interface will work without STARTTLS, but a warning will be displayed on the page. - startTLS: "FALSE" - # If you need to use a specific CA certificate for TLS connections to the LDAP server (when LDAP_REQUIRE_STARTTLS is set), - # then assign the contents of the CA certificate to this variable. e.g. -e LDAP_TLS_CERT=$(
Group was deleted.
Group wasn't deleted.
User was deleted.
+User wasn't deleted.
+. Unfortunately adding it to the admin group failed.
+Unfortunately adding it to the admin group failed.
Failed to create the account.
+Failed to create the account:
++ +
The password is too weak.
++ There were issues creating the account: +
The password contained invalid characters.
-The email address is invalid.
-The passwords are mismatched.
-The username is invalid.
-The group has been updated.
The username is missing.
+The account identifier is missing.
The username is invalid.
-The account has been updated.
There was a problem updating the account. Check the logs for more information.
The group membership has been updated.