diff --git a/canaille/configuration.py b/canaille/configuration.py index c9347963..dbac99b8 100644 --- a/canaille/configuration.py +++ b/canaille/configuration.py @@ -2,6 +2,7 @@ import ldap import os import smtplib import socket +import uuid from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa @@ -31,12 +32,13 @@ def validate(config, validate_remote=False): def validate_ldap_configuration(config): + from canaille.models import User, Group + try: conn = ldap.initialize(config["LDAP"]["URI"]) if config["LDAP"].get("TIMEOUT"): conn.set_option(ldap.OPT_NETWORK_TIMEOUT, config["LDAP"]["TIMEOUT"]) conn.simple_bind_s(config["LDAP"]["BIND_DN"], config["LDAP"]["BIND_PW"]) - conn.unbind_s() except ldap.SERVER_DOWN as exc: raise ConfigurationException( @@ -48,6 +50,57 @@ def validate_ldap_configuration(config): f'LDAP authentication failed with user \'{config["LDAP"]["BIND_DN"]}\'' ) from exc + try: + User.ocs_by_name(conn) + user = User( + objectClass=["inetOrgPerson"], + cn=f"canaille_{uuid.uuid4()}", + sn=f"canaille_{uuid.uuid4()}", + uid=f"canaille_{uuid.uuid4()}", + mail=f"canaille_{uuid.uuid4()}@mydomain.tld", + userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz", + ) + user.save(conn) + user.delete(conn) + + except ldap.INSUFFICIENT_ACCESS as exc: + raise ConfigurationException( + f'LDAP user \'{config["LDAP"]["BIND_DN"]}\' cannot create ' + f'users at \'{config["LDAP"]["USER_BASE"]}\'' + ) from exc + + try: + Group.ocs_by_name(conn) + + user = User( + objectClass=["inetOrgPerson"], + cn=f"canaille_{uuid.uuid4()}", + sn=f"canaille_{uuid.uuid4()}", + uid=f"canaille_{uuid.uuid4()}", + mail=f"canaille_{uuid.uuid4()}@mydomain.tld", + userPassword="{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz", + ) + user.save(conn) + + group = Group( + objectClass=["groupOfNames"], + cn=f"canaille_{uuid.uuid4()}", + member=[user.dn], + ) + group.save(conn) + group.delete(conn) + + except ldap.INSUFFICIENT_ACCESS as exc: + raise ConfigurationException( + f'LDAP user \'{config["LDAP"]["BIND_DN"]}\' cannot create ' + f'groups at \'{config["LDAP"]["GROUP_BASE"]}\'' + ) from exc + + finally: + user.delete(conn) + + conn.unbind_s() + def validate_smtp_configuration(config): try: diff --git a/tests/test_configuration.py b/tests/test_configuration.py index fefc599a..fc86753b 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -1,3 +1,5 @@ +import ldap +import mock import pytest from canaille.commands import cli from canaille.configuration import validate, ConfigurationException @@ -47,6 +49,34 @@ def test_ldap_connection_remote_ldap_wrong_credentials(configuration): validate(configuration, validate_remote=True) +def test_ldap_cannot_create_users(configuration): + from canaille.models import User + + def fake_init(*args, **kwarg): + raise ldap.INSUFFICIENT_ACCESS + + with mock.patch.object(User, "__init__", fake_init): + with pytest.raises( + ConfigurationException, + match=r"cannot create users at", + ): + validate(configuration, validate_remote=True) + + +def test_ldap_cannot_create_groups(configuration): + from canaille.models import Group + + def fake_init(*args, **kwarg): + raise ldap.INSUFFICIENT_ACCESS + + with mock.patch.object(Group, "__init__", fake_init): + with pytest.raises( + ConfigurationException, + match=r"cannot create groups at", + ): + validate(configuration, validate_remote=True) + + def test_smtp_connection_remote_smtp_unreachable(configuration): configuration["SMTP"]["HOST"] = "smtp://invalid-smtp.com" with pytest.raises(