Skip to content
Snippets Groups Projects

Add README to document configuration

Merged Russ Garrett requested to merge russ/postorius-ldap-membership-management:readme into master
1 file
+ 187
0
Compare changes
  • Side-by-side
  • Inline
README.md 0 → 100644
+ 187
0
 
# Postorius (Mailman 3) LDAP Membership Management
 
 
This Mailman 3 extension enables single-sign-on and list membership synchronisation with [uffd](https://git.cccv.de/uffd/uffd), using [uffd-ldapd](https://git.cccv.de/uffd/uffd-ldapd) and [uffd-nginxauth](https://git.cccv.de/uffd/uffd-nginxauth/).
 
 
User accounts and mailing list memberships are periodically synchronised with uffd group membership. Authentication is handled using Django's `PersistentRemoteUserMiddleware`, which only requires the login URLs to be proxied through the authentication proxy.
 
 
The CCCV [ansible role](https://git.cccv.de/infra/ansible/roles/mailman/) may also be helpful when configuring this.
 
 
## Installing
 
These examples assume that Mailman 3, uffd-ldapd, and uffd-nginxauth are installed as Debian packages. You should have a basic working Mailman 3 setup before attempting to install this. Nginx should be used as the reverse proxy, and uffd-ldapd and uffd-nginxauth should be installed and configured.
 
 
The `python3-django-auth-ldap` package should also be installed from apt.
 
 
This `postorius_ldap_membership_management` package needs to be accessible by the Mailman installation. This is (currently) possible by checking out the git repo and running the following command as root to install it in the global python packages:
 
```
 
# python3 ./setup.py install
 
```
 
 
## Configuration
 
 
We assume your HTTP hostname is `lists.example.org` and your uffd-ldapd DN is set to `dc=example,dc=org`.
 
 
### Nginx Configuration
 
 
This should probably be in `/etc/nginx/sites-enabled/lists.example.org.conf`:
 
 
```nginx
 
location /mailman3/static/favicon.ico {
 
alias /var/lib/mailman3/web/static/postorius/img/favicon.ico;
 
index index.html index.htm index.php;
 
}
 
 
location /mailman3/static {
 
alias /var/lib/mailman3/web/static;
 
index index.html index.htm index.php;
 
}
 
 
location /oauthproxy/ {
 
rewrite ^/oauthproxy/(.*) /$1 break;
 
include /etc/nginx/uwsgi_params;
 
# The OAuth client credentials must match those configured in uffd.
 
uwsgi_param HTTP_X_REDIRECT_URI "https://lists.example.org/oauthproxy/callback";
 
uwsgi_param HTTP_X_CLIENT_ID "<uffd_client_id>";
 
uwsgi_param HTTP_X_CLIENT_SECRET "<uffd_client_secret>";
 
# those options are needed to have working POST requests
 
uwsgi_param HTTP_CONTENT_LENGTH "";
 
uwsgi_param REQUEST_METHOD "GET";
 
uwsgi_pass_request_body off;
 
 
uwsgi_pass unix:///run/uwsgi/app/uffd-nginxauth/socket;
 
}
 
 
location @error401 {
 
return 302 https://lists.example.org/oauthproxy/login?rawurl=https://lists.example.org$request_uri;
 
}
 
 
location ~ ^/(accounts|admin)/login/ {
 
error_page 401 = @error401;
 
auth_request /oauthproxy/auth;
 
auth_request_set $auth_header $upstream_http_OAUTH_USER_NICKNAME;
 
uwsgi_param REMOTE_USER $auth_header;
 
include /etc/nginx/uwsgi_params;
 
uwsgi_pass unix:///run/mailman3-web/uwsgi.sock;
 
}
 
 
location / {
 
include /etc/nginx/uwsgi_params;
 
uwsgi_pass unix:///run/mailman3-web/uwsgi.sock;
 
}
 
```
 
 
You can check `https://lists.example.org/oauthproxy/status` to confirm that uffd-nginxauth is configured successfully.
 
 
### Mailman3 Configuration
 
 
The following changes need to be made to the Mailman web configuration at `/etc/mailman3/mailman-web.py`:
 
 
```python
 
# Append the app to the list of installed apps:
 
INSTALLED_APPS = (
 
...
 
'postorius_ldap_membership_management'
 
)
 
 
# Copy the MIDDLEWARE statement from /usr/share/mailman3-web/settings.py and append:
 
MIDDLEWARE = (
 
...
 
'django.contrib.auth.middleware.PersistentRemoteUserMiddleware',
 
'postorius_ldap_membership_management.middleware.SessionTimeoutMiddleware',
 
)
 
 
# Replace AUTHENTICATION_BACKENDS
 
AUTHENTICATION_BACKENDS = (
 
'postorius_ldap_membership_management.backends.LdapRemoteUserBackend',
 
)
 
 
# Set session expiry and disable account email verification
 
SESSION_EXPIRE_SECONDS=3600
 
ACCOUNT_EMAIL_VERIFICATION = 'none'
 
```
 
 
Now we configure the LDAP settings in the same file. These configuration options are from the [django-auth-ldap](https://django-auth-ldap.readthedocs.io) module.
 
 
In this example, `list_users` is the uffd group which allows access to the mailing list interface, and `list_admin` provides Mailman admin privileges:
 
 
```python
 
from django_auth_ldap.config import *
 
 
AUTH_LDAP_SERVER_URI = "ldap://localhost"
 
AUTH_LDAP_BIND_DN = "cn=service,ou=system,dc=example,dc=org"
 
# Bind password set in uffd-ldapd config
 
AUTH_LDAP_BIND_PASSWORD = "<bind_password>"
 
 
AUTH_LDAP_CONNECTION_OPTIONS = {}
 
AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,ou=users,dc=example,dc=org"
 
AUTH_LDAP_USER_SEARCH = None
 
AUTH_LDAP_USER_SEARCH_ALL_NAME = LDAPSearch(
 
"ou=users,dc=example,dc=org",
 
ldap.SCOPE_ONELEVEL,
 
"(&(objectClass=posixAccount)(memberOf=cn=list_users,ou=groups,dc=example,dc=org))",
 
["uid"]
 
)
 
AUTH_LDAP_USER_ATTR_MAP = {"first_name": "cn", "email": "mail"}
 
 
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
 
"ou=groups,dc=example,dc=org",
 
ldap.SCOPE_ONELEVEL,
 
"(objectClass=groupOfUniqueNames)"
 
)
 
AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType()
 
 
AUTH_LDAP_ALWAYS_UPDATE_USER = True
 
AUTH_LDAP_CACHE_TIMEOUT = 0
 
 
AUTH_LDAP_FIND_GROUP_PERMS = True
 
AUTH_LDAP_REQUIRE_GROUP = "cn=list_users,dc=example,dc=org"
 
AUTH_LDAP_DENY_GROUP = ""
 
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
 
"is_active": "cn=list_users,ou=groups,dc=example,dc=org",
 
"is_staff": "cn=list_admin,ou=groups,dc=example,dc=org",
 
"is_superuser": "cn=list_admin,ou=groups,dc=example,dc=org",
 
}
 
```
 
 
## Periodic jobs
 
 
At this point, the periodic jobs can be set up. These two commands should be run periodically:
 
 
```
 
/usr/bin/mailman-web syncldapusers
 
/usr/bin/mailman-web syncldapmemberships
 
```
 
 
# Configuring Mailing List Membership
 
 
Now we can configure synchronisation of mailing list membership. Note that the mailing list must be created in the Mailman web interface first.
 
 
This is also configured in `mailman-web.py`. In this example, the list `mygroup@lists.example.org` is configured. Members of `mygroup` are added as members of the list, `mygroup_moderators` are moderators and `mygroup_owners` are owners.
 
 
```python
 
LDAP_MEMBERSHIP_SYNC = {
 
'mygroup@lists.example.org': {
 
'ldap': {
 
'member': {
 
'enabled': True,
 
'dn': 'ou=users,dc=example,dc=org',
 
'filter': "(&(objectClass=posixAccount)(memberOf=cn=mygroup,ou=groups,dc=example,dc=org))",
 
'username_attr': 'uid'
 
},
 
'moderator': {
 
'enabled': True,
 
'dn': 'ou=users,dc=example,dc=org',
 
'filter': "(&(objectClass=posixAccount)(memberOf=cn=mygroup_moderators,ou=groups,dc=example,dc=org))",
 
'username_attr': 'uid'
 
},
 
'owner': {
 
'enabled': True,
 
'dn': 'ou=users,dc=example,dc=org',
 
'filter': "(&(objectClass=posixAccount)(memberOf=cn=mygroup_owners,ou=groups,dc=example,dc=org))",
 
'username_attr': 'uid'
 
}
 
}
 
}
 
}
 
```
 
 
Running the `mailman-web syncldapmemberships` command should now synchronise the membership of this list.
 
\ No newline at end of file
Loading