ldap: allow local accounts and aliases with ldap enabled
In conflicts between local addresses and LDAP addresses the local one will always take priority in mail routing. This is something we now document and guarantee through tests.
This commit is contained in:
@@ -70,8 +70,6 @@ SNM branch corresponding to your NixOS version.
|
|||||||
* [ ] [Mobileconfig](https://support.apple.com/guide/profile-manager/distribute-profiles-manually-pmdbd71ebc9/mac)
|
* [ ] [Mobileconfig](https://support.apple.com/guide/profile-manager/distribute-profiles-manually-pmdbd71ebc9/mac)
|
||||||
* Improve the Forwarding Experience
|
* Improve the Forwarding Experience
|
||||||
* [ ] Support [ARC](https://en.wikipedia.org/wiki/Authenticated_Received_Chain) signing with [Rspamd](https://rspamd.com/doc/modules/arc.html)
|
* [ ] Support [ARC](https://en.wikipedia.org/wiki/Authenticated_Received_Chain) signing with [Rspamd](https://rspamd.com/doc/modules/arc.html)
|
||||||
* User management
|
|
||||||
* [ ] Allow local and LDAP user to coexist
|
|
||||||
* OpenID Connect
|
* OpenID Connect
|
||||||
* Depends on relevant clients adding support, e.g. [Thunderbird](https://bugzilla.mozilla.org/show_bug.cgi?id=1602166)
|
* Depends on relevant clients adding support, e.g. [Thunderbird](https://bugzilla.mozilla.org/show_bug.cgi?id=1602166)
|
||||||
|
|
||||||
|
|||||||
+21
-9
@@ -40,15 +40,25 @@ follow best practices to simplify maintenance.
|
|||||||
Limitations
|
Limitations
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
We have various assertions in place, that prevent using LDAP together with
|
Design choices
|
||||||
other features. Most of them are not technical limitations per se, but instead
|
^^^^^^^^^^^^^^
|
||||||
lack configuration or validation.
|
|
||||||
|
|
||||||
- Local users (:option:`mailserver.loginAccounts`) and aliases
|
These are intentional choices in how the mail server operates that affect the
|
||||||
(:option:`mailserver.extraVirtualAliases`) are not currently allowed with
|
LDAP integration.
|
||||||
:option:`mailserver.ldap.enable` enabled
|
|
||||||
- Aliases based on LDAP attributes are currently not implemented
|
- For mail address routing local accounts always take priority over LDAP accounts.
|
||||||
- Quotas based on LDAP attributes are currently not implemented
|
|
||||||
|
Planned
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
These are features we are interested in but require implementation,
|
||||||
|
documentation and tests.
|
||||||
|
|
||||||
|
- Aliases based on LDAP attributes
|
||||||
|
- Quotas based on LDAP attributes
|
||||||
|
|
||||||
|
Avoided
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
The following features will likely never be implemented, since they would
|
The following features will likely never be implemented, since they would
|
||||||
complicate the setup significantly.
|
complicate the setup significantly.
|
||||||
@@ -58,7 +68,9 @@ complicate the setup significantly.
|
|||||||
- Use of ``homeDirectory``, ``uid``, ``gid`` LDAP attributes (we are
|
- Use of ``homeDirectory``, ``uid``, ``gid`` LDAP attributes (we are
|
||||||
committed to a virtual setup with one vmail user/uid/gid and UUID based home
|
committed to a virtual setup with one vmail user/uid/gid and UUID based home
|
||||||
directories)
|
directories)
|
||||||
|
- Declarative aliases through :option:`mailserver.extraVirtualAliases`. These
|
||||||
|
are limited to local accounts, because Postfix enforces sender ownership based
|
||||||
|
on login identity and does not consult virtual aliases for authorization.
|
||||||
|
|
||||||
Enabling LDAP support
|
Enabling LDAP support
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ NixOS 26.05
|
|||||||
rather than their email address, which is more convenient and consistent
|
rather than their email address, which is more convenient and consistent
|
||||||
with typical LDAP practices. The exact attribute can be customized through
|
with typical LDAP practices. The exact attribute can be customized through
|
||||||
:option:`mailserver.ldap.attributes.username`.
|
:option:`mailserver.ldap.attributes.username`.
|
||||||
|
- Local and LDAP accounts can now co-exist. For overlapping names and addresses
|
||||||
|
the local account will always win.
|
||||||
- The following integrations are deprecated and will be removed before the next
|
- The following integrations are deprecated and will be removed before the next
|
||||||
release:
|
release:
|
||||||
|
|
||||||
|
|||||||
@@ -98,16 +98,6 @@ in
|
|||||||
) config.mailserver.dkim.domains
|
) config.mailserver.dkim.domains
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
++ lib.optionals config.mailserver.ldap.enable [
|
|
||||||
{
|
|
||||||
assertion = config.mailserver.loginAccounts == { };
|
|
||||||
message = "When the LDAP support is enable (mailserver.ldap.enable = true), it is not possible to define mailserver.loginAccounts";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
assertion = config.mailserver.extraVirtualAliases == { };
|
|
||||||
message = "When the LDAP support is enable (mailserver.ldap.enable = true), it is not possible to define mailserver.extraVirtualAliases";
|
|
||||||
}
|
|
||||||
]
|
|
||||||
++
|
++
|
||||||
lib.optionals (config.mailserver.ldap.enable && config.mailserver.mailDirectory != "/var/vmail")
|
lib.optionals (config.mailserver.ldap.enable && config.mailserver.mailDirectory != "/var/vmail")
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -1,7 +1,25 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
|
hashPassword =
|
||||||
|
password:
|
||||||
|
pkgs.runCommand "password-${password}-hashed"
|
||||||
|
{
|
||||||
|
buildInputs = [ pkgs.mkpasswd ];
|
||||||
|
inherit password;
|
||||||
|
}
|
||||||
|
''
|
||||||
|
mkpasswd -s <<<"$password" > $out
|
||||||
|
'';
|
||||||
|
|
||||||
bindPassword = "unsafegibberish";
|
bindPassword = "unsafegibberish";
|
||||||
alicePassword = "testalice";
|
alicePassword = "testalice";
|
||||||
bobPassword = "testbob";
|
bobPassword = "testbob";
|
||||||
|
carolPassword = "testcarol";
|
||||||
|
frankPassword = "testfrank";
|
||||||
|
malloryPassword = "testmallory";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
name = "ldap";
|
name = "ldap";
|
||||||
@@ -83,6 +101,22 @@ in
|
|||||||
mail: bob@example.com
|
mail: bob@example.com
|
||||||
homeDirectory: /home/bob
|
homeDirectory: /home/bob
|
||||||
userPassword: ${bobPassword}
|
userPassword: ${bobPassword}
|
||||||
|
|
||||||
|
dn: cn=carol,ou=users,dc=example
|
||||||
|
entryUUID: 41240499-27e2-4fa2-be4f-4113a77661b1
|
||||||
|
objectClass: inetOrgPerson
|
||||||
|
uid: carol
|
||||||
|
sn: Baz
|
||||||
|
mail: carol@example.com
|
||||||
|
userPassword: ${carolPassword}
|
||||||
|
|
||||||
|
dn: cn=frank,ou=users,dc=example
|
||||||
|
entryUUID: ca16f594-f6b2-418f-87d3-0d02d746461f
|
||||||
|
objectClass: inetOrgPerson
|
||||||
|
uid: frank
|
||||||
|
sn: Moo
|
||||||
|
mail: frank@example.com
|
||||||
|
userPassword: ${frankPassword}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,6 +127,24 @@ in
|
|||||||
localDnsResolver = false;
|
localDnsResolver = false;
|
||||||
indexDir = "/var/lib/dovecot/indices";
|
indexDir = "/var/lib/dovecot/indices";
|
||||||
|
|
||||||
|
extraVirtualAliases = {
|
||||||
|
# Steal frank@example.com from LDAP user frank
|
||||||
|
"frank@example.com" = "mallory@example.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
loginAccounts = {
|
||||||
|
# Colliding local account takes precedence over LDAP account with
|
||||||
|
# same address.
|
||||||
|
"carol@example.com" = {
|
||||||
|
hashedPasswordFile = hashPassword carolPassword;
|
||||||
|
};
|
||||||
|
# Another account used as a virtual alias target to steal
|
||||||
|
# frank@example.com from the LDAP user frank
|
||||||
|
"mallory@example.com" = {
|
||||||
|
hashedPasswordFile = hashPassword malloryPassword;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
ldap = {
|
ldap = {
|
||||||
enable = true;
|
enable = true;
|
||||||
uris = [
|
uris = [
|
||||||
@@ -237,5 +289,37 @@ in
|
|||||||
]))
|
]))
|
||||||
machine.succeed("journalctl -u postfix | grep -q 'Sender address rejected: not owned by user bob'")
|
machine.succeed("journalctl -u postfix | grep -q 'Sender address rejected: not owned by user bob'")
|
||||||
|
|
||||||
|
with subtest("Local addresses take priority over those learnt from LDAP"):
|
||||||
|
# carol@example.com is routed to the local user account
|
||||||
|
machine.succeed(" ".join([
|
||||||
|
"mail-check send-and-read",
|
||||||
|
"--smtp-port 465",
|
||||||
|
"--smtp-ssl",
|
||||||
|
"--smtp-host localhost",
|
||||||
|
"--smtp-username alice", # LDAP user
|
||||||
|
"--imap-host localhost",
|
||||||
|
"--imap-username carol@example.com", # Local user
|
||||||
|
"--from-addr alice@example.com",
|
||||||
|
"--to-addr carol@example.com",
|
||||||
|
"--src-password-file <(echo '${alicePassword}')",
|
||||||
|
"--dst-password-file <(echo '${carolPassword}')",
|
||||||
|
"--ignore-dkim-spf"
|
||||||
|
]))
|
||||||
|
|
||||||
|
# frank@example.com gets routed to mallory@example.com due to a virtual alias
|
||||||
|
machine.succeed(" ".join([
|
||||||
|
"mail-check send-and-read",
|
||||||
|
"--smtp-port 465",
|
||||||
|
"--smtp-ssl",
|
||||||
|
"--smtp-host localhost",
|
||||||
|
"--smtp-username alice", # LDAP user
|
||||||
|
"--imap-host localhost",
|
||||||
|
"--imap-username mallory@example.com", # Local user
|
||||||
|
"--from-addr alice@example.com",
|
||||||
|
"--to-addr frank@example.com",
|
||||||
|
"--src-password-file <(echo '${alicePassword}')",
|
||||||
|
"--dst-password-file <(echo '${malloryPassword}')",
|
||||||
|
"--ignore-dkim-spf"
|
||||||
|
]))
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user