Skip to content
This repository has been archived by the owner on Jan 26, 2024. It is now read-only.

Commit

Permalink
feat: disable login instead of disabling account
Browse files Browse the repository at this point in the history
  • Loading branch information
wardpieters committed Aug 22, 2022
1 parent 7f9cb24 commit 6e3000c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 57 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM python:3-alpine

RUN apk --no-cache add build-base openldap-dev python2-dev python3-dev
RUN apk --no-cache add build-base openldap-dev python3-dev
RUN pip3 install python-ldap sqlalchemy requests

COPY templates ./templates
Expand Down
90 changes: 41 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

Adds LDAP accounts to mailcow-dockerized and enables LDAP (e.g., Active Directory) authentication.

* [How does it work](#how-does-it-work)
* [Usage](#usage)
* [LDAP Fine-tuning](#ldap-fine-tuning)
* [Limitations](#limitations)
* [WebUI and EAS authentication](#webui-and-eas-authentication)
* [Two-way sync](#two-way-sync)
* [Customizations and Integration support](#customizations-and-integration-support)
- [How does it work](#how-does-it-work)
- [Usage](#usage)
- [LDAP Fine-tuning](#ldap-fine-tuning)
- [Limitations](#limitations)
- [WebUI and EAS authentication](#webui-and-eas-authentication)
- [Two-way sync](#two-way-sync)
- [Customizations and Integration support](#customizations-and-integration-support)

## How does it work

Expand All @@ -19,41 +19,41 @@ A python script periodically checks and creates new LDAP accounts and deactivate
1. Create a `data/ldap` directory. SQLite database for synchronization will be stored there.
2. Extend your `docker-compose.override.yml` with an additional container:

```yaml
ldap-mailcow:
image: programmierus/ldap-mailcow
network_mode: host
container_name: mailcowcustomized_ldap-mailcow
depends_on:
- nginx-mailcow
volumes:
- ./data/ldap:/db:rw
- ./data/conf/dovecot:/conf/dovecot:rw
- ./data/conf/sogo:/conf/sogo:rw
environment:
- LDAP-MAILCOW_LDAP_URI=ldap(s)://dc.example.local
- LDAP-MAILCOW_LDAP_BASE_DN=OU=Mail Users,DC=example,DC=local
- LDAP-MAILCOW_LDAP_BIND_DN=CN=Bind DN,CN=Users,DC=example,DC=local
- LDAP-MAILCOW_LDAP_BIND_DN_PASSWORD=BindPassword
- LDAP-MAILCOW_API_HOST=https://mailcow.example.local
- LDAP-MAILCOW_API_KEY=XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX
- LDAP-MAILCOW_SYNC_INTERVAL=300
- LDAP-MAILCOW_LDAP_FILTER=(&(objectClass=user)(objectCategory=person)(memberOf:1.2.840.113556.1.4.1941:=CN=Group,CN=Users,DC=example DC=local))
- LDAP-MAILCOW_SOGO_LDAP_FILTER=objectClass='user' AND objectCategory='person' AND memberOf:1.2.840.113556.1.4.1941:='CN=Group,CN=Users,DC=example DC=local'
```
```yaml
ldap-mailcow:
image: ghcr.io/wardpieters/mailcow-ldap
network_mode: host
container_name: mailcowcustomized_ldap-mailcow
depends_on:
- nginx-mailcow
volumes:
- ./data/ldap:/db:rw
- ./data/conf/dovecot:/conf/dovecot:rw
- ./data/conf/sogo:/conf/sogo:rw
environment:
- LDAP-MAILCOW_LDAP_URI=ldap(s)://dc.example.local
- LDAP-MAILCOW_LDAP_BASE_DN=OU=Mail Users,DC=example,DC=local
- LDAP-MAILCOW_LDAP_BIND_DN=CN=Bind DN,CN=Users,DC=example,DC=local
- LDAP-MAILCOW_LDAP_BIND_DN_PASSWORD=BindPassword
- LDAP-MAILCOW_API_HOST=https://mailcow.example.local
- LDAP-MAILCOW_API_KEY=XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX
- LDAP-MAILCOW_SYNC_INTERVAL=300
- LDAP-MAILCOW_LDAP_FILTER=(&(objectClass=user)(objectCategory=person)(memberOf:1.2.840.113556.1.4.1941:=CN=Group,CN=Users,DC=example DC=local))
- LDAP-MAILCOW_SOGO_LDAP_FILTER=objectClass='user' AND objectCategory='person' AND memberOf:1.2.840.113556.1.4.1941:='CN=Group,CN=Users,DC=example DC=local'
```
3. Configure environmental variables:
* `LDAP-MAILCOW_LDAP_URI` - LDAP (e.g., Active Directory) URI (must be reachable from within the container). The URIs are in syntax `protocol://host:port`. For example `ldap://localhost` or `ldaps://secure.domain.org`
* `LDAP-MAILCOW_LDAP_BASE_DN` - base DN where user accounts can be found
* `LDAP-MAILCOW_LDAP_BIND_DN` - bind DN of a special LDAP account that will be used to browse for users
* `LDAP-MAILCOW_LDAP_BIND_DN_PASSWORD` - password for bind DN account
* `LDAP-MAILCOW_API_HOST` - mailcow API url. Make sure it's enabled and accessible from within the container for both reads and writes
* `LDAP-MAILCOW_API_KEY` - mailcow API key (read/write)
* `LDAP-MAILCOW_SYNC_INTERVAL` - interval in seconds between LDAP synchronizations
* **Optional** LDAP filters (see example above). SOGo uses special syntax, so you either have to **specify both or none**:
* `LDAP-MAILCOW_LDAP_FILTER` - LDAP filter to apply, defaults to `(&(objectClass=user)(objectCategory=person))`
* `LDAP-MAILCOW_SOGO_LDAP_FILTER` - LDAP filter to apply for SOGo ([special syntax](https://sogo.nu/files/docs/SOGoInstallationGuide.html#_authentication_using_ldap)), defaults to `objectClass='user' AND objectCategory='person'`
- `LDAP-MAILCOW_LDAP_URI` - LDAP (e.g., Active Directory) URI (must be reachable from within the container). The URIs are in syntax `protocol://host:port`. For example `ldap://localhost` or `ldaps://secure.domain.org`
- `LDAP-MAILCOW_LDAP_BASE_DN` - base DN where user accounts can be found
- `LDAP-MAILCOW_LDAP_BIND_DN` - bind DN of a special LDAP account that will be used to browse for users
- `LDAP-MAILCOW_LDAP_BIND_DN_PASSWORD` - password for bind DN account
- `LDAP-MAILCOW_API_HOST` - mailcow API url. Make sure it's enabled and accessible from within the container for both reads and writes
- `LDAP-MAILCOW_API_KEY` - mailcow API key (read/write)
- `LDAP-MAILCOW_SYNC_INTERVAL` - interval in seconds between LDAP synchronizations
- **Optional** LDAP filters (see example above). SOGo uses special syntax, so you either have to **specify both or none**:
- `LDAP-MAILCOW_LDAP_FILTER` - LDAP filter to apply, defaults to `(&(objectClass=user)(objectCategory=person))`
- `LDAP-MAILCOW_SOGO_LDAP_FILTER` - LDAP filter to apply for SOGo ([special syntax](https://sogo.nu/files/docs/SOGoInstallationGuide.html#_authentication_using_ldap)), defaults to `objectClass='user' AND objectCategory='person'`

4. Start additional container: `docker-compose up -d ldap-mailcow`
5. Check logs `docker-compose logs ldap-mailcow`
Expand All @@ -63,8 +63,8 @@ A python script periodically checks and creates new LDAP accounts and deactivate

Container internally uses the following configuration templates:

* SOGo: `/templates/sogo/plist_ldap`
* dovecot: `/templates/dovecot/ldap/passdb.conf`
- SOGo: `/templates/sogo/plist_ldap`
- dovecot: `/templates/dovecot/ldap/passdb.conf`

These files have been tested against Active Directory running on Windows Server 2019 domain controller. If necessary, you can edit and remount them through docker volumes. Some documentation on these files can be found here: [dovecot](https://doc.dovecot.org/configuration_manual/authentication/ldap/), [SOGo](https://sogo.nu/files/docs/SOGoInstallationGuide.html#_authentication_using_ldap)

Expand All @@ -89,11 +89,3 @@ As a side-effect, It will also allow logging into mailcow UI using mailcow app p
### Two-way sync

Users from your LDAP directory will be added (and deactivated if disabled/not found) to your mailcow database. Not vice-versa, and this is by design.

## Customizations and Integration support

External authentication (identity federation) is an enterprise feature [for mailcow](https://github.com/mailcow/mailcow-dockerized/issues/2316#issuecomment-491212921). That’s why I developed an external solution, and it is unlikely that it’ll be ever directly integrated into mailcow.

I’ve created this tool because I needed it for my regular work. You are free to use it for commercial needs. Please understand that I can work on issues only if they fall within the scope of my current work interests or if I’ll have some available free time (never happened for many years). I’ll do my best to review submitted PRs ASAP, though.

**You can always [contact me](mailto:[email protected]) to help you with the integration or for custom modifications on a paid basis. My current hourly rate (ActivityWatch tracked) is 100,-€ with 3h minimum commitment.**
8 changes: 1 addition & 7 deletions api.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def add_user(email, name, active, quotum):
def edit_user(email, active=None, name=None):
attr = {}
if (active is not None):
attr['active'] = 1 if active else 0
attr['active'] = 1 if active else 2
if (name is not None):
attr['name'] = name

Expand All @@ -82,12 +82,6 @@ def edit_user(email, active=None, name=None):
__post_request('api/v1/edit/mailbox', json_data)


def __delete_user(email):
json_data = [email]

__post_request('api/v1/delete/mailbox', json_data)


def check_user(email):
url = f"{api_host}/api/v1/get/mailbox/{email}"
headers = {'X-API-Key': api_key, 'Content-type': 'application/json'}
Expand Down

0 comments on commit 6e3000c

Please sign in to comment.