Skip to content

Commit 04b7fa6

Browse files
committed
Add a coarse filter on allowed peers values in external account requests.
Should be extended with one or more basic unit tests of the new accountreq helpers.
1 parent 8d6a5d6 commit 04b7fa6

File tree

8 files changed

+76
-4
lines changed

8 files changed

+76
-4
lines changed

mig/install/MiGserver-template.conf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,11 @@ password_policy = __PASSWORD_POLICY__
761761
password_legacy_policy = __PASSWORD_LEGACY_POLICY__
762762
# Optional additional guard against simple passwords with the cracklib library
763763
password_cracklib = __ENABLE_CRACKLIB__
764+
# Optional prefilter on users who may potenially invite peers as site users.
765+
# Used as a coarse filter to reject clearly invalid user requests early.
766+
# Space separated list of user field and regexp-filter pattern pairs separated
767+
# by colons.
768+
peers_prefilter = __PEERS_PREFILTER__
764769
# Optional limit on users who may invite peers as site users. Space separated
765770
# list of user field and regexp-filter pattern pairs separated by colons.
766771
peers_permit = __PEERS_PERMIT__

mig/shared/accountreq.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,15 @@ def list_country_codes(configuration):
11731173
return country_list
11741174

11751175

1176+
def prefilter_potential_peers(peers_list, configuration):
1177+
"""Return entries from peers_list that fit local prefilter policy"""
1178+
potential_peers = []
1179+
for peer_dict in peers_list:
1180+
if peers_prefilter_allowed(configuration, peer_dict):
1181+
potential_peers.append(peer_dict)
1182+
return potential_peers
1183+
1184+
11761185
def forced_org_email_match(org, email, configuration):
11771186
"""Check that email and organization follow the required policy"""
11781187

@@ -1322,6 +1331,16 @@ def auto_add_user_allowed_with_peer(configuration, user_dict):
13221331
return __auto_add_user_allowed(configuration, user_dict,
13231332
configuration.auto_add_user_with_peer)
13241333

1334+
def peers_prefilter_allowed(configuration, user_dict):
1335+
"""Check if user with user_dict is potentially allowed to manage peers
1336+
soleley based on optional configuration prefilter.
1337+
Please use peers_permit_allowed too before actually allowing user as peer.
1338+
"""
1339+
for (key, val) in configuration.site_peers_prefilter:
1340+
if not re.match(val, user_dict.get(key, 'NO SUCH FIELD')):
1341+
return False
1342+
return True
1343+
13251344

