Skip to content

Commit 9462073

Browse files
committed
Merge remote-tracking branch 'origin/master' into edge
2 parents b04835d + ce25bb0 commit 9462073

12 files changed

+122
-74
lines changed

mig/install/MiGserver-template.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ mig_server_id = %(server_fqdn)s.0
187187
empty_job_name = no_grid_jobs_in_grid_scheduler
188188
notify_protocols = email
189189
smtp_server = __SMTP_SERVER__
190-
storage_protocols = __STORAGE_PROTOCOLS__
191190
gdp_email_notify = __GDP_EMAIL_NOTIFY__
192191

192+
# Optional space-separated prioritized list of efficient storage access
193+
# protocols to advertize to clients. Leave to AUTO to use the ones actually
194+
# enabled with the corresponding enable_SERVICE options. Default is AUTO and
195+
# other allowed values are one or more of sftp, ftps and davs.
196+
# NOTE: the sftpsubsys service is advertized as just sftp to fit the protocol.
197+
storage_protocols = __STORAGE_PROTOCOLS__
198+
193199
# Optional extra service interfaces with common structure
194200
# * user_X_address is the host address to listen on
195201
# * user_X_port is the host port to listen on

mig/shared/configuration.py

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@
5050
from mig.shared.defaults import CSRF_MINIMAL, CSRF_WARN, CSRF_MEDIUM, \
5151
CSRF_FULL, POLICY_NONE, POLICY_WEAK, POLICY_MEDIUM, POLICY_HIGH, \
5252
POLICY_MODERN, POLICY_CUSTOM, freeze_flavors, cert_field_order, \
53-
duplicati_protocol_choices, default_css_filename, keyword_any, \
54-
cert_valid_days, oid_valid_days, generic_valid_days, keyword_all, \
55-
keyword_file, keyword_env, DEFAULT_USER_ID_FORMAT, \
56-
valid_user_id_formats, valid_filter_methods, default_twofactor_auth_apps
53+
default_css_filename, keyword_any, keyword_auto, keyword_all, \
54+
keyword_file, keyword_env, cert_valid_days, oid_valid_days, \
55+
generic_valid_days, DEFAULT_USER_ID_FORMAT, valid_user_id_formats, \
56+
valid_filter_methods, default_twofactor_auth_apps
5757
from mig.shared.logger import Logger, SYSLOG_GDP
5858
from mig.shared.htmlgen import menu_items, vgrid_items
5959
from mig.shared.fileio import read_file, load_json, write_file
@@ -264,7 +264,6 @@ def fix_missing(config_file, verbose=True):
264264
'user_seafile_auth': ['password'],
265265
'user_seafile_local_instance': False,
266266
'user_seafile_ro_access': False,
267-
'user_duplicati_protocols': [],
268267
'user_cloud_console_access': [],
269268
'user_cloud_ssh_auth': ['publickey'],
270269
'user_cloud_alias': '',
@@ -528,7 +527,7 @@ def fix_missing(config_file, verbose=True):
528527
'user_seafile_alias': '',
529528
'user_seafile_local_instance': False,
530529
'user_seafile_ro_access': False,
531-
'user_duplicati_protocols': [],
530+
'user_duplicati_protocols': keyword_auto,
532531
'user_cloud_console_access': [],
533532
'user_cloud_ssh_auth': ['publickey'],
534533
'user_cloud_alias': '',
@@ -619,7 +618,7 @@ def fix_missing(config_file, verbose=True):
619618
'scriptlanguages': [],
620619
'jobtypes': [],
621620
'lrmstypes': [],
622-
'storage_protocols': [],
621+
'storage_protocols': keyword_auto,
623622
'server_cert': '',
624623
'server_key': '',
625624
'passphrase_file': '',
@@ -1284,6 +1283,17 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
12841283
'user_ftps_alias')
12851284
if config.has_option('GLOBAL', 'user_ftps_log'):
12861285
self.user_ftps_log = config.get('GLOBAL', 'user_ftps_log')
1286+
1287+
# NOTE: prioritized order based on performance and robustness.
1288+
# Needed by duplicati and storage protocols setup below.
1289+
prio_storage_protos = []
1290+
if self.site_enable_sftp_subsys or self.site_enable_sftp:
1291+
prio_storage_protos.append('sftp')
1292+
if self.site_enable_ftps:
1293+
prio_storage_protos.append('ftps')
1294+
if self.site_enable_davs:
1295+
prio_storage_protos.append('davs')
1296+
12871297
if config.has_option('SITE', 'enable_seafile'):
12881298
self.site_enable_seafile = config.getboolean(
12891299
'SITE', 'enable_seafile')
@@ -1321,10 +1331,21 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
13211331
else:
13221332
self.site_enable_duplicati = False
13231333
if config.has_option('GLOBAL', 'user_duplicati_protocols'):
1324-
allowed_protos = [j for (i, j) in duplicati_protocol_choices]
1325-
protos = config.get('GLOBAL', 'user_duplicati_protocols').split()
1334+
allowed_protos = prio_storage_protos
1335+
plain_val = config.get('GLOBAL', 'user_duplicati_protocols')
1336+
protos = [i for i in plain_val.split() if i]
1337+
# Append missing supported protocols for AUTO and filter invalid
1338+
if keyword_auto in protos:
1339+
protos = [i for i in protos if i != keyword_auto] +\
1340+
[i for i in allowed_protos if i not in protos]
13261341
valid_protos = [i for i in protos if i in allowed_protos]
1342+
if protos != valid_protos:
1343+
invalid_protos = [i for i in protos if i not in valid_protos]
1344+
self.logger.warning("invalid duplicati_protocol value(s): %s" %
1345+
', '.join(invalid_protos))
13271346
self.user_duplicati_protocols = valid_protos
1347+
else:
1348+
self.user_duplicati_protocols = prio_storage_protos
13281349
if config.has_option('SITE', 'enable_cloud'):
13291350
self.site_enable_cloud = config.getboolean(
13301351
'SITE', 'enable_cloud')
@@ -1589,8 +1610,22 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
15891610
else:
15901611
self.notify_protocols = []
15911612
if config.has_option('GLOBAL', 'storage_protocols'):
1592-
self.storage_protocols = config.get(
1593-
'GLOBAL', 'storage_protocols').split()
1613+
allowed_protos = prio_storage_protos
1614+
plain_val = config.get('GLOBAL', 'storage_protocols')
1615+
protos = [i for i in plain_val.split() if i]
1616+
# Append missing supported protocols for AUTO and filter invalid
1617+
if keyword_auto in protos:
1618+
protos = [i for i in protos if i != keyword_auto] +\
1619+
[i for i in allowed_protos if i not in protos]
1620+
valid_protos = [i for i in protos if i in allowed_protos]
1621+
if protos != valid_protos:
1622+
invalid_protos = [i for i in protos if i not in valid_protos]
1623+
self.logger.warning("invalid storage_protocols value(s): %s" %
1624+
', '.join(invalid_protos))
1625+
self.storage_protocols = valid_protos
1626+
else:
1627+
self.storage_protocols = prio_storage_protos
1628+
15941629
if config.has_option('SITE', 'enable_jupyter'):
15951630
self.site_enable_jupyter = config.getboolean(
15961631
'SITE', 'enable_jupyter')

