|
40 | 40 | import base64
|
41 | 41 | import crypt
|
42 | 42 | import datetime
|
| 43 | +import grp |
43 | 44 | import os
|
44 | 45 | import pwd
|
45 | 46 | import random
|
|
49 | 50 | import sys
|
50 | 51 |
|
51 | 52 | from mig.shared.defaults import default_http_port, default_https_port, \
|
| 53 | + mig_user, mig_group, default_source, default_destination, \ |
52 | 54 | auth_openid_mig_db, auth_openid_ext_db, STRONG_TLS_CIPHERS, \
|
53 | 55 | STRONG_TLS_CURVES, STRONG_SSH_KEXALGOS, STRONG_SSH_LEGACY_KEXALGOS, \
|
54 | 56 | STRONG_SSH_CIPHERS, STRONG_SSH_LEGACY_CIPHERS, STRONG_SSH_MACS, \
|
55 | 57 | STRONG_SSH_LEGACY_MACS, CRACK_USERNAME_REGEX, CRACK_WEB_REGEX, \
|
56 | 58 | keyword_any, keyword_auto
|
| 59 | +from mig.shared.compat import ensure_native_string |
57 | 60 | from mig.shared.fileio import read_file, read_file_lines, write_file, \
|
58 | 61 | write_file_lines
|
59 | 62 | from mig.shared.htmlgen import menu_items
|
@@ -187,8 +190,8 @@ def template_remove(template_file, remove_pattern):
|
187 | 190 | def generate_confs(
|
188 | 191 | # NOTE: make sure command line args with white-space are properly wrapped
|
189 | 192 | generateconfs_command=subprocess.list2cmdline(sys.argv),
|
190 |
| - source=os.path.dirname(sys.argv[0]), |
191 |
| - destination=os.path.dirname(sys.argv[0]), |
| 193 | + source=default_source, |
| 194 | + destination=default_destination, |
192 | 195 | destination_suffix="",
|
193 | 196 | base_fqdn='',
|
194 | 197 | public_fqdn='',
|
@@ -217,8 +220,9 @@ def generate_confs(
|
217 | 220 | jupyter_services_desc='{}',
|
218 | 221 | cloud_services='',
|
219 | 222 | cloud_services_desc='{}',
|
220 |
| - user='mig', |
221 |
| - group='mig', |
| 223 | + user=mig_user, |
| 224 | + group=mig_group, |
| 225 | + timezone=keyword_auto, |
222 | 226 | apache_version='2.4',
|
223 | 227 | apache_etc='/etc/apache2',
|
224 | 228 | apache_run='/var/run',
|
@@ -358,6 +362,8 @@ def generate_confs(
|
358 | 362 | openid_port=8443,
|
359 | 363 | openid_show_port='',
|
360 | 364 | openid_session_lifetime=43200,
|
| 365 | + seafile_secret=keyword_auto, |
| 366 | + seafile_ccnetid=keyword_auto, |
361 | 367 | seafile_seahub_port=8000,
|
362 | 368 | seafile_seafhttp_port=8082,
|
363 | 369 | seafile_client_port=13419,
|
@@ -403,12 +409,31 @@ def generate_confs(
|
403 | 409 | quota_backend='lustre',
|
404 | 410 | quota_user_limit=(1024**4),
|
405 | 411 | quota_vgrid_limit=(1024**4),
|
| 412 | + _getpwnam=pwd.getpwnam, |
406 | 413 | ):
|
407 | 414 | """Generate Apache and MiG server confs with specified variables"""
|
408 | 415 |
|
409 | 416 | # Read out dictionary of args with defaults and overrides
|
410 | 417 |
|
411 |
| - expanded = locals() |
| 418 | + expanded = dict(locals()) |
| 419 | + |
| 420 | + # expand any directory path specific as "auto" relative to CWD |
| 421 | + if source is keyword_auto: |
| 422 | + expanded['source'] = os.path.dirname(sys.argv[0]) |
| 423 | + source = expanded['source'] |
| 424 | + if destination is keyword_auto: |
| 425 | + expanded['destination'] = os.path.dirname(sys.argv[0]) |
| 426 | + destination = expanded['destination'] |
| 427 | + |
| 428 | + # expand any user information marked as "auto" based on the environment |
| 429 | + if user is keyword_auto: |
| 430 | + user = pwd.getpwuid(os.getuid())[0] |
| 431 | + if group is keyword_auto: |
| 432 | + group = grp.getgrgid(os.getgid())[0] |
| 433 | + |
| 434 | + # finalize a destination path up-front |
| 435 | + expanded['destination_path'] = "%s%s" % (destination, destination_suffix) |
| 436 | + destination_path = expanded['destination_path'] |
412 | 437 |
|
413 | 438 | # Backwards compatibility with old name
|
414 | 439 | if public_port and not public_http_port:
|
@@ -656,7 +681,7 @@ def generate_confs(
|
656 | 681 | user_dict['__QUOTA_VGRID_LIMIT__'] = "%s" % quota_vgrid_limit
|
657 | 682 |
|
658 | 683 | # Needed for PAM/NSS
|
659 |
| - pw_info = pwd.getpwnam(user) |
| 684 | + pw_info = _getpwnam(user) |
660 | 685 | user_dict['__MIG_UID__'] = "%s" % (pw_info.pw_uid)
|
661 | 686 | user_dict['__MIG_GID__'] = "%s" % (pw_info.pw_gid)
|
662 | 687 |
|
@@ -916,22 +941,36 @@ def generate_confs(
|
916 | 941 | prio_duplicati_protocols.append('davs')
|
917 | 942 | user_dict['__DUPLICATI_PROTOCOLS__'] = ' '.join(prio_duplicati_protocols)
|
918 | 943 |
|
919 |
| - sys_timezone = 'UTC' |
920 |
| - timezone_cmd = ["/usr/bin/timedatectl", "status"] |
921 |
| - try: |
922 |
| - timezone_proc = subprocess_popen(timezone_cmd, stdout=subprocess_pipe) |
923 |
| - for line in timezone_proc.stdout.readlines(): |
924 |
| - line = line.strip() |
925 |
| - if not line.startswith("Time zone: "): |
926 |
| - continue |
927 |
| - sys_timezone = line.replace("Time zone: ", "").split(" ", 1)[0] |
928 |
| - except Exception as exc: |
929 |
| - print("WARNING: failed to extract system time zone: %s" % exc) |
930 |
| - user_dict['__SEAFILE_TIMEZONE__'] = sys_timezone |
931 |
| - user_dict['__SEAFILE_SECRET_KEY__'] = base64.b64encode( |
932 |
| - os.urandom(32)).lower() |
933 |
| - user_dict['__SEAFILE_CCNET_ID__'] = base64.b16encode( |
934 |
| - os.urandom(20)).lower() |
| 944 | + if timezone is keyword_auto: |
| 945 | + # attempt to detect the timezone |
| 946 | + sys_timezone = None |
| 947 | + try: |
| 948 | + timezone_cmd = ["/usr/bin/timedatectl", "status"] |
| 949 | + timezone_proc = subprocess_popen(timezone_cmd, stdout=subprocess_pipe) |
| 950 | + for line in timezone_proc.stdout.readlines(): |
| 951 | + line = ensure_native_string(line.strip()) |
| 952 | + if not line.startswith("Time zone: "): |
| 953 | + continue |
| 954 | + sys_timezone = line.replace("Time zone: ", "").split(" ", 1)[0] |
| 955 | + except OSError as exc: |
| 956 | + # warn about any issues executing the command but continue |
| 957 | + pass |
| 958 | + if sys_timezone is None: |
| 959 | + print("WARNING: failed to extract system time zone; defaulting to UTC") |
| 960 | + sys_timezone = 'UTC' |
| 961 | + |
| 962 | + timezone = sys_timezone |
| 963 | + |
| 964 | + user_dict['__SEAFILE_TIMEZONE__'] = timezone |
| 965 | + |
| 966 | + if seafile_secret is keyword_auto: |
| 967 | + seafile_secret = ensure_native_string(base64.b64encode(os.urandom(32))).lower() |
| 968 | + user_dict['__SEAFILE_SECRET_KEY__'] = seafile_secret |
| 969 | + |
| 970 | + if seafile_ccnetid is keyword_auto: |
| 971 | + seafile_ccnetid = ensure_native_string(base64.b64encode(os.urandom(20))).lower() |
| 972 | + user_dict['__SEAFILE_CCNET_ID__'] = seafile_ccnetid |
| 973 | + |
935 | 974 | user_dict['__SEAFILE_SHORT_NAME__'] = short_title.replace(' ', '-')
|
936 | 975 | # IMPORTANT: we discriminate on local and remote seafile service
|
937 | 976 | # for local ones we partly integrate directly with apache etc.
|
@@ -1584,14 +1623,16 @@ def generate_confs(
|
1584 | 1623 | user_dict['__ALL_OIDC_PROVIDER_META_URLS__'] = ' '.join(
|
1585 | 1624 | all_oidc_provider_meta_urls)
|
1586 | 1625 |
|
1587 |
| - destination_path = "%s%s" % (destination, destination_suffix) |
1588 | 1626 | if not os.path.islink(destination) and os.path.isdir(destination):
|
1589 | 1627 | print("ERROR: Legacy %s dir in the way - please remove first" %
|
1590 | 1628 | destination)
|
1591 | 1629 | sys.exit(1)
|
1592 | 1630 | try:
|
1593 | 1631 | os.makedirs(destination_path)
|
1594 |
| - if os.path.exists(destination): |
| 1632 | + except OSError: |
| 1633 | + pass |
| 1634 | + try: |
| 1635 | + if os.path.lexists(destination): |
1595 | 1636 | os.remove(destination)
|
1596 | 1637 | os.symlink(destination_path, destination)
|
1597 | 1638 | except OSError:
|
@@ -1691,16 +1732,17 @@ def generate_confs(
|
1691 | 1732 | default_https_port])
|
1692 | 1733 | user_dict['__SID_URL__'] += ':%(__SID_PORT__)s' % user_dict
|
1693 | 1734 |
|
1694 |
| - if digest_salt == keyword_auto: |
| 1735 | + if digest_salt is keyword_auto: |
1695 | 1736 | # Generate random hex salt for scrambling saved digest credentials
|
1696 |
| - digest_salt = base64.b16encode(os.urandom(16)) |
1697 |
| - if crypto_salt == keyword_auto: |
1698 |
| - # Generate random hex salt for various crypto helpers |
1699 |
| - crypto_salt = base64.b16encode(os.urandom(16)) |
1700 |
| - |
| 1737 | + digest_salt = ensure_native_string(base64.b16encode(os.urandom(16))) |
1701 | 1738 | user_dict['__DIGEST_SALT__'] = digest_salt
|
| 1739 | + |
| 1740 | + if crypto_salt is keyword_auto: |
| 1741 | + # Generate random hex salt for various crypto helpers |
| 1742 | + crypto_salt = ensure_native_string(base64.b16encode(os.urandom(16))) |
1702 | 1743 | user_dict['__CRYPTO_SALT__'] = crypto_salt
|
1703 | 1744 |
|
| 1745 | + |
1704 | 1746 | # Greedy match trailing space for all the values to uncomment stuff
|
1705 | 1747 | strip_trailing_space = ['__IF_SEPARATE_PORTS__', '__APACHE_PRE2.4__',
|
1706 | 1748 | '__APACHE_RECENT__']
|
@@ -1989,7 +2031,7 @@ def generate_confs(
|
1989 | 2031 | sudo cp %(destination)s/migacctexpire /etc/cron.monthly/
|
1990 | 2032 |
|
1991 | 2033 | ''' % expanded
|
1992 |
| - instructions_path = "%s/instructions.txt" % destination |
| 2034 | + instructions_path = "%s/instructions.txt" % destination_path |
1993 | 2035 | if not write_file(instructions, instructions_path, None):
|
1994 | 2036 | print("could not write instructions ot %s" % instructions_path)
|
1995 | 2037 | return expanded
|
|
0 commit comments