implemented a function that checks some parts of the configuration

This commit is contained in:
Éloi Rivard 2021-10-12 20:36:31 +02:00 committed by Éloi Rivard
parent 30e071dcaf
commit d0b4121945
6 changed files with 152 additions and 84 deletions

View file

@ -1,3 +1,5 @@
import ldap
import smtplib
import os
from cryptography.hazmat.primitives import serialization as crypto_serialization
@ -12,6 +14,28 @@ def validate(config, validate_remote=False):
if not os.path.exists(config["JWT"]["PRIVATE_KEY"]):
raise Exception(f'Private key does not exist {config["JWT"]["PRIVATE_KEY"]}')
if not validate_remote:
return
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()
with smtplib.SMTP(
host=config["SMTP"]["HOST"],
port=config["SMTP"]["PORT"],
) as smtp:
if config["SMTP"].get("TLS"):
smtp.starttls()
if config["SMTP"].get("LOGIN"):
smtp.login(
user=config["SMTP"]["LOGIN"],
password=config["SMTP"].get("PASSWORD"),
)
def setup_dev_keypair(config):
if os.path.exists(config["JWT"]["PUBLIC_KEY"]) or os.path.exists(

View file

@ -60,6 +60,7 @@ deps =
pdbpp
pytest
slapd
smtpdfix
[testenv:doc]
deps =
@ -77,6 +78,7 @@ deps =
pytest
pytest-coverage
slapd
smtpdfix
commands =
{envbindir}/pytest --cov {posargs}

View file

@ -121,12 +121,10 @@ def slapd_connection(slapd_server):
@pytest.fixture
def app(slapd_server, keypair_path):
os.environ["AUTHLIB_INSECURE_TRANSPORT"] = "true"
def configuration(slapd_server, smtpd, keypair_path):
smtpd.config.use_starttls = True
private_key_path, public_key_path = keypair_path
app = create_app(
{
return {
"SECRET_KEY": gen_salt(24),
"OAUTH2_METADATA_FILE": "canaille/conf/oauth-authorization-server.sample.json",
"OIDC_METADATA_FILE": "canaille/conf/openid-configuration.sample.json",
@ -174,15 +172,20 @@ def app(slapd_server, keypair_path):
},
},
"SMTP": {
"HOST": "localhost",
"PORT": 25,
"HOST": smtpd.hostname,
"PORT": smtpd.port,
"TLS": True,
"LOGIN": "smtp_login",
"PASSWORD": "smtp_password",
"LOGIN": smtpd.config.login_username,
"PASSWORD": smtpd.config.login_password,
"FROM_ADDR": "admin@mydomain.tld",
},
}
)
@pytest.fixture
def app(configuration):
os.environ["AUTHLIB_INSECURE_TRANSPORT"] = "true"
app = create_app(configuration)
return app
@ -346,14 +349,21 @@ def logged_moderator(moderator, testclient):
@pytest.fixture(autouse=True)
def cleanups(slapd_connection):
yield
try:
for consent in Consent.filter(conn=slapd_connection):
consent.delete(conn=slapd_connection)
except Exception:
pass
@pytest.fixture
def foo_group(app, user, slapd_connection):
Group.ocs_by_name(slapd_connection)
g = Group(objectClass=["groupOfNames"], member=[user.dn], cn="foo",)
g = Group(
objectClass=["groupOfNames"],
member=[user.dn],
cn="foo",
)
g.save(slapd_connection)
with app.app_context():
user.load_groups(conn=slapd_connection)
@ -365,7 +375,11 @@ def foo_group(app, user, slapd_connection):
@pytest.fixture
def bar_group(app, admin, slapd_connection):
Group.ocs_by_name(slapd_connection)
g = Group(objectClass=["groupOfNames"], member=[admin.dn], cn="bar",)
g = Group(
objectClass=["groupOfNames"],
member=[admin.dn],
cn="bar",
)
g.save(slapd_connection)
with app.app_context():
admin.load_groups(conn=slapd_connection)

View file