13261345
def peers_permit_allowed(configuration, user_dict):
13271346
"""Check if user with user_dict is allowed to manage peers based on

mig/shared/configuration.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ def get(self, *args, **kwargs):
529529
'site_signup_methods': ['extcert'],
530530
'site_login_methods': ['extcert'],
531531
'site_signup_hint': "",
532+
'site_peers_prefilter': [('email', '.*')],
532533
'site_peers_permit': [('distinguished_name', '.*')],
533534
'site_peers_notice': "",
534535
# TODO: switch to CSRF_FULL when rpc and scripts are ready?
@@ -2138,6 +2139,9 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
21382139
self.site_login_methods = self.site_signup_methods
21392140
if config.has_option('SITE', 'signup_hint'):
21402141
self.site_signup_hint = config.get('SITE', 'signup_hint').strip()
2142+
if config.has_option('SITE', 'peers_prefilter'):
2143+
req = config.get('SITE', 'peers_prefilter').split()
2144+
self.site_peers_prefilter = [i.split(':', 2) for i in req]
21412145
if config.has_option('SITE', 'peers_permit'):
21422146
req = config.get('SITE', 'peers_permit').split()
21432147
self.site_peers_permit = [i.split(':', 2) for i in req]

mig/shared/functionality/reqcertaction.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# reqcertaction - handle certificate account requests and send email to admins
7-
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2025 The MiG Project by the Science HPC Center at UCPH
88
#
99
# This file is part of MiG.
1010
#
@@ -37,7 +37,7 @@
3737

3838
from mig.shared import returnvalues
3939
from mig.shared.accountreq import existing_country_code, forced_org_email_match, \
40-
user_manage_commands, save_account_request
40+
prefilter_potential_peers, user_manage_commands, save_account_request
4141
from mig.shared.accountstate import default_account_expire
4242
from mig.shared.base import client_id_dir, canonical_user, mask_creds, \
4343
generate_https_urls, fill_distinguished_name
@@ -190,6 +190,21 @@ def main(client_id, user_arguments_dict):
190190
'class': 'genericbutton', 'text': "Try again"})
191191
return (output_objects, returnvalues.CLIENT_ERROR)
192192

193+
peers_list = []
194+
for (peer_name, peer_email) in zip(peers_full_name_list, peers_email_list):
195+
peers_list.append({'full_name': peer_name, 'email': peer_email})
196+
valid_peers = prefilter_potential_peers(peers_list, configuration)
197+
if not valid_peers:
198+
output_objects.append({'object_type': 'error_text', 'text':
199+
'''Invalid peers specification:
200+
Please read and follow the sign up help and instructions on the request page!
201+
You may also read more about the Peers system in the site documentation.
202+
'''})
203+
output_objects.append(
204+
{'object_type': 'link', 'destination': 'javascript:history.back();',
205+
'class': 'genericbutton', 'text': "Try again"})
206+
return (output_objects, returnvalues.CLIENT_ERROR)
207+
193208
# TODO: move this check to conf?
194209

195210
if not forced_org_email_match(org, email, configuration):

mig/shared/functionality/reqoidaction.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# reqoidaction - handle OpenID account requests and send email to admins
7-
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2025 The MiG Project by the Science HPC Center at UCPH
88
#
99
# This file is part of MiG.
1010
#
@@ -37,7 +37,7 @@
3737

3838
from mig.shared import returnvalues
3939
from mig.shared.accountreq import existing_country_code, forced_org_email_match, \
40-
user_manage_commands, save_account_request
40+
prefilter_potential_peers, user_manage_commands, save_account_request
4141
from mig.shared.accountstate import default_account_expire
4242
from mig.shared.base import client_id_dir, canonical_user, mask_creds, \
4343
force_utf8, force_unicode, force_native_str, force_native_str_rec, \
@@ -198,6 +198,21 @@ def main(client_id, user_arguments_dict):
198198
'class': 'genericbutton', 'text': "Try again"})
199199
return (output_objects, returnvalues.CLIENT_ERROR)
200200

201+
peers_list = []
202+
for (peer_name, peer_email) in zip(peers_full_name_list, peers_email_list):
203+
peers_list.append({'full_name': peer_name, 'email': peer_email})
204+
valid_peers = prefilter_potential_peers(peers_list, configuration)
205+
if not valid_peers:
206+
output_objects.append({'object_type': 'error_text', 'text':
207+
'''Invalid peers specification:
208+
Please read and follow the sign up help and instructions on the request page!
209+
You may also read more about the Peers system in the site documentation.
210+
'''})
211+
output_objects.append(
212+
{'object_type': 'link', 'destination': 'javascript:history.back();',
213+
'class': 'genericbutton', 'text': "Try again"})
214+
return (output_objects, returnvalues.CLIENT_ERROR)
215+
201216
# TODO: move this check to conf?
202217

203218
if not forced_org_email_match(org, email, configuration):

mig/shared/install.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ def generate_confs(
447447
daemon_pubkey_from_dns=False,
448448
daemon_show_address='',
449449
alias_field='',
450+
peers_prefilter='email:.*',
450451
peers_permit='distinguished_name:.*',
451452
vgrid_creators='distinguished_name:.*',
452453
vgrid_managers='distinguished_name:.*',
@@ -771,6 +772,7 @@ def _generate_confs_prepare(
771772
daemon_pubkey_from_dns,
772773
daemon_show_address,
773774
alias_field,
775+
peers_prefilter,
774776
peers_permit,
775777
vgrid_creators,
776778
vgrid_managers,
@@ -1056,6 +1058,7 @@ def _generate_confs_prepare(
10561058
user_dict['__SEAFILE_RO_ACCESS__'] = "%s" % seafile_ro_access
10571059
user_dict['__PUBLIC_USE_HTTPS__'] = "%s" % public_use_https
10581060
user_dict['__ALIAS_FIELD__'] = alias_field
1061+
user_dict['__PEERS_PREFILTER__'] = peers_prefilter
10591062
user_dict['__PEERS_PERMIT__'] = peers_permit
10601063
user_dict['__VGRID_CREATORS__'] = vgrid_creators
10611064
user_dict['__VGRID_MANAGERS__'] = vgrid_managers

tests/fixture/confs-stdlocal/MiGserver.conf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,11 @@ password_policy = MEDIUM
761761
password_legacy_policy =
762762
# Optional additional guard against simple passwords with the cracklib library
763763
password_cracklib = False
764+
# Optional prefilter on users who may potenially invite peers as site users.
765+
# Used as a coarse filter to reject clearly invalid user requests early.
766+
# Space separated list of user field and regexp-filter pattern pairs separated
767+
# by colons.
768+
peers_prefilter = email:.*
764769
# Optional limit on users who may invite peers as site users. Space separated
765770
# list of user field and regexp-filter pattern pairs separated by colons.
766771
peers_permit = distinguished_name:.*

tests/fixture/mig_shared_configuration--new.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@
181181
".*"
182182
]
183183
],
184+
"site_peers_prefilter": [
185+
[
186+
"email",
187+
".*"
188+
]
189+
],
184190
"site_prefer_python3": false,
185191
"site_signup_hint": "",
186192
"site_signup_methods": [

0 commit comments

Comments
 (0)