|
1 | 1 | # ucs2mailman.py
|
2 | 2 |
|
3 |
| -Script to read LDAP directory on UCS server and manage |
4 |
| -appropriate mailman3 mailing lists. |
| 3 | +Script to read LDAP directory on a UCS server and manage |
| 4 | +mailman3 mailing lists corresponding to the LDAP groups. |
5 | 5 |
|
6 |
| -LDAP groups with mailAddress: that is not None will have |
7 |
| -should have mailman lists with the users subscribed. |
| 6 | +The straight forward use of this script is translating LDAP groups |
| 7 | +with mailAddress: (which is not None) to mailman lists with that |
| 8 | +name and all group members as subscribers. The subscription will |
| 9 | +happen with the main identity (uid @ domain), and all the other |
| 10 | +known user mail addresses from the LDAP users will be added as |
| 11 | +non-members which can post without being moderated. |
8 | 12 |
|
9 |
| -Purpose of the script is to sync from UCS to mailman: |
10 |
| -* Create missing lists |
11 |
| -* Add missing users |
12 |
| -* Remove extra users |
13 |
| -* Also create whitelist for other mail addresses |
14 |
| - of subscribers. These will not typically cleaned |
15 |
| - up as we don't know, whether these have been added |
16 |
| - by the admin and should stay ... |
| 13 | +As UCS does mail forwarding from the groups already (without |
| 14 | +offering a full feature set for mailing lists), it is a good |
| 15 | +idea to leave the normal UCS redistribution in place and create |
| 16 | +mailing lists with different names. Using a secondary domain |
| 17 | +(option ``-t``), adding a prefix (``-p``) or using arbitrary |
| 18 | +name replacements (``-r``) can be used to implement this. |
17 | 19 |
|
| 20 | +It's also possible to only handle a subset of the LDAP groups |
| 21 | +by using filters (options ``-f`` and ``-x``). Lists can also |
| 22 | +be set to only ever have group members added but never removed |
| 23 | +(``-k``). Without this option, subscribers from the managed |
| 24 | +lists that are not (no longer) part of the respective LDAP |
| 25 | +group will be removed from the list. |
18 | 26 |
|
| 27 | +ucs2mailman.py will only do changes to the lists that have |
| 28 | +mailAddress: set in the UCS group directory (after applying |
| 29 | +the translations from option ``-p``, ``-r``, ``-t`` -- in |
| 30 | +this order) and the filters (``-f``, ``-x``), so manually |
| 31 | +managed lists, partially managed lists (``-k``) and fully |
| 32 | +automatically managed lists can coexist on the same mailman3 |
| 33 | +instance. |
| 34 | + |
| 35 | +Note that the changes to the mailman3 config are performed |
| 36 | +with the user identity of mailman3 owner, ``list`` on Debian |
| 37 | +(UCS) systems. The script will change its euid/egid to this |
| 38 | +identity (unless overriden by ``-s``), so it needs to be started |
| 39 | +with this identity already or as root. (``-s ""`` would skip |
| 40 | +the switching, but you'll likely not be able to talk to mailman3 |
| 41 | +this way.) |
| 42 | + |
| 43 | +## Installation and usage |
| 44 | + |
| 45 | +You need to have mailman3 installed and set up and an admin |
| 46 | +user configured which you pass with option ``-a`` as owner/ |
| 47 | +admin for any newly created lists. |
| 48 | + |
| 49 | +By default, the script calls ``udm`` to get UCS LDAP users |
| 50 | +and group lists -- note that this typically requires root privileges. |
| 51 | +You can instead use the options ``-u`` and ``-g`` to read the |
| 52 | +directory from files. (It is advisable to strip hashed passwords |
| 53 | +and jpegPhotos from dumps that end up on your disk.) |
| 54 | + |
| 55 | +On UCS hosts, your postfix configuration is automatically generated |
| 56 | +by the univention scripts. To have mailman3 work, you need to tweak |
| 57 | +the config file creation logic. Apply the patch from |
| 58 | +``integration/postfix-mailman.diff``. |
| 59 | + |
| 60 | +Next step is to monitor the user/group database and ensure that changes |
| 61 | +are automatically reflected in mailman subscriptions. On UCS, this can be |
| 62 | +done by calling ``integration/new_udm.sh`` every few minutes from a cron |
| 63 | +job as root. The script will then call ``/var/list/update_mls.sh`` as user |
| 64 | +``list`` *if* the user/group databases have changed. Copy |
| 65 | +``integration/update_mls.sh`` there (and make sure ``new_udm.sh`` and |
| 66 | +``update_mls.sh`` are executable by the respective users). |
| 67 | + |
| 68 | +## Testing |
| 69 | + |
| 70 | +You can use the options ``-d`` and ``-n`` to test and understand |
| 71 | +what changes ``ucs2mailman.py`` would to your mailings lists |
| 72 | +prior to having it performing changes. |
| 73 | + |
| 74 | +There is a test script which tests creation of mailing lists, adding |
| 75 | +users and changing and removing users. See ``test/`` directory. |
| 76 | + |
| 77 | +## TODO |
| 78 | + |
| 79 | +The LDAP (LDIF) parsing does understand the formatting from |
| 80 | +``udm`` output as well as plain ``ldapsearch`` output (if you switch |
| 81 | +off line wrapping). However, ``ucs2mailman.py`` has really been |
| 82 | +developed for being run on a UCS instance, so expect a few tweaks |
| 83 | +to be required on non-UCS LDAP hosts for it to really be useful. |
| 84 | +Patches (pull requests) are welcome! |
| 85 | + |
| 86 | +mailman3 has a REST interface -- from hindsight, it might have been |
| 87 | +cleaner to use it to create mailing lists and handle subscription |
| 88 | +management. This would have avoided to change the identity to |
| 89 | +the mailman3 user. I have not investigated whether the REST interface |
| 90 | +exposes all needed controls and is straight forward to talk to, so this |
| 91 | +may or may not be a practical approach. |
| 92 | + |
| 93 | +The ``test/`` directory would likely benefit from more test cases. |
| 94 | + |
| 95 | +UCS offers to run scripts via "listener plugins" after changes to the |
| 96 | +LDAP directory, see |
| 97 | +https://docs.software-univention.de/developer-reference-5.0.html#chap:listener |
| 98 | +We could filter group changes and implement a ``postrun`` action. This |
| 99 | +would seem cleaner than looking at the database file every few minutes |
| 100 | +from a cron job. |
| 101 | + |
| 102 | +## Output from ``-h`` |
| 103 | + |
| 104 | +<pre> |
| 105 | +Usage: ucs2mailman.py [-d] [-n] [-h] [-a adminMail] [-t DOMAIN] [-p PREFIX] |
| 106 | + [-r SRC,DST [-r ...] [-f LIST[,LIST]] [-x LIST[,LIST]] [-u FILE] [-g FILE] |
| 107 | +(c) Kurt Garloff <garloff@osb-alliance.com>, 9/2021, AGPL-v3 |
| 108 | +ucs2mailman.py calls udm to get lists of groups and users from UCS LDAP. |
| 109 | +Alternatively it can also process ldapsearch output (ldapsearch -o "ldif-wrap=255"), |
| 110 | + see options -u -g to read UDM/ldapsearch output from files. |
| 111 | +It then gets the mailing list with subscribers and nonMembers from Mailman3. |
| 112 | +It then ensures that all LDAP groups with mailAddress have a corresponding |
| 113 | +MailMan3 mailing list (ML) and that all group members are subscribed to it |
| 114 | +and all other known mail addresses from subscribers are added as non-members |
| 115 | +to allow them to have unmoderated posting. Extra subscribers (not in LDAP group) |
| 116 | +will be removed (unless -k is given), extra non-members are left alone. |
| 117 | +Extra lists are also left alone. |
| 118 | +Note that you will typically need to run this as root (with sudo). |
| 119 | +Options: -d => debug output |
| 120 | + -n => don't do any changes to MailMan, just print actions |
| 121 | + -k => keep subscribers, only add, don't delete (but print) |
| 122 | + -h => output this help an exit |
| 123 | + -a adminMail => use this user as owner/moderator for newly created lists (must exist!) |
| 124 | + -p PREFIX => prepend prefix to mailing list names |
| 125 | + -r SRC,DST => replace ML name SRC with DST (after -p, skips -t), can be used multiple times |
| 126 | + -t DOMAIN => replace mailAddress domain with DOMAIN for the ML |
| 127 | + -f LIST[,LIST] => only process mailing list LIST(s) (matching happens after applying -p/-r/-t) |
| 128 | + -x LIST[,LIST] => do not process mailing list LIST(s) (matching happens after applying -p/-r/-t) |
| 129 | + -u FILE => use user list from file (ldif) instead of calling udm |
| 130 | + -g FILE => use group list from file (ldif) instead of calling udm |
| 131 | + -s user => switch ID (uid and gid) to to user (name) for mm3 config, default list |
| 132 | +</pre> |
0 commit comments