@ -0,0 +1,37 @@
import ldap
import pytest
import smtplib
import socket
from canaille.configuration import validate
def test_ldap_connection_no_remote(configuration):
validate(configuration)
def test_ldap_connection_remote(configuration):
validate(configuration, validate_remote=True)
def test_ldap_connection_remote_ldap_unreachable(configuration):
configuration["LDAP"]["URI"] = "ldap://invalid-ldap.com"
with pytest.raises(ldap.SERVER_DOWN):
validate(configuration, validate_remote=True)
def test_ldap_connection_remote_ldap_wrong_credentials(configuration):
configuration["LDAP"]["BIND_PW"] = "invalid-password"
with pytest.raises(ldap.INVALID_CREDENTIALS):
validate(configuration, validate_remote=True)
def test_smtp_connection_remote_smtp_unreachable(configuration):
configuration["SMTP"]["HOST"] = "smtp://invalid-smtp.com"
with pytest.raises(socket.gaierror):
validate(configuration, validate_remote=True)
def test_smtp_connection_remote_smtp_wrong_credentials(configuration):
configuration["SMTP"]["PASSWORD"] = "invalid-password"
with pytest.raises(smtplib.SMTPAuthenticationError):
validate(configuration, validate_remote=True)

View file

@ -1,8 +1,4 @@
import mock
@mock.patch("smtplib.SMTP")
def test_password_forgotten(SMTP, testclient, slapd_connection, user):
def test_password_forgotten(smtpd, testclient, slapd_connection, user):
res = testclient.get("/reset", status=200)
res.form["login"] = "user"
@ -10,22 +6,20 @@ def test_password_forgotten(SMTP, testclient, slapd_connection, user):
assert "A password reset link has been sent at your email address." in res.text
assert "Send again" in res.text
SMTP.assert_called_once_with(host="localhost", port=25)
assert len(smtpd.messages) == 1
@mock.patch("smtplib.SMTP")
def test_password_forgotten_invalid_form(SMTP, testclient, slapd_connection, user):
def test_password_forgotten_invalid_form(smtpd, testclient, slapd_connection, user):
res = testclient.get("/reset", status=200)
res.form["login"] = ""
res = res.form.submit(status=200)
assert "Could not send the password reset link." in res.text
SMTP.assert_not_called()
assert len(smtpd.messages) == 0
@mock.patch("smtplib.SMTP")
def test_password_forgotten_invalid(SMTP, testclient, slapd_connection, user):
def test_password_forgotten_invalid(smtpd, testclient, slapd_connection, user):
testclient.app.config["HIDE_INVALID_LOGINS"] = False
res = testclient.get("/reset", status=200)
@ -42,4 +36,4 @@ def test_password_forgotten_invalid(SMTP, testclient, slapd_connection, user):
assert "A password reset link has been sent at your email address." not in res.text
assert "The login 'i-dont-really-exist' does not exist" in res.text
SMTP.assert_not_called()
assert len(smtpd.messages) == 0

View file

@ -1,4 +1,3 @@
import mock
from canaille.models import User
@ -182,8 +181,7 @@ def test_user_creation_edition_and_deletion(
assert "george" not in res.text
@mock.patch("smtplib.SMTP")
def test_first_login_mail_button(SMTP, testclient, slapd_connection, logged_admin):
def test_first_login_mail_button(smtpd, testclient, slapd_connection, logged_admin):
User.ocs_by_name(slapd_connection)
u = User(
objectClass=["inetOrgPerson"],
@ -206,7 +204,7 @@ def test_first_login_mail_button(SMTP, testclient, slapd_connection, logged_admi
in res
)
assert "Send again" in res
SMTP.assert_called_once_with(host="localhost", port=25)
assert len(smtpd.messages) == 1
u.reload(slapd_connection)
u.userPassword = ["{SSHA}fw9DYeF/gHTHuVMepsQzVYAkffGcU8Fz"]
@ -216,8 +214,7 @@ def test_first_login_mail_button(SMTP, testclient, slapd_connection, logged_admi
assert "This user does not have a password yet" not in res
@mock.patch("smtplib.SMTP")
def test_email_reset_button(SMTP, testclient, slapd_connection, logged_admin):
def test_email_reset_button(smtpd, testclient, slapd_connection, logged_admin):
User.ocs_by_name(slapd_connection)
u = User(
objectClass=["inetOrgPerson"],
@ -230,7 +227,7 @@ def test_email_reset_button(SMTP, testclient, slapd_connection, logged_admin):
u.save(slapd_connection)
res = testclient.get("/profile/temp", status=200)
assert "If the user has forgotten his password" in res
assert "If the user has forgotten his password" in res, res.text
assert "Send" in res
res = res.form.submit(name="action", value="password-reset-mail", status=200)
@ -239,4 +236,4 @@ def test_email_reset_button(SMTP, testclient, slapd_connection, logged_admin):
in res
)
assert "Send again" in res
SMTP.assert_called_once_with(host="localhost", port=25)
assert len(smtpd.messages) == 1