From cc0bc4a638e9959b30b8150b067178c043021183 Mon Sep 17 00:00:00 2001 From: Max Erenberg Date: Thu, 19 Aug 2021 16:14:41 +0000 Subject: [PATCH] add tests for Mailman API --- ceod/api/krb5_cred_handlers.py | 2 + tests/ceod/api/test_mailman.py | 14 +++++++ tests/ceod/model/test_group.py | 4 +- tests/ceod/model/test_user.py | 10 ++--- tests/ceod/model/test_uwldap.py | 2 +- tests/ceod_test_local.ini | 2 +- tests/conftest.py | 74 ++++++++++++++++++++------------- tests/conftest_ceod_api.py | 5 +++ 8 files changed, 75 insertions(+), 38 deletions(-) create mode 100644 tests/ceod/api/test_mailman.py diff --git a/ceod/api/krb5_cred_handlers.py b/ceod/api/krb5_cred_handlers.py index 0cf26f7..237e6aa 100644 --- a/ceod/api/krb5_cred_handlers.py +++ b/ceod/api/krb5_cred_handlers.py @@ -25,5 +25,7 @@ def teardown_request(err): try: ctx = g.stored_creds_ctx ctx.__exit__(None, None, None) + g.pop('sasl_user') + g.pop('stored_creds_ctx') except Exception: logger.error(traceback.format_exc()) diff --git a/tests/ceod/api/test_mailman.py b/tests/ceod/api/test_mailman.py new file mode 100644 index 0000000..d55384f --- /dev/null +++ b/tests/ceod/api/test_mailman.py @@ -0,0 +1,14 @@ +def test_subscriptions(cfg, client, ldap_user, mock_mailman_server): + base_domain = cfg.get('base_domain') + uid = ldap_user.uid + address = f'{uid}@{base_domain}' + + status, data = client.post(f'/api/mailman/csc-general/{uid}') + assert status == 200 + assert data == {'result': 'OK'} + assert address in mock_mailman_server.subscriptions['csc-general'] + + status, data = client.delete(f'/api/mailman/csc-general/{uid}') + assert status == 200 + assert data == {'result': 'OK'} + assert address not in mock_mailman_server.subscriptions['csc-general'] diff --git a/tests/ceod/model/test_group.py b/tests/ceod/model/test_group.py index c246646..2ae2d45 100644 --- a/tests/ceod/model/test_group.py +++ b/tests/ceod/model/test_group.py @@ -3,7 +3,7 @@ import pytest from ceo_common.errors import GroupNotFoundError -def test_group_add_to_ldap(simple_group, ldap_srv, g_admin): +def test_group_add_to_ldap(simple_group, ldap_srv): group = simple_group group.add_to_ldap() @@ -15,7 +15,7 @@ def test_group_add_to_ldap(simple_group, ldap_srv, g_admin): ldap_srv.get_group(group.cn) -def test_group_members(ldap_group, ldap_srv, g_admin): +def test_group_members(ldap_group, ldap_srv): group = ldap_group group.add_member('member1') diff --git a/tests/ceod/model/test_user.py b/tests/ceod/model/test_user.py index 2d8e92b..cf98924 100644 --- a/tests/ceod/model/test_user.py +++ b/tests/ceod/model/test_user.py @@ -7,7 +7,7 @@ from ceo_common.errors import UserNotFoundError, UserAlreadyExistsError from ceod.model import User -def test_user_add_to_ldap(cfg, ldap_srv, simple_user, g_admin): +def test_user_add_to_ldap(cfg, ldap_srv, simple_user): user = simple_user min_id = cfg.get('members_min_id') user.add_to_ldap() @@ -23,7 +23,7 @@ def test_user_add_to_ldap(cfg, ldap_srv, simple_user, g_admin): ldap_srv.get_user(user.uid) -def test_club_add_to_ldap(cfg, ldap_srv, simple_club, g_admin): +def test_club_add_to_ldap(cfg, ldap_srv, simple_club): club = simple_club min_id = cfg.get('clubs_min_id') club.add_to_ldap() @@ -74,7 +74,7 @@ def test_user_forwarding_addresses(cfg, ldap_user): assert not os.path.isdir(user.home_directory) -def test_user_terms(ldap_user, ldap_srv, g_admin): +def test_user_terms(ldap_user, ldap_srv): user = ldap_user user.add_terms(['f2021']) @@ -86,7 +86,7 @@ def test_user_terms(ldap_user, ldap_srv, g_admin): assert ldap_srv.get_user(user.uid).non_member_terms == user.non_member_terms -def test_user_positions(ldap_user, ldap_srv, g_admin): +def test_user_positions(ldap_user, ldap_srv): user = ldap_user user.add_position('treasurer') @@ -108,7 +108,7 @@ def test_user_change_password(krb_user): user.change_password('new_password') -def test_login_shell(ldap_user, ldap_srv, g_admin): +def test_login_shell(ldap_user, ldap_srv): user = ldap_user user.replace_login_shell('/bin/sh') diff --git a/tests/ceod/model/test_uwldap.py b/tests/ceod/model/test_uwldap.py index ccb58b5..efd758b 100644 --- a/tests/ceod/model/test_uwldap.py +++ b/tests/ceod/model/test_uwldap.py @@ -10,7 +10,7 @@ def test_uwldap_get(uwldap_srv, uwldap_user): def test_ldap_updateprograms( - cfg, ldap_conn, ldap_srv, uwldap_srv, ldap_user, uwldap_user, g_admin): + cfg, ldap_conn, ldap_srv, uwldap_srv, ldap_user, uwldap_user): # sanity check assert ldap_user.uid == uwldap_user.uid # modify the user's program in UWLDAP diff --git a/tests/ceod_test_local.ini b/tests/ceod_test_local.ini index bf233bd..f86bdea 100644 --- a/tests/ceod_test_local.ini +++ b/tests/ceod_test_local.ini @@ -4,7 +4,7 @@ base_domain = csclub.internal [ceod] admin_host = phosphoric-acid fs_root_host = phosphoric-acid -mailman_host = mail +mailman_host = phosphoric-acid krb5_cache_dir = /tmp/ceod_test_krb5_cache use_https = false port = 9987 diff --git a/tests/conftest.py b/tests/conftest.py index a75d93e..86f1fe3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import contextlib import importlib.resources import os import shutil @@ -70,6 +71,27 @@ def ceod_admin_creds(cfg, krb_srv): ) +@pytest.fixture +def g_admin_ctx(cfg, ceod_admin_creds, app): + """ + Store the principal for ceod/admin in flask.g. + This context manager should be used any time LDAP is modified via the + LDAPService, and we are not in a request context. + This should NOT be active when CeodTestClient is making a request, since + that will override the values in flask.g. + """ + @contextlib.contextmanager + def wrapper(): + admin_principal = cfg.get('ldap_admin_principal') + with app.app_context(): + try: + flask.g.sasl_user = admin_principal + yield + finally: + flask.g.pop('sasl_user') + return wrapper + + @pytest.fixture(scope='session') def ldap_conn(cfg, ceod_admin_creds) -> ldap3.Connection: # Assume that the same server URL is being used for the CSC @@ -85,7 +107,7 @@ def ldap_conn(cfg, ceod_admin_creds) -> ldap3.Connection: @pytest.fixture(scope='session') -def ldap_srv(cfg, krb_srv, ldap_conn): +def ldap_srv_session(cfg, krb_srv, ldap_conn): conn = ldap_conn users_base = cfg.get('ldap_users_base') groups_base = cfg.get('ldap_groups_base') @@ -98,12 +120,22 @@ def ldap_srv(cfg, krb_srv, ldap_conn): conn.add(base_dn, 'organizationalUnit') _ldap_srv = LDAPService() component.provideUtility(_ldap_srv, ILDAPService) + yield _ldap_srv delete_subtree(conn, users_base) delete_subtree(conn, groups_base) +@pytest.fixture +def ldap_srv(ldap_srv_session, g_admin_ctx): + # This is an ugly hack to get around the fact that function-scoped + # fixtures (g_admin_ctx) can't be used from session-scoped fixtures + # (ldap_srv_session). + with g_admin_ctx(): + yield ldap_srv_session + + @pytest.fixture(scope='session') def file_srv(cfg): _file_srv = FileService() @@ -145,7 +177,6 @@ def mailman_srv(mock_mailman_server, cfg, http_client): def uwldap_srv(cfg, ldap_conn): conn = ldap_conn base_dn = cfg.get('uwldap_base') - ou = base_dn.split(',', 1)[0].split('=')[1] delete_subtree(conn, base_dn) @@ -176,35 +207,16 @@ def mail_srv(cfg, mock_mail_server): def app( cfg, krb_srv, - ldap_srv, + ldap_srv_session, file_srv, mailman_srv, uwldap_srv, mail_srv, ): - # need to be root to read keytab - assert os.geteuid() == 0 - app = create_app({ - 'TESTING': True, - }) + app = create_app({'TESTING': True}) return app -@pytest.fixture -def g_admin(cfg, ceod_admin_creds, app): - """ - Store the creds for ceod/admin in flask.g. - This fixture should be used any time LDAP is modified via the LDAPService. - """ - admin_principal = cfg.get('ldap_admin_principal') - with app.app_context(): - try: - flask.g.sasl_user = admin_principal - yield - finally: - flask.g.pop('sasl_user') - - @pytest.fixture def simple_user(): return User( @@ -225,10 +237,12 @@ def simple_club(): @pytest.fixture -def ldap_user(simple_user, g_admin): - simple_user.add_to_ldap() +def ldap_user(simple_user, g_admin_ctx): + with g_admin_ctx(): + simple_user.add_to_ldap() yield simple_user - simple_user.remove_from_ldap() + with g_admin_ctx(): + simple_user.remove_from_ldap() @pytest.fixture @@ -247,10 +261,12 @@ def simple_group(): @pytest.fixture -def ldap_group(simple_group, g_admin): - simple_group.add_to_ldap() +def ldap_group(simple_group, g_admin_ctx): + with g_admin_ctx(): + simple_group.add_to_ldap() yield simple_group - simple_group.remove_from_ldap() + with g_admin_ctx(): + simple_group.remove_from_ldap() @pytest.fixture diff --git a/tests/conftest_ceod_api.py b/tests/conftest_ceod_api.py index 70d2fcf..fe76cb2 100644 --- a/tests/conftest_ceod_api.py +++ b/tests/conftest_ceod_api.py @@ -4,6 +4,7 @@ import socket import subprocess import tempfile +from flask import g from flask.testing import FlaskClient import gssapi import pytest @@ -68,6 +69,10 @@ class CeodTestClient: return headers def request(self, method, path, principal, **kwargs): + # Make sure that we're not already in a request context, otherwise + # g will get overridden + with pytest.raises(RuntimeError): + '' in g if principal is None: principal = self.syscom_principal resp = self.client.open(