mig/shared/defaults.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,6 @@
424424
'rsyncssh': 'RSYNC over SSH', 'rsyncd': 'RSYNC daemon',
425425
'oid': 'OpenID 2.0', 'openid': 'OpenID 2.0',
426426
'oidc': 'OpenID Connect', 'openidc': 'OpenID Connect'}
427-
# Prioritized protocol choices for duplicati - order matters!
428-
duplicati_protocol_choices = [(protocol_aliases[i], i) for i in
429-
['sftp', 'ftps', 'davs']]
430427
# Prioritized schedule backup frequency choices and json values
431428
duplicati_schedule_choices = [('Daily', '1D'), ('Weekly', '1W'),
432429
('Monthly', '1M'), ('Never', '')]

mig/shared/duplicatikeywords.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# duplicatikeywords - keywords used in the duplicati settings file
7-
# Copyright (C) 2003-2021 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
88
#
99
# This file is part of MiG.
1010
#
@@ -29,8 +29,7 @@
2929

3030
from __future__ import absolute_import
3131

32-
from mig.shared.defaults import duplicati_protocol_choices, \
33-
duplicati_schedule_choices
32+
from mig.shared.defaults import protocol_aliases, duplicati_schedule_choices
3433
from mig.shared.url import urlencode
3534

3635

@@ -54,17 +53,31 @@
5453
}'''
5554
}
5655

57-
protocol_map = dict(duplicati_protocol_choices)
5856
schedule_map = dict(duplicati_schedule_choices)
5957

60-
# TODO: this function should probably move to shared.settings or something
58+
59+
def get_duplicati_protocol_map(configuration, reverse=False):
60+
"""Simple helper to extract supported storage protocols from conf and map
61+
them to user-friendly aliases. If the optional reverse argument is set the
62+
map is reversed to map from aliases to protocols instead of vice-versa.
63+
"""
64+
if reverse:
65+
return {protocol_aliases[i]: i for i in configuration.storage_protocols}
66+
else:
67+
return {i: protocol_aliases[i] for i in configuration.storage_protocols}
6168

6269

70+
# TODO: this function should probably move to shared.settings or something
71+
6372
def extract_duplicati_helper(configuration, client_id, duplicati_dict):
6473
"""Fill helper dictionary with values used in duplicati_conf_templates"""
6574
# lookup fqdn, username, etc for specified protocol
66-
default_protocol = duplicati_protocol_choices[0][0]
67-
protocol_alias = duplicati_dict.get('PROTOCOL', default_protocol)
75+
rev_proto_map = get_duplicati_protocol_map(configuration, reverse=True)
76+
if configuration.storage_protocols:
77+
default_alias = protocol_aliases[configuration.storage_protocols[0]]
78+
else:
79+
default_alias = ''
80+
protocol_alias = duplicati_dict.get('PROTOCOL', default_alias)
6881
username = duplicati_dict.get('USERNAME')
6982
password = duplicati_dict.get('PASSWORD', '')
7083
credentials = [('auth-username', username)]
@@ -82,7 +95,7 @@ def extract_duplicati_helper(configuration, client_id, duplicati_dict):
8295
# cert renew will change the hash and thus break existing confs.
8396
schedule_alias = duplicati_dict.get('SCHEDULE', '')
8497
schedule_freq = schedule_map.get(schedule_alias, '')
85-
protocol = protocol_map[protocol_alias]
98+
protocol = rev_proto_map[protocol_alias]
8699
if protocol in ('webdavs', 'davs'):
87100
# Duplicati client requires webdavs://BLA
88101
protocol = 'webdavs'

mig/shared/functionality/settings.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# settings - back end for the settings page
7-
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
88
#
99
# This file is part of MiG.
1010
#
@@ -41,8 +41,9 @@
4141
from mig.shared.defaults import default_mrsl_filename, \
4242
default_css_filename, profile_img_max_kb, profile_img_extensions, \
4343
seafile_ro_dirname, duplicati_conf_dir, csrf_field, \
44-
duplicati_protocol_choices, duplicati_schedule_choices
45-
from mig.shared.duplicatikeywords import get_duplicati_specs
44+
duplicati_schedule_choices
45+
from mig.shared.duplicatikeywords import get_duplicati_specs, \
46+
get_duplicati_protocol_map
4647
from mig.shared.editing import cm_css, cm_javascript, cm_options, wrap_edit_area
4748
from mig.shared.functional import validate_input_and_cert
4849
from mig.shared.handlers import get_csrf_limit, make_csrf_token
@@ -1675,9 +1676,8 @@ def main(client_id, user_arguments_dict):
16751676
if configuration.user_duplicati_protocols:
16761677
protocol_order = configuration.user_duplicati_protocols
16771678
else:
1678-
protocol_order = [j for (i, j) in duplicati_protocol_choices]
1679-
reverse_proto_map = dict([(j, i) for (i, j) in
1680-
duplicati_protocol_choices])
1679+
protocol_order = configuration.storage_protocols
1680+
proto_map = get_duplicati_protocol_map(configuration)
16811681

16821682
enabled_map = {
16831683
'davs': configuration.site_enable_davs,
@@ -1691,7 +1691,7 @@ def main(client_id, user_arguments_dict):
16911691
'ftps': extract_field(client_id, configuration.user_ftps_alias)
16921692
}
16931693
for proto in protocol_order:
1694-
pretty_proto = reverse_proto_map[proto]
1694+
pretty_proto = proto_map[proto]
16951695
if not enabled_map[proto]:
16961696
continue
16971697
if not pretty_proto in configuration.protocol:

mig/shared/functionality/setup.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# setup - back end for the client access setup page
7-
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
88
#
99
# This file is part of MiG.
1010
#
@@ -38,9 +38,10 @@
3838
from mig.shared.base import client_alias, client_id_dir, extract_field, get_xgi_bin, \
3939
get_short_id, requested_url_base, requested_backend
4040
from mig.shared.defaults import seafile_ro_dirname, duplicati_conf_dir, csrf_field, \
41-
duplicati_protocol_choices, duplicati_schedule_choices, keyword_all, \
42-
AUTH_MIG_OID, AUTH_EXT_OID, AUTH_MIG_OIDC, AUTH_EXT_OIDC
43-
from mig.shared.duplicatikeywords import get_duplicati_specs
41+
duplicati_schedule_choices, keyword_all, AUTH_MIG_OID, AUTH_EXT_OID, \
42+
AUTH_MIG_OIDC, AUTH_EXT_OIDC
43+
from mig.shared.duplicatikeywords import get_duplicati_specs, \
44+
get_duplicati_protocol_map
4445
from mig.shared.editing import cm_css, cm_javascript, cm_options, wrap_edit_area
4546
from mig.shared.functional import validate_input_and_cert
4647
from mig.shared.handlers import get_csrf_limit, make_csrf_token
@@ -1377,9 +1378,8 @@ def main(client_id, user_arguments_dict, target_op='settingsaction'):
13771378
if configuration.user_duplicati_protocols:
13781379
protocol_order = configuration.user_duplicati_protocols
13791380
else:
1380-
protocol_order = [j for (i, j) in duplicati_protocol_choices]
1381-
reverse_proto_map = dict([(j, i) for (i, j) in
1382-
duplicati_protocol_choices])
1381+
protocol_order = configuration.storage_protocols
1382+
proto_map = get_duplicati_protocol_map(configuration)
13831383

13841384
enabled_map = {
13851385
'davs': configuration.site_enable_davs,
@@ -1393,7 +1393,7 @@ def main(client_id, user_arguments_dict, target_op='settingsaction'):
13931393
'ftps': extract_field(client_id, configuration.user_ftps_alias)
13941394
}
13951395
for proto in protocol_order:
1396-
pretty_proto = reverse_proto_map[proto]
1396+
pretty_proto = proto_map[proto]
13971397
if not enabled_map[proto]:
13981398
continue
13991399
if not pretty_proto in configuration.protocol:

mig/shared/install.py

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,8 @@ def _generate_confs_prepare(
10541054
user_dict['__PERMANENT_FREEZE__'] = permanent_freeze
10551055
user_dict['__FREEZE_TO_TAPE__'] = freeze_to_tape
10561056
user_dict['__STATUS_SYSTEM_MATCH__'] = status_system_match
1057+
user_dict['__STORAGE_PROTOCOLS__'] = storage_protocols
1058+
user_dict['__DUPLICATI_PROTOCOLS__'] = duplicati_protocols
10571059
user_dict['__IMNOTIFY_ADDRESS__'] = imnotify_address
10581060
user_dict['__IMNOTIFY_CHANNEL__'] = imnotify_channel
10591061
user_dict['__IMNOTIFY_USERNAME__'] = imnotify_username
@@ -1330,29 +1332,6 @@ def _generate_confs_prepare(
13301332
if davs_show_port:
13311333
fail2ban_daemon_ports.append(davs_show_port)
13321334

1333-
# NOTE: prioritized order based on performance and robustness
1334-
best_storage_svc = []
1335-
if enable_sftp_subsys or enable_sftp:
1336-
best_storage_svc.append('sftp')
1337-
if enable_ftps:
1338-
best_storage_svc.append('ftps')
1339-
if enable_davs:
1340-
best_storage_svc.append('davs')
1341-
1342-
if storage_protocols != keyword_auto:
1343-
storage_protocols = [i for i in storage_protocols.split() if i in
1344-
best_storage_svc]
1345-
else:
1346-
storage_protocols = best_storage_svc
1347-
user_dict['__STORAGE_PROTOCOLS__'] = ' '.join(storage_protocols)
1348-
1349-
if duplicati_protocols != keyword_auto:
1350-
prio_duplicati_protocols = [i for i in duplicati_protocols.split() if i
1351-
in best_storage_svc]
1352-
else:
1353-
prio_duplicati_protocols = best_storage_svc
1354-
user_dict['__DUPLICATI_PROTOCOLS__'] = ' '.join(prio_duplicati_protocols)
1355-
13561335
user_dict['__SEAFILE_TIMEZONE__'] = options['timezone']
13571336

13581337
if seafile_secret == keyword_auto:

tests/data/MiGserver--storage_protocols.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ mig_server_id = %(server_fqdn)s.0
187187
empty_job_name = no_grid_jobs_in_grid_scheduler
188188
notify_protocols = email
189189
smtp_server = localhost
190-
storage_protocols = xxx yyy zzz
191190
gdp_email_notify = False
192191

192+
# Optional space-separated prioritized list of efficient storage access
193+
# protocols to advertize to clients. Leave to AUTO to use the ones actually
194+
# enabled with the corresponding enable_SERVICE options. Default is AUTO and
195+
# other allowed values are one or more of sftp, ftps and davs.
196+
# NOTE: the sftpsubsys service is advertized as just sftp to fit the protocol.
197+
storage_protocols = sftp
198+
193199
# Optional extra service interfaces with common structure
194200
# * user_X_address is the host address to listen on
195201
# * user_X_port is the host port to listen on

tests/fixture/confs-stdlocal/MiGserver.conf

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ mig_server_id = %(server_fqdn)s.0
187187
empty_job_name = no_grid_jobs_in_grid_scheduler
188188
notify_protocols = email
189189
smtp_server = localhost
190-
storage_protocols =
191190
gdp_email_notify = False
192191

192+
# Optional space-separated prioritized list of efficient storage access
193+
# protocols to advertize to clients. Leave to AUTO to use the ones actually
194+
# enabled with the corresponding enable_SERVICE options. Default is AUTO and
195+
# other allowed values are one or more of sftp, ftps and davs.
196+
# NOTE: the sftpsubsys service is advertized as just sftp to fit the protocol.
197+
storage_protocols = AUTO
198+
193199
# Optional extra service interfaces with common structure
194200
# * user_X_address is the host address to listen on
195201
# * user_X_port is the host port to listen on
@@ -290,7 +296,7 @@ user_seafile_local_instance = False
290296
# if local read-only mount is available for user home integration (default: False)
291297
user_seafile_ro_access = True
292298
# Priority list of protocols allowed in Duplicati backups (sftp, ftps, davs)
293-
user_duplicati_protocols =
299+
user_duplicati_protocols = AUTO
294300
# Cloud settings for remote access - more in individual service sections
295301
# space separated list of cloud user authentication methods
296302
# (default: publickey)

tests/fixture/mig_shared_configuration--new.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@
207207
"smtp_server": "",
208208
"sss_home": "",
209209
"state_path": "/some/place/state",
210-
"storage_protocols": [],
210+
"storage_protocols": "AUTO",
211211
"submitui": [
212212
"fields",
213213
"textarea",
@@ -242,7 +242,7 @@
242242
"user_davs_show_address": "",
243243
"user_davs_show_port": 4443,
244244
"user_db_home": "",
245-
"user_duplicati_protocols": [],
245+
"user_duplicati_protocols": "AUTO",
246246
"user_events_log": "events.log",
247247
"user_ext_cert_title": "",
248248
"user_ext_oid_provider": "",

0 commit comments

Comments
 (0)