diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9642e92f6..953e2940f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -13,10 +13,3 @@ ## How to test ... - -## Validation - -- [ ] Principle agreement 0/2 : -- [ ] Quick review 0/1 : -- [ ] Simple test 0/1 : -- [ ] Deep review 0/1 : diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ac3584630..eb34de38e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,124 +1,22 @@ stages: - - postinstall + - build + - install - tests - lint + - doc -######################################## -# POSTINSTALL -######################################## +default: + tags: + - yunohost-ci + # All jobs are interruptible by default + interruptible: true -postinstall: - image: before-postinstall - stage: postinstall - script: - - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns +variables: + YNH_BUILD_DIR: "ynh-build" -######################################## -# TESTS -######################################## - -.test-stage: - image: after-postinstall - stage: tests - before_script: - - apt-get install python-pip -y - - mkdir -p .pip - - pip install -U pip - - hash -d pip - - pip --cache-dir=.pip install pytest pytest-sugar pytest-mock requests-mock mock - - export PYTEST_ADDOPTS="--color=yes" - cache: - paths: - - .pip - - src/yunohost/tests/apps - key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" - -root-tests: - extends: .test-stage - script: - - py.test tests - -test-apps: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_apps.py - -test-appscatalog: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_appscatalog.py - -test-appurl: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_appurl.py - -test-backuprestore: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_backuprestore.py - -test-changeurl: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_changeurl.py - -test-permission: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_permission.py - -test-settings: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_settings.py - -test-user-group: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_user-group.py - -test-regenconf: - extends: .test-stage - script: - - cd src/yunohost - - py.test tests/test_regenconf.py - -######################################## -# LINTER -######################################## - -.lint-stage: - image: before-postinstall - stage: lint - before_script: - - apt-get install python-pip -y - - mkdir -p .pip - - pip install -U pip - - hash -d pip - - pip --cache-dir=.pip install tox - cache: - paths: - - .pip - - .tox - key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" - -lint: - extends: .lint-stage - allow_failure: true - script: - - tox -e lint - -# Disabled, waiting for buster -#format-check: -# extends: .lint-stage -# script: -# - black --check --diff +include: + - local: .gitlab/ci/build.gitlab-ci.yml + - local: .gitlab/ci/install.gitlab-ci.yml + - local: .gitlab/ci/test.gitlab-ci.yml + - local: .gitlab/ci/lint.gitlab-ci.yml + - local: .gitlab/ci/doc.gitlab-ci.yml diff --git a/.gitlab/ci/build.gitlab-ci.yml b/.gitlab/ci/build.gitlab-ci.yml new file mode 100644 index 000000000..d2dbbaa80 --- /dev/null +++ b/.gitlab/ci/build.gitlab-ci.yml @@ -0,0 +1,54 @@ +.build-stage: + stage: build + image: "before-install" + variables: + YNH_SOURCE: "https://github.com/yunohost" + before_script: + - mkdir -p $YNH_BUILD_DIR + artifacts: + paths: + - $YNH_BUILD_DIR/*.deb + +.build_script: &build_script + - cd $YNH_BUILD_DIR/$PACKAGE + - VERSION=$(dpkg-parsechangelog -S Version 2>/dev/null) + - VERSION_NIGHTLY="${VERSION}+$(date +%Y%m%d%H%M)" + - dch --package "${PACKAGE}" --force-bad-version -v "${VERSION_NIGHTLY}" -D "unstable" --force-distribution "Daily build." + - debuild --no-lintian -us -uc + +######################################## +# BUILD DEB +######################################## + +build-yunohost: + extends: .build-stage + variables: + PACKAGE: "yunohost" + script: + - git ls-files | xargs tar -czf archive.tar.gz + - mkdir -p $YNH_BUILD_DIR/$PACKAGE + - cat archive.tar.gz | tar -xz -C $YNH_BUILD_DIR/$PACKAGE + - rm archive.tar.gz + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script + + +build-ssowat: + extends: .build-stage + variables: + PACKAGE: "ssowat" + script: + - DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "ssowat \([>,=,<]+ .*\)" | grep -Po "[0-9]+([.][0-9]+)?" | head -n 1) + - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1 + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script + +build-moulinette: + extends: .build-stage + variables: + PACKAGE: "moulinette" + script: + - DEBIAN_DEPENDS=$(cat debian/control | tr "," "\n" | grep -Po "moulinette \([>,=,<]+ .*\)" | grep -Po "[0-9]+([.][0-9]+)?" | head -n 1) + - git clone $YNH_SOURCE/$PACKAGE -b $CI_COMMIT_REF_NAME $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE -b $DEBIAN_DEPENDS $YNH_BUILD_DIR/$PACKAGE --depth 1 || git clone $YNH_SOURCE/$PACKAGE $YNH_BUILD_DIR/$PACKAGE --depth 1 + - DEBIAN_FRONTEND=noninteractive apt --assume-yes -o Dpkg::Options::="--force-confold" build-dep $(pwd)/$YNH_BUILD_DIR/$PACKAGE + - *build_script diff --git a/.gitlab/ci/doc.gitlab-ci.yml b/.gitlab/ci/doc.gitlab-ci.yml new file mode 100644 index 000000000..b246cc238 --- /dev/null +++ b/.gitlab/ci/doc.gitlab-ci.yml @@ -0,0 +1,14 @@ +######################################## +# DOC +######################################## + +generate-helpers-doc: + stage: doc + image: "before-install" + needs: [] + script: + - cd doc + - python generate_helper_doc.py + artifacts: + paths: + - doc/helpers.html diff --git a/.gitlab/ci/install.gitlab-ci.yml b/.gitlab/ci/install.gitlab-ci.yml new file mode 100644 index 000000000..1df4fc4b9 --- /dev/null +++ b/.gitlab/ci/install.gitlab-ci.yml @@ -0,0 +1,29 @@ +.install-stage: + stage: install + needs: + - job: build-yunohost + artifacts: true + - job: build-ssowat + artifacts: true + - job: build-moulinette + artifacts: true + +######################################## +# INSTALL DEB +######################################## + +upgrade: + extends: .install-stage + image: "after-install" + script: + - apt-get update -o Acquire::Retries=3 + - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb + + +install-postinstall: + extends: .install-stage + image: "before-install" + script: + - apt-get update -o Acquire::Retries=3 + - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb + - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns diff --git a/.gitlab/ci/lint.gitlab-ci.yml b/.gitlab/ci/lint.gitlab-ci.yml new file mode 100644 index 000000000..8db1ee756 --- /dev/null +++ b/.gitlab/ci/lint.gitlab-ci.yml @@ -0,0 +1,43 @@ +######################################## +# LINTER +######################################## +# later we must fix lint and format-check jobs and remove "allow_failure" + +lint27: + stage: lint + image: "before-install" + needs: [] + allow_failure: true + script: + - tox -e py27-lint + +lint37: + stage: lint + image: "before-install" + needs: [] + allow_failure: true + script: + - tox -e py37-lint + +invalidcode27: + stage: lint + image: "before-install" + needs: [] + script: + - tox -e py27-invalidcode + +invalidcode37: + stage: lint + image: "before-install" + allow_failure: true + needs: [] + script: + - tox -e py37-invalidcode + +format-check: + stage: lint + image: "before-install" + needs: [] + allow_failure: true + script: + - tox -e py37-black diff --git a/.gitlab/ci/test.gitlab-ci.yml b/.gitlab/ci/test.gitlab-ci.yml new file mode 100644 index 000000000..ef21731f3 --- /dev/null +++ b/.gitlab/ci/test.gitlab-ci.yml @@ -0,0 +1,120 @@ +.install_debs: &install_debs + - apt-get update -o Acquire::Retries=3 + - DEBIAN_FRONTEND=noninteractive SUDO_FORCE_REMOVE=yes apt --assume-yes -o Dpkg::Options::="--force-confold" --allow-downgrades install ./$YNH_BUILD_DIR/*.deb + +.test-stage: + stage: tests + image: "after-install" + variables: + PYTEST_ADDOPTS: "--color=yes" + before_script: + - *install_debs + cache: + paths: + - src/yunohost/tests/apps + key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG" + needs: + - job: build-yunohost + artifacts: true + - job: build-ssowat + artifacts: true + - job: build-moulinette + artifacts: true + - job: upgrade + + +######################################## +# TESTS +######################################## + +full-tests: + stage: tests + image: "before-install" + variables: + PYTEST_ADDOPTS: "--color=yes" + before_script: + - *install_debs + - yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns + script: + - python -m pytest --cov=yunohost tests/ src/yunohost/tests/ --junitxml=report.xml + needs: + - job: build-yunohost + artifacts: true + - job: build-ssowat + artifacts: true + - job: build-moulinette + artifacts: true + artifacts: + reports: + junit: report.xml + +root-tests: + extends: .test-stage + script: + - python -m pytest tests + +test-apps: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_apps.py + +test-appscatalog: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_appscatalog.py + +test-appurl: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_appurl.py + +test-apps-arguments-parsing: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_apps_arguments_parsing.py + +test-backuprestore: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_backuprestore.py + +test-changeurl: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_changeurl.py + +test-permission: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_permission.py + +test-settings: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_settings.py + +test-user-group: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_user-group.py + +test-regenconf: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_regenconf.py + +test-service: + extends: .test-stage + script: + - cd src/yunohost + - python -m pytest tests/test_service.py diff --git a/.travis.yml b/.travis.yml index 8674d4d03..9a0f40674 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,18 @@ language: python matrix: allow_failures: - - env: TOXENV=lint + - env: TOXENV=py27-lint + - env: TOXENV=py37-lint + - env: TOXENV=py37-invalidcode include: - python: 2.7 - env: TOXENV=py27 + env: TOXENV=py27-lint - python: 2.7 - env: TOXENV=lint + env: TOXENV=py27-invalidcode + - python: 3.7 + env: TOXENV=py37-lint + - python: 3.7 + env: TOXENV=py37-invalidcode install: - pip install tox diff --git a/bin/yunohost b/bin/yunohost index b640c8c52..546d2d913 100755 --- a/bin/yunohost +++ b/bin/yunohost @@ -5,70 +5,28 @@ import os import sys import argparse -# Either we are in a development environment or not -IN_DEVEL = False +sys.path.insert(0, "/usr/lib/moulinette/") +import yunohost -# Level for which loggers will log -LOGGERS_LEVEL = 'DEBUG' -TTY_LOG_LEVEL = 'INFO' - -# Handlers that will be used by loggers -# - file: log to the file LOG_DIR/LOG_FILE -# - tty: log to current tty -LOGGERS_HANDLERS = ['file', 'tty'] - -# Directory and file to be used by logging -LOG_DIR = '/var/log/yunohost' -LOG_FILE = 'yunohost-cli.log' - -# Check and load - as needed - development environment -if not __file__.startswith('/usr/'): - IN_DEVEL = True -if IN_DEVEL: - basedir = os.path.abspath('%s/../' % os.path.dirname(__file__)) - if os.path.isdir(os.path.join(basedir, 'moulinette')): - sys.path.insert(0, basedir) - LOG_DIR = os.path.join(basedir, 'log') - - -import moulinette -from moulinette.actionsmap import ActionsMap -from moulinette.interfaces.cli import colorize, get_locale - - -# Initialization & helpers functions ----------------------------------- - -def _die(message, title='Error:'): - """Print error message and exit""" - print('%s %s' % (colorize(title, 'red'), message)) - sys.exit(1) def _parse_cli_args(): """Parse additional arguments for the cli""" parser = argparse.ArgumentParser(add_help=False) - parser.add_argument('--no-cache', - action='store_false', default=True, dest='use_cache', - help="Don't use actions map cache", - ) parser.add_argument('--output-as', choices=['json', 'plain', 'none'], default=None, - help="Output result in another format", + help="Output result in another format" ) parser.add_argument('--debug', action='store_true', default=False, - help="Log and print debug messages", + help="Log and print debug messages" ) parser.add_argument('--quiet', action='store_true', default=False, - help="Don't produce any output", + help="Don't produce any output" ) parser.add_argument('--timeout', type=int, default=None, - help="Number of seconds before this command will timeout because it can't acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock", - ) - parser.add_argument('--admin-password', - default=None, dest='password', metavar='PASSWORD', - help="The admin password to use to authenticate", + help="Number of seconds before this command will timeout because it can't acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock" ) # deprecated arguments parser.add_argument('--plain', @@ -88,96 +46,6 @@ def _parse_cli_args(): return (parser, opts, args) -def _init_moulinette(debug=False, quiet=False): - """Configure logging and initialize the moulinette""" - # Define loggers handlers - handlers = set(LOGGERS_HANDLERS) - if quiet and 'tty' in handlers: - handlers.remove('tty') - elif 'tty' not in handlers: - handlers.append('tty') - - root_handlers = set(handlers) - if not debug and 'tty' in root_handlers: - root_handlers.remove('tty') - - # Define loggers level - level = LOGGERS_LEVEL - tty_level = TTY_LOG_LEVEL - if debug: - tty_level = 'DEBUG' - - # Custom logging configuration - logging = { - 'version': 1, - 'disable_existing_loggers': True, - 'formatters': { - 'tty-debug': { - 'format': '%(relativeCreated)-4d %(fmessage)s' - }, - 'precise': { - 'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s' - }, - }, - 'filters': { - 'action': { - '()': 'moulinette.utils.log.ActionFilter', - }, - }, - 'handlers': { - 'tty': { - 'level': tty_level, - 'class': 'moulinette.interfaces.cli.TTYHandler', - 'formatter': 'tty-debug' if debug else '', - }, - 'file': { - 'class': 'logging.FileHandler', - 'formatter': 'precise', - 'filename': '%s/%s' % (LOG_DIR, LOG_FILE), - 'filters': ['action'], - }, - }, - 'loggers': { - 'yunohost': { - 'level': level, - 'handlers': handlers, - 'propagate': False, - }, - 'moulinette': { - 'level': level, - 'handlers': [], - 'propagate': True, - }, - 'moulinette.interface': { - 'level': level, - 'handlers': handlers, - 'propagate': False, - }, - }, - 'root': { - 'level': level, - 'handlers': root_handlers, - }, - } - - # Create log directory - if not os.path.isdir(LOG_DIR): - try: - os.makedirs(LOG_DIR, 0750) - except os.error as e: - _die(str(e)) - - # Initialize moulinette - moulinette.init(logging_config=logging, _from_source=IN_DEVEL) - -def _retrieve_namespaces(): - """Return the list of namespaces to load""" - ret = ['yunohost'] - for n in ActionsMap.get_namespaces(): - # Append YunoHost modules - if n.startswith('ynh_'): - ret.append(n) - return ret # Stupid PATH management because sometimes (e.g. some cron job) PATH is only /usr/bin:/bin ... default_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" @@ -188,33 +56,18 @@ if os.environ["PATH"] != default_path: if __name__ == '__main__': if os.geteuid() != 0: - # since moulinette isn't initialized, we can't use m18n here - sys.stderr.write("\033[1;31mError:\033[0m yunohost command must be " \ + sys.stderr.write("\033[1;31mError:\033[0m yunohost command must be " "run as root or with sudo.\n") sys.exit(1) parser, opts, args = _parse_cli_args() - _init_moulinette(opts.debug, opts.quiet) - - # Check that YunoHost is installed - if not os.path.isfile('/etc/yunohost/installed') and \ - (len(args) < 2 or (args[0] +' '+ args[1] != 'tools postinstall' and \ - args[0] +' '+ args[1] != 'backup restore' and \ - args[0] +' '+ args[1] != 'log display')): - - from moulinette import m18n - # Init i18n - m18n.load_namespace('yunohost') - m18n.set_locale(get_locale()) - - # Print error and exit - _die(m18n.n('yunohost_not_installed'), m18n.g('error')) # Execute the action - ret = moulinette.cli( - _retrieve_namespaces(), args, - use_cache=opts.use_cache, output_as=opts.output_as, - password=opts.password, parser_kwargs={'top_parser': parser}, + yunohost.cli( + debug=opts.debug, + quiet=opts.quiet, + output_as=opts.output_as, timeout=opts.timeout, + args=args, + parser=parser ) - sys.exit(ret) diff --git a/bin/yunohost-api b/bin/yunohost-api index e518c34b0..cc849590a 100755 --- a/bin/yunohost-api +++ b/bin/yunohost-api @@ -1,52 +1,16 @@ #! /usr/bin/python # -*- coding: utf-8 -*- -import os import sys import argparse -# Either we are in a development environment or not -IN_DEVEL = False +sys.path.insert(0, "/usr/lib/moulinette/") +import yunohost # Default server configuration DEFAULT_HOST = 'localhost' DEFAULT_PORT = 6787 -# Level for which loggers will log -LOGGERS_LEVEL = 'DEBUG' -API_LOGGER_LEVEL = 'INFO' - -# Handlers that will be used by loggers -# - file: log to the file LOG_DIR/LOG_FILE -# - api: serve logs through the api -# - console: log to stderr -LOGGERS_HANDLERS = ['file', 'api'] - -# Directory and file to be used by logging -LOG_DIR = '/var/log/yunohost' -LOG_FILE = 'yunohost-api.log' - -# Check and load - as needed - development environment -if not __file__.startswith('/usr/'): - IN_DEVEL = True -if IN_DEVEL: - basedir = os.path.abspath('%s/../' % os.path.dirname(__file__)) - if os.path.isdir(os.path.join(basedir, 'moulinette')): - sys.path.insert(0, basedir) - LOG_DIR = os.path.join(basedir, 'log') - - -import moulinette -from moulinette.actionsmap import ActionsMap -from moulinette.interfaces.cli import colorize - - -# Initialization & helpers functions ----------------------------------- - -def _die(message, title='Error:'): - """Print error message and exit""" - print('%s %s' % (colorize(title, 'red'), message)) - sys.exit(1) def _parse_api_args(): """Parse main arguments for the api""" @@ -62,149 +26,19 @@ def _parse_api_args(): action='store', default=DEFAULT_PORT, type=int, help="Port to listen on (default: %d)" % DEFAULT_PORT, ) - srv_group.add_argument('--no-websocket', - action='store_true', default=True, dest='use_websocket', - help="Serve without WebSocket support, used to handle " - "asynchronous responses such as the messages", - ) glob_group = parser.add_argument_group('global arguments') - glob_group.add_argument('--no-cache', - action='store_false', default=True, dest='use_cache', - help="Don't use actions map cache", - ) glob_group.add_argument('--debug', action='store_true', default=False, help="Set log level to DEBUG", ) - glob_group.add_argument('--verbose', - action='store_true', default=False, - help="Be verbose in the output", - ) glob_group.add_argument('--help', action='help', help="Show this help message and exit", ) return parser.parse_args() -def _init_moulinette(use_websocket=True, debug=False, verbose=False): - """Configure logging and initialize the moulinette""" - # Define loggers handlers - handlers = set(LOGGERS_HANDLERS) - if not use_websocket and 'api' in handlers: - handlers.remove('api') - if verbose and 'console' not in handlers: - handlers.add('console') - root_handlers = handlers - set(['api']) - - # Define loggers level - level = LOGGERS_LEVEL - api_level = API_LOGGER_LEVEL - if debug: - level = 'DEBUG' - api_level = 'DEBUG' - - # Custom logging configuration - logging = { - 'version': 1, - 'disable_existing_loggers': True, - 'formatters': { - 'console': { - 'format': '%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s' - }, - 'precise': { - 'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s' - }, - }, - 'filters': { - 'action': { - '()': 'moulinette.utils.log.ActionFilter', - }, - }, - 'handlers': { - 'api': { - 'level': api_level, - 'class': 'moulinette.interfaces.api.APIQueueHandler', - }, - 'file': { - 'class': 'logging.handlers.WatchedFileHandler', - 'formatter': 'precise', - 'filename': '%s/%s' % (LOG_DIR, LOG_FILE), - 'filters': ['action'], - }, - 'console': { - 'class': 'logging.StreamHandler', - 'formatter': 'console', - 'stream': 'ext://sys.stdout', - 'filters': ['action'], - }, - }, - 'loggers': { - 'yunohost': { - 'level': level, - 'handlers': handlers, - 'propagate': False, - }, - 'moulinette': { - 'level': level, - 'handlers': [], - 'propagate': True, - }, - 'gnupg': { - 'level': 'INFO', - 'handlers': [], - 'propagate': False, - }, - }, - 'root': { - 'level': level, - 'handlers': root_handlers, - }, - } - - # Create log directory - if not os.path.isdir(LOG_DIR): - try: - os.makedirs(LOG_DIR, 0750) - except os.error as e: - _die(str(e)) - - # Initialize moulinette - moulinette.init(logging_config=logging, _from_source=IN_DEVEL) - -def _retrieve_namespaces(): - """Return the list of namespaces to load""" - ret = ['yunohost'] - for n in ActionsMap.get_namespaces(): - # Append YunoHost modules - if n.startswith('ynh_'): - ret.append(n) - return ret - - -# Callbacks for additional routes -------------------------------------- - -def is_installed(): - """ - Check whether YunoHost is installed or not - - """ - installed = False - if os.path.isfile('/etc/yunohost/installed'): - installed = True - return { 'installed': installed } - - -# Main action ---------------------------------------------------------- if __name__ == '__main__': opts = _parse_api_args() - _init_moulinette(opts.use_websocket, opts.debug, opts.verbose) - # Run the server - ret = moulinette.api( - _retrieve_namespaces(), - host=opts.host, port=opts.port, routes={ - ('GET', '/installed'): is_installed, - }, use_cache=opts.use_cache, use_websocket=opts.use_websocket - ) - sys.exit(ret) + yunohost.api(debug=opts.debug, host=opts.host, port=opts.port) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index a748e4533..195220938 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -99,13 +99,7 @@ user: - "pattern_lastname" -m: full: --mail - help: Main unique email address - extra: - ask: ask_email - required: True - pattern: &pattern_email - - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ - - "pattern_email" + help: (Deprecated, see --domain) Main unique email address -p: full: --password help: User password @@ -116,6 +110,13 @@ user: - !!str ^.{3,}$ - "pattern_password" comment: good_practices_about_user_password + -d: + full: --domain + help: Domain for the email address and xmpp account + extra: + pattern: &pattern_domain + - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$ + - "pattern_domain" -q: full: --mailbox-quota help: Mailbox size quota @@ -157,7 +158,9 @@ user: -m: full: --mail extra: - pattern: *pattern_email + pattern: &pattern_email + - !!str ^[\w.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$ + - "pattern_email" -p: full: --change-password help: New password to set @@ -419,9 +422,7 @@ domain: domain: help: Domain name to add extra: - pattern: &pattern_domain - - !!str ^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+([^\W\d_]{2,})$ - - "pattern_domain" + pattern: *pattern_domain -d: full: --dyndns help: Subscribe to the DynDNS service @@ -660,6 +661,10 @@ app: -f: full: --file help: Folder or tarball for upgrade + -F: + full: --force + help: Force the update, even though the app is up to date + action: store_true ### app_change_url() change-url: @@ -847,10 +852,6 @@ backup: -o: full: --output-directory help: Output directory for the backup - -r: - full: --no-compress - help: Do not create an archive file - action: store_true --methods: help: List of backup methods to apply (copy or tar by default) nargs: "*" @@ -996,7 +997,6 @@ service: choices: - file - systemd - default: file --test_status: help: Specify a custom bash command to check the status of the service. Note that it only makes sense to specify this if the corresponding systemd service does not return the proper information already. --test_conf: @@ -1632,17 +1632,19 @@ log: action_help: List logs api: GET /logs arguments: - category: - help: Log category to display (default operations), could be operation, history, package, system, access, service or app - nargs: "*" -l: full: --limit - help: Maximum number of logs + help: Maximum number of operations to list (default to 50) type: int + default: 50 -d: full: --with-details help: Show additional infos (e.g. operation success) but may significantly increase command time. Consider using --limit in combination with this. action: store_true + -s: + full: --with-suboperations + help: Include metadata about operations that are not the main operation but are sub-operations triggered by another ongoing operation... (e.g. initializing groups/permissions when installing an app) + action: store_true ### log_display() display: @@ -1663,6 +1665,10 @@ log: full: --filter-irrelevant help: Do not show some lines deemed not relevant (like set +x or helper argument parsing) action: store_true + -s: + full: --with-suboperations + help: Include metadata about sub-operations of this operation... (e.g. initializing groups/permissions when installing an app) + action: store_true ############################# @@ -1692,6 +1698,9 @@ diagnosis: --share: help: Share the logs using yunopaste action: store_true + --human-readable: + help: Show a human-readable output + action: store_true run: action_help: Run diagnosis @@ -1706,6 +1715,9 @@ diagnosis: --except-if-never-ran-yet: help: Don't run anything if diagnosis never ran yet ... (this is meant to be used by the webadmin) action: store_true + --email: + help: Send an email to root with issues found (this is meant to be used by cron job) + action: store_true ignore: action_help: Configure some diagnosis results to be ignored and therefore not considered as actual issues diff --git a/data/actionsmap/yunohost_completion.py b/data/actionsmap/yunohost_completion.py index 45d15f16c..f4fee30ca 100644 --- a/data/actionsmap/yunohost_completion.py +++ b/data/actionsmap/yunohost_completion.py @@ -15,15 +15,17 @@ THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml' BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost' + def get_dict_actions(OPTION_SUBTREE, category): ACTIONS = [action for action in OPTION_SUBTREE[category]["actions"].keys() - if not action.startswith('_')] + if not action.startswith('_')] ACTIONS_STR = '{}'.format(' '.join(ACTIONS)) - DICT = { "actions_str": ACTIONS_STR } + DICT = {"actions_str": ACTIONS_STR} return DICT + with open(ACTIONSMAP_FILE, 'r') as stream: # Getting the dictionary containning what actions are possible per category @@ -40,10 +42,10 @@ with open(ACTIONSMAP_FILE, 'r') as stream: ACTIONS_DICT[category]["subcategories_str"] = "" if "subcategories" in OPTION_TREE[category].keys(): - SUBCATEGORIES = [ subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys() ] + SUBCATEGORIES = [subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys()] SUBCATEGORIES_STR = '{}'.format(' '.join(SUBCATEGORIES)) - + ACTIONS_DICT[category]["subcategories_str"] = SUBCATEGORIES_STR for subcategory in SUBCATEGORIES: diff --git a/data/helpers b/data/helpers index a56a6a57a..5ec562f61 100644 --- a/data/helpers +++ b/data/helpers @@ -1,7 +1,8 @@ # -*- shell-script -*- -# TODO : use --regex to validate against a namespace +set +x for helper in $(run-parts --list /usr/share/yunohost/helpers.d 2>/dev/null) ; do [ -r $helper ] && . $helper || true done +set -x diff --git a/data/helpers.d/apt b/data/helpers.d/apt index 3b4b199d0..1a4a9f74a 100644 --- a/data/helpers.d/apt +++ b/data/helpers.d/apt @@ -10,6 +10,7 @@ # Requires YunoHost version 3.3.1 or higher. ynh_wait_dpkg_free() { local try + set +o xtrace # set +x # With seq 1 17, timeout will be almost 30 minutes for try in `seq 1 17` do @@ -32,13 +33,16 @@ ynh_wait_dpkg_free() { then # If so, that a remaining of dpkg. ynh_print_err "E: dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem." + set -o xtrace # set -x return 1 fi done 9<<< "$(ls -1 $dpkg_dir)" + set -o xtrace # set -x return 0 fi done echo "apt still used, but timeout reached !" + set -o xtrace # set -x } # Check either a package is installed or not @@ -96,7 +100,7 @@ ynh_package_version() { # Requires YunoHost version 2.4.0.3 or higher. ynh_apt() { ynh_wait_dpkg_free - LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get --assume-yes $@ + LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get --assume-yes --quiet -o=Acquire::Retries=3 -o=Dpkg::Use-Pty=0 $@ } # Update package index files @@ -256,15 +260,11 @@ ynh_install_app_dependencies () { # And we have packages from sury installed (7.0.33-10+weirdshiftafter instead of 7.0.33-0 on debian) if dpkg --list | grep "php7.0" | grep --quiet --invert-match "7.0.33-0+deb9" then - # And sury ain't already installed - if ! grep --line-number --recursive --quiet "sury" /etc/apt/sources.list* + # And sury ain't already in sources.lists + if ! grep --recursive --quiet "^ *deb.*sury" /etc/apt/sources.list* then # Re-add sury - ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version - - # Pin this sury repository to prevent sury of doing shit - ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version - ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append + ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version --priority=600 fi fi fi @@ -329,8 +329,6 @@ ynh_remove_app_dependencies () { ynh_package_autopurge ${dep_app}-ynh-deps # Remove the fake package and its dependencies if they not still used. } -#================================================= - # Install packages from an extra repository properly. # # usage: ynh_install_extra_app_dependencies --repo="repo" --package="dep1 dep2" [--key=key_url] [--name=name] @@ -463,8 +461,8 @@ ynh_remove_extra_repo () { ynh_secure_remove "/etc/apt/sources.list.d/$name.list" ynh_secure_remove "/etc/apt/preferences.d/$name" - ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.gpg" - ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.asc" + ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.gpg" > /dev/null + ynh_secure_remove "/etc/apt/trusted.gpg.d/$name.asc" > /dev/null # Update the list of package to exclude the old repo ynh_package_update diff --git a/data/helpers.d/fail2ban b/data/helpers.d/fail2ban index d8777a16d..f9bdd89b2 100644 --- a/data/helpers.d/fail2ban +++ b/data/helpers.d/fail2ban @@ -134,7 +134,7 @@ EOF ynh_systemd_action --service_name=fail2ban --action=reload --line_match="(Started|Reloaded) Fail2Ban Service" --log_path=systemd - local fail2ban_error="$(journalctl --unit=fail2ban | tail --lines=50 | grep "WARNING.*$app.*")" + local fail2ban_error="$(journalctl --no-hostname --unit=fail2ban | tail --lines=50 | grep "WARNING.*$app.*")" if [[ -n "$fail2ban_error" ]] then ynh_print_err --message="Fail2ban failed to load the jail for $app" diff --git a/data/helpers.d/getopts b/data/helpers.d/getopts index 10c06930c..a4bbe20e6 100644 --- a/data/helpers.d/getopts +++ b/data/helpers.d/getopts @@ -80,10 +80,10 @@ ynh_handle_getopts_args () { arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}-/--${args_array[$option_flag]}\\TOBEREMOVED\\-}" # And replace long option (value of the option_flag) by the short option, the option_flag itself # (e.g. for [u]=user, --user will be -u) - # Replace long option with = - arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}/-${option_flag} }" - # And long option without = - arguments[arg]="${arguments[arg]//--${args_array[$option_flag]%=}/-${option_flag}}" + # Replace long option with = (match the beginning of the argument) + arguments[arg]="$(echo "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]}/-${option_flag} /")" + # And long option without = (match the whole line) + arguments[arg]="$(echo "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]%=}$/-${option_flag} /")" done done diff --git a/data/helpers.d/logging b/data/helpers.d/logging index d5f4f5eec..45b5b7e67 100644 --- a/data/helpers.d/logging +++ b/data/helpers.d/logging @@ -80,7 +80,7 @@ ynh_print_warn () { # Manage arguments with getopts ynh_handle_getopts_args "$@" - ynh_print_log "\e[93m\e[1m[WARN]\e[0m ${message}" >&2 + ynh_print_log "${message}" >&2 } # Print an error on stderr @@ -97,7 +97,7 @@ ynh_print_err () { # Manage arguments with getopts ynh_handle_getopts_args "$@" - ynh_print_log "\e[91m\e[1m[ERR]\e[0m ${message}" >&2 + ynh_print_log "[Error] ${message}" >&2 } # Execute a command and print the result as an error @@ -332,7 +332,7 @@ ynh_debug () { if [ -n "$message" ] then - ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2 + ynh_print_log "[Debug] ${message}" >&2 fi if [ "$trace" == "1" ] diff --git a/data/helpers.d/mysql b/data/helpers.d/mysql index 84acc1029..05f75e0a2 100644 --- a/data/helpers.d/mysql +++ b/data/helpers.d/mysql @@ -44,8 +44,13 @@ ynh_mysql_execute_as_root() { ynh_handle_getopts_args "$@" database="${database:-}" + if [ -n "$database" ] + then + database="--database=$database" + fi + ynh_mysql_connect_as --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" \ - --database="$database" <<< "$sql" + $database <<< "$sql" } # Execute a command from a file as root user @@ -65,8 +70,14 @@ ynh_mysql_execute_file_as_root() { ynh_handle_getopts_args "$@" database="${database:-}" + if [ -n "$database" ] + then + database="--database=$database" + fi + + ynh_mysql_connect_as --user="root" --password="$(cat $MYSQL_ROOT_PWD_FILE)" \ - --database="$database" < "$file" + $database < "$file" } # Create a database and grant optionnaly privilegies to a user diff --git a/data/helpers.d/nodejs b/data/helpers.d/nodejs index 3ad0c400f..75472c278 100644 --- a/data/helpers.d/nodejs +++ b/data/helpers.d/nodejs @@ -1,5 +1,6 @@ #!/bin/bash +n_version=6.5.1 n_install_dir="/opt/node_n" node_version_path="$n_install_dir/n/versions/node" # N_PREFIX is the directory of n, it needs to be loaded as a environment variable. @@ -16,8 +17,8 @@ ynh_install_n () { ynh_print_info --message="Installation of N - Node.js version management" # Build an app.src for n mkdir --parents "../conf" - echo "SOURCE_URL=https://github.com/tj/n/archive/v4.1.0.tar.gz -SOURCE_SUM=3983fa3f00d4bf85ba8e21f1a590f6e28938093abe0bb950aeea52b1717471fc" > "../conf/n.src" + echo "SOURCE_URL=https://github.com/tj/n/archive/v${n_version}.tar.gz +SOURCE_SUM=5833f15893b9951a9ed59487e87b6c181d96b83a525846255872c4f92f0d25dd" > "../conf/n.src" # Download and extract n ynh_setup_source --dest_dir="$n_install_dir/git" --source_id=n # Install n @@ -125,7 +126,10 @@ ynh_install_nodejs () { test -x /usr/bin/npm && mv /usr/bin/npm /usr/bin/npm_n # If n is not previously setup, install it - if ! test $(n --version > /dev/null 2>&1) + if ! $n_install_dir/bin/n --version > /dev/null 2>&1 + then + ynh_install_n + elif dpkg --compare-versions "$($n_install_dir/bin/n --version)" lt $n_version then ynh_install_n fi diff --git a/data/helpers.d/php b/data/helpers.d/php index e8de6d9ff..489c448a8 100644 --- a/data/helpers.d/php +++ b/data/helpers.d/php @@ -1,37 +1,37 @@ #!/bin/bash -readonly YNH_DEFAULT_PHP_VERSION=7.0 -# Declare the actual php version to use. -# A packager willing to use another version of php can override the variable into its _common.sh. +readonly YNH_DEFAULT_PHP_VERSION=7.3 +# Declare the actual PHP version to use. +# A packager willing to use another version of PHP can override the variable into its _common.sh. YNH_PHP_VERSION=${YNH_PHP_VERSION:-$YNH_DEFAULT_PHP_VERSION} -# Create a dedicated php-fpm config +# Create a dedicated PHP-FPM config # # usage 1: ynh_add_fpm_config [--phpversion=7.X] [--use_template] [--package=packages] [--dedicated_service] -# | arg: -v, --phpversion= - Version of php to use. +# | arg: -v, --phpversion= - Version of PHP to use. # | arg: -t, --use_template - Use this helper in template mode. -# | arg: -p, --package= - Additionnal php packages to install -# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one. +# | arg: -p, --package= - Additionnal PHP packages to install +# | arg: -d, --dedicated_service - Use a dedicated PHP-FPM service instead of the common one. # # ----------------------------------------------------------------------------- # # usage 2: ynh_add_fpm_config [--phpversion=7.X] --usage=usage --footprint=footprint [--package=packages] [--dedicated_service] -# | arg: -v, --phpversion= - Version of php to use. +# | arg: -v, --phpversion= - Version of PHP to use. # | arg: -f, --footprint= - Memory footprint of the service (low/medium/high). -# low - Less than 20Mb of ram by pool. -# medium - Between 20Mb and 40Mb of ram by pool. -# high - More than 40Mb of ram by pool. -# Or specify exactly the footprint, the load of the service as Mb by pool instead of having a standard value. +# low - Less than 20 MB of RAM by pool. +# medium - Between 20 MB and 40 MB of RAM by pool. +# high - More than 40 MB of RAM by pool. +# Or specify exactly the footprint, the load of the service as MB by pool instead of having a standard value. # To have this value, use the following command and stress the service. # watch -n0.5 ps -o user,cmd,%cpu,rss -u APP # # | arg: -u, --usage= - Expected usage of the service (low/medium/high). -# low - Personal usage, behind the sso. +# low - Personal usage, behind the SSO. # medium - Low usage, few people or/and publicly accessible. # high - High usage, frequently visited website. # -# | arg: -p, --package= - Additionnal php packages to install for a specific version of php -# | arg: -d, --dedicated_service - Use a dedicated php-fpm service instead of the common one. +# | arg: -p, --package= - Additionnal PHP packages to install for a specific version of PHP +# | arg: -d, --dedicated_service - Use a dedicated PHP-FPM service instead of the common one. # # # The footprint of the service will be used to defined the maximum footprint we can allow, which is half the maximum RAM. @@ -85,7 +85,7 @@ ynh_add_fpm_config () { # Set the default PHP-FPM version by default phpversion="${phpversion:-$YNH_PHP_VERSION}" - # If the requested php version is not the default version for YunoHost + # If the requested PHP version is not the default version for YunoHost if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ] then # If the argument --package is used, add the packages to ynh_install_php to install them from sury @@ -95,7 +95,7 @@ ynh_add_fpm_config () { else local additionnal_packages="" fi - # Install this specific version of php. + # Install this specific version of PHP. ynh_install_php --phpversion="$phpversion" "$additionnal_packages" elif [ -n "$package" ] then @@ -118,7 +118,7 @@ ynh_add_fpm_config () { fpm_service="php5-fpm" fi - # Create the directory for fpm pools + # Create the directory for FPM pools mkdir --parents "$fpm_config_dir/pool.d" ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir" @@ -127,7 +127,7 @@ ynh_add_fpm_config () { ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion finalphpconf="$fpm_config_dir/pool.d/$app.conf" - # Migrate from mutual php service to dedicated one. + # Migrate from mutual PHP service to dedicated one. if [ $dedicated_service -eq 1 ] then local old_fpm_config_dir="/etc/php/$phpversion/fpm" @@ -137,9 +137,9 @@ ynh_add_fpm_config () { ynh_print_info --message="Migrate to a dedicated php-fpm service for $app." # Create a backup of the old file before migration ynh_backup_if_checksum_is_different --file="$old_fpm_config_dir/pool.d/$app.conf" - # Remove the old php config file + # Remove the old PHP config file ynh_secure_remove --file="$old_fpm_config_dir/pool.d/$app.conf" - # Reload php to release the socket and allow the dedicated service to use it + # Reload PHP to release the socket and allow the dedicated service to use it ynh_systemd_action --service_name=php${phpversion}-fpm --action=reload fi fi @@ -148,21 +148,27 @@ ynh_add_fpm_config () { if [ $use_template -eq 1 ] then - # Usage 1, use the template in ../conf/php-fpm.conf - cp ../conf/php-fpm.conf "$finalphpconf" + # Usage 1, use the template in conf/php-fpm.conf + local phpfpm_path="../conf/php-fpm.conf" + if [ ! -e "$phpfpm_path" ]; then + phpfpm_path="../settings/conf/php-fpm.conf" # Into the restore script, the PHP-FPM template is not at the same place + fi + # Make sure now that the template indeed exists + [ -e "$phpfpm_path" ] || ynh_die --message="Unable to find template to configure PHP-FPM." + cp "$phpfpm_path" "$finalphpconf" ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$finalphpconf" ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalphpconf" ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$finalphpconf" ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="$finalphpconf" else - # Usage 2, generate a php-fpm config file with ynh_get_scalable_phpfpm + # Usage 2, generate a PHP-FPM config file with ynh_get_scalable_phpfpm # Store settings ynh_app_setting_set --app=$app --key=fpm_footprint --value=$footprint ynh_app_setting_set --app=$app --key=fpm_usage --value=$usage - # Define the values to use for the configuration of php. + # Define the values to use for the configuration of PHP. ynh_get_scalable_phpfpm --usage=$usage --footprint=$footprint # Copy the default file @@ -175,7 +181,7 @@ ynh_add_fpm_config () { ynh_replace_string --match_string="^group = .*" --replace_string="group = $app" --target_file="$finalphpconf" ynh_replace_string --match_string=".*chdir = .*" --replace_string="chdir = $final_path" --target_file="$finalphpconf" - # Configure fpm children + # Configure FPM children ynh_replace_string --match_string=".*pm = .*" --replace_string="pm = $php_pm" --target_file="$finalphpconf" ynh_replace_string --match_string=".*pm.max_children = .*" --replace_string="pm.max_children = $php_max_children" --target_file="$finalphpconf" ynh_replace_string --match_string=".*pm.max_requests = .*" --replace_string="pm.max_requests = 500" --target_file="$finalphpconf" @@ -232,7 +238,7 @@ ynh_add_fpm_config () { ynh_replace_string --match_string="^[; ]*syslog.ident *=.*" --replace_string="syslog.ident = php-fpm-$app" --target_file="$globalphpconf" ynh_replace_string --match_string="^[; ]*include *=.*" --replace_string="include = $finalphpconf" --target_file="$globalphpconf" - # Create a config for a dedicated php-fpm service for the app + # Create a config for a dedicated PHP-FPM service for the app echo "[Unit] Description=PHP $phpversion FastCGI Process Manager for $app After=network.target @@ -247,7 +253,7 @@ ExecReload=/bin/kill -USR2 \$MAINPID WantedBy=multi-user.target " > ../conf/$fpm_service - # Create this dedicated php-fpm service + # Create this dedicated PHP-FPM service ynh_add_systemd_config --service=$fpm_service --template=$fpm_service # Integrate the service in YunoHost admin panel yunohost service add $fpm_service --log /var/log/php/fpm-php.$app.log --log_type file --description "Php-fpm dedicated to $app" @@ -256,12 +262,12 @@ WantedBy=multi-user.target # Restart the service, as this service is either stopped or only for this app ynh_systemd_action --service_name=$fpm_service --action=restart else - # Reload php, to not impact other parts of the system using php + # Reload PHP, to not impact other parts of the system using PHP ynh_systemd_action --service_name=$fpm_service --action=reload fi } -# Remove the dedicated php-fpm config +# Remove the dedicated PHP-FPM config # # usage: ynh_remove_fpm_config # @@ -271,13 +277,13 @@ ynh_remove_fpm_config () { local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service) local dedicated_service=$(ynh_app_setting_get --app=$app --key=fpm_dedicated_service) dedicated_service=${dedicated_service:-0} - # Get the version of php used by this app + # Get the version of PHP used by this app local phpversion=$(ynh_app_setting_get $app phpversion) # Assume default PHP-FPM version by default phpversion="${phpversion:-$YNH_DEFAULT_PHP_VERSION}" - # Assume default php files if not set + # Assume default PHP files if not set if [ -z "$fpm_config_dir" ] then fpm_config_dir="/etc/php/$YNH_DEFAULT_PHP_VERSION/fpm" @@ -286,34 +292,37 @@ ynh_remove_fpm_config () { if [ $dedicated_service -eq 1 ] then - # Remove the dedicated service php-fpm service for the app + # Remove the dedicated service PHP-FPM service for the app ynh_remove_systemd_config --service=$fpm_service - # Remove the global php-fpm conf + # Remove the global PHP-FPM conf ynh_secure_remove --file="$fpm_config_dir/php-fpm-$app.conf" - # Remove the service from the list of services known by Yunohost + # Remove the service from the list of services known by YunoHost yunohost service remove $fpm_service elif ynh_package_is_installed --package="php${phpversion}-fpm"; then ynh_systemd_action --service_name=$fpm_service --action=reload fi ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf" - ynh_exec_warn_less ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini" + if [ -e $fpm_config_dir/conf.d/20-$app.ini ] + then + ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini" + fi - # If the php version used is not the default version for YunoHost + # If the PHP version used is not the default version for YunoHost if [ "$phpversion" != "$YNH_DEFAULT_PHP_VERSION" ] then - # Remove this specific version of php + # Remove this specific version of PHP ynh_remove_php fi } -# Install another version of php. +# Install another version of PHP. # # [internal] # # usage: ynh_install_php --phpversion=phpversion [--package=packages] -# | arg: -v, --phpversion= - Version of php to install. -# | arg: -p, --package= - Additionnal php packages to install +# | arg: -v, --phpversion= - Version of PHP to install. +# | arg: -p, --package= - Additionnal PHP packages to install # # Requires YunoHost version 3.8.1 or higher. ynh_install_php () { @@ -340,30 +349,26 @@ ynh_install_php () { # Do not add twice the same line if ! grep --quiet "$YNH_APP_INSTANCE_NAME:" "/etc/php/ynh_app_version" then - # Store the ID of this app and the version of php requested for it + # Store the ID of this app and the version of PHP requested for it echo "$YNH_APP_INSTANCE_NAME:$phpversion" | tee --append "/etc/php/ynh_app_version" fi # Add an extra repository for those packages - ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version + ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version --priority=600 # Install requested dependencies from this extra repository. - # Install php-fpm first, otherwise php will install apache as a dependency. + # Install PHP-FPM first, otherwise PHP will install apache as a dependency. ynh_add_app_dependencies --package="php${phpversion}-fpm" ynh_add_app_dependencies --package="php$phpversion php${phpversion}-common $package" - # Set the default php version back as the default version for php-cli. + # Set the default PHP version back as the default version for php-cli. update-alternatives --set php /usr/bin/php$YNH_DEFAULT_PHP_VERSION - # Pin this extra repository after packages are installed to prevent sury of doing shit - ynh_pin_repo --package="*" --pin="origin \"packages.sury.org\"" --priority=200 --name=extra_php_version - ynh_pin_repo --package="php${YNH_DEFAULT_PHP_VERSION}*" --pin="origin \"packages.sury.org\"" --priority=600 --name=extra_php_version --append - # Advertise service in admin panel yunohost service add php${phpversion}-fpm --log "/var/log/php${phpversion}-fpm.log" } -# Remove the specific version of php used by the app. +# Remove the specific version of PHP used by the app. # # [internal] # @@ -371,7 +376,7 @@ ynh_install_php () { # # Requires YunoHost version 3.8.1 or higher. ynh_remove_php () { - # Get the version of php used by this app + # Get the version of PHP used by this app local phpversion=$(ynh_app_setting_get $app phpversion) if [ "$phpversion" == "$YNH_DEFAULT_PHP_VERSION" ] || [ -z "$phpversion" ] @@ -389,7 +394,7 @@ ynh_remove_php () { # Remove the line for this app sed --in-place "/$YNH_APP_INSTANCE_NAME:$phpversion/d" "/etc/php/ynh_app_version" - # If no other app uses this version of php, remove it. + # If no other app uses this version of PHP, remove it. if ! grep --quiet "$phpversion" "/etc/php/ynh_app_version" then # Remove the service from the admin panel @@ -397,26 +402,26 @@ ynh_remove_php () { yunohost service remove php${phpversion}-fpm fi - # Purge php dependencies for this version. + # Purge PHP dependencies for this version. ynh_package_autopurge "php$phpversion php${phpversion}-fpm php${phpversion}-common" fi } -# Define the values to configure php-fpm +# Define the values to configure PHP-FPM # # [internal] # # usage: ynh_get_scalable_phpfpm --usage=usage --footprint=footprint [--print] # | arg: -f, --footprint= - Memory footprint of the service (low/medium/high). -# low - Less than 20Mb of ram by pool. -# medium - Between 20Mb and 40Mb of ram by pool. -# high - More than 40Mb of ram by pool. -# Or specify exactly the footprint, the load of the service as Mb by pool instead of having a standard value. +# low - Less than 20 MB of RAM by pool. +# medium - Between 20 MB and 40 MB of RAM by pool. +# high - More than 40 MB of RAM by pool. +# Or specify exactly the footprint, the load of the service as MB by pool instead of having a standard value. # To have this value, use the following command and stress the service. # watch -n0.5 ps -o user,cmd,%cpu,rss -u APP # # | arg: -u, --usage= - Expected usage of the service (low/medium/high). -# low - Personal usage, behind the sso. +# low - Personal usage, behind the SSO. # medium - Low usage, few people or/and publicly accessible. # high - High usage, frequently visited website. # @@ -487,7 +492,7 @@ ynh_get_scalable_phpfpm () { # Define pm.max_children # The value of pm.max_children is the total amount of ram divide by 2 and divide again by the footprint of a pool for this app. - # So if php-fpm start the maximum of children, it won't exceed half of the ram. + # So if PHP-FPM start the maximum of children, it won't exceed half of the ram. php_max_children=$(( $max_ram / 2 / $footprint )) # If process manager is set as static, use half less children. # Used as static, there's always as many children as the value of pm.max_children diff --git a/data/helpers.d/postgresql b/data/helpers.d/postgresql index e2bef8746..11b9c0fed 100644 --- a/data/helpers.d/postgresql +++ b/data/helpers.d/postgresql @@ -1,6 +1,7 @@ #!/bin/bash PSQL_ROOT_PWD_FILE=/etc/yunohost/psql +PSQL_VERSION=11 # Open a connection as a user # @@ -45,8 +46,13 @@ ynh_psql_execute_as_root() { ynh_handle_getopts_args "$@" database="${database:-}" + if [ -n "$database" ] + then + database="--database=$database" + fi + ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \ - --database="$database" <<<"$sql" + $database <<<"$sql" } # Execute a command from a file as root user @@ -66,8 +72,13 @@ ynh_psql_execute_file_as_root() { ynh_handle_getopts_args "$@" database="${database:-}" + if [ -n "$database" ] + then + database="--database=$database" + fi + ynh_psql_connect_as --user="postgres" --password="$(cat $PSQL_ROOT_PWD_FILE)" \ - --database="$database" <"$file" + $database <"$file" } # Create a database and grant optionnaly privilegies to a user @@ -212,7 +223,7 @@ ynh_psql_drop_user() { # usage: ynh_psql_setup_db --db_user=user --db_name=name [--db_pwd=pwd] # | arg: -u, --db_user= - Owner of the database # | arg: -n, --db_name= - Name of the database -# | arg: -p, --db_pwd= - Password of the database. If not given, a password will be generated +# | arg: -p, --db_pwd= - Password of the database. If not provided, a password will be generated # # After executing this helper, the password of the created database will be available in $db_pwd # It will also be stored as "psqlpwd" into the app settings. @@ -228,12 +239,14 @@ ynh_psql_setup_db() { # Manage arguments with getopts ynh_handle_getopts_args "$@" - local new_db_pwd=$(ynh_string_random) # Generate a random password - # If $db_pwd is not given, use new_db_pwd instead for db_pwd - db_pwd="${db_pwd:-$new_db_pwd}" - if ! ynh_psql_user_exists --user=$db_user; then + local new_db_pwd=$(ynh_string_random) # Generate a random password + # If $db_pwd is not provided, use new_db_pwd instead for db_pwd + db_pwd="${db_pwd:-$new_db_pwd}" + ynh_psql_create_user "$db_user" "$db_pwd" + elif [ -z $db_pwd ]; then + ynh_die --message="The user $db_user exists, please provide his password" fi ynh_psql_create_db "$db_name" "$db_user" # Create the database @@ -273,6 +286,7 @@ ynh_psql_remove_db() { } # Create a master password and set up global settings +# It also make sure that postgresql is installed and running # Please always call this script in install and restore scripts # # usage: ynh_psql_test_if_first_run @@ -280,45 +294,38 @@ ynh_psql_remove_db() { # Requires YunoHost version 2.7.13 or higher. ynh_psql_test_if_first_run() { - if [ -f "$PSQL_ROOT_PWD_FILE" ] + # Make sure postgresql is indeed installed + dpkg --list | grep -q "ii postgresql-$PSQL_VERSION" || ynh_die "postgresql-$PSQL_VERSION is not installed !?" + + # Check for some weird issue where postgresql could be installed but etc folder would not exist ... + [ -e "/etc/postgresql/$PSQL_VERSION" ] || ynh_die "It looks like postgresql was not properly configured ? /etc/postgresql/$PSQL_VERSION is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist" + + # Make sure postgresql is started and enabled + # (N.B. : to check the active state, we check the cluster state because + # postgresql could be flagged as active even though the cluster is in + # failed state because of how the service is configured..) + systemctl is-active postgresql@$PSQL_VERSION-main -q || ynh_systemd_action --service_name=postgresql --action=restart + systemctl is-enabled postgresql -q || systemctl enable postgresql --quiet + + # If this is the very first time, we define the root password + # and configure a few things + if [ ! -f "$PSQL_ROOT_PWD_FILE" ] then - ynh_print_info --message="PostgreSQL is already installed, no need to create master password" - return + local pg_hba=/etc/postgresql/$PSQL_VERSION/main/pg_hba.conf + + local psql_root_password="$(ynh_string_random)" + echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE + sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres + + # force all user to connect to local databases using hashed passwords + # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF + # Note: we can't use peer since YunoHost create users with nologin + # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user + ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba" + + # Integrate postgresql service in yunohost + yunohost service add postgresql --log "/var/log/postgresql/" + + ynh_systemd_action --service_name=postgresql --action=reload fi - - local psql_root_password="$(ynh_string_random)" - echo "$psql_root_password" >$PSQL_ROOT_PWD_FILE - - if [ -e /etc/postgresql/9.4/ ] - then - local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf - local logfile=/var/log/postgresql/postgresql-9.4-main.log - elif [ -e /etc/postgresql/9.6/ ] - then - local pg_hba=/etc/postgresql/9.6/main/pg_hba.conf - local logfile=/var/log/postgresql/postgresql-9.6-main.log - else - if dpkg --list | grep -q "ii postgresql-9." - then - ynh_die "It looks like postgresql was not properly configured ? /etc/postgresql/9.* is missing ... Could be due to a locale issue, c.f.https://serverfault.com/questions/426989/postgresql-etc-postgresql-doesnt-exist" - else - ynh_die "postgresql shoud be 9.4 or 9.6" - fi - fi - - ynh_systemd_action --service_name=postgresql --action=start - - sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$psql_root_password'" postgres - - # force all user to connect to local databases using hashed passwords - # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF - # Note: we can't use peer since YunoHost create users with nologin - # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user - ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3md5" --target_file="$pg_hba" - - # Advertise service in admin panel - yunohost service add postgresql --log "$logfile" - - systemctl enable postgresql - ynh_systemd_action --service_name=postgresql --action=reload } diff --git a/data/helpers.d/systemd b/data/helpers.d/systemd index 613f023fa..5c5fda852 100644 --- a/data/helpers.d/systemd +++ b/data/helpers.d/systemd @@ -58,7 +58,7 @@ ynh_add_systemd_config () { ynh_store_file_checksum --file="$finalsystemdconf" chown root: "$finalsystemdconf" - systemctl enable $service + systemctl enable $service --quiet systemctl daemon-reload } @@ -81,7 +81,7 @@ ynh_remove_systemd_config () { if [ -e "$finalsystemdconf" ] then ynh_systemd_action --service_name=$service --action=stop - systemctl disable $service + systemctl disable $service --quiet ynh_secure_remove --file="$finalsystemdconf" systemctl daemon-reload fi @@ -145,7 +145,7 @@ ynh_systemd_action() { if ! systemctl $action $service_name then # Show syslog for this service - ynh_exec_err journalctl --no-pager --lines=$length --unit=$service_name + ynh_exec_err journalctl --quiet --no-hostname --no-pager --lines=$length --unit=$service_name # If a log is specified for this service, show also the content of this log if [ -e "$log_path" ] then @@ -183,7 +183,7 @@ ynh_systemd_action() { then ynh_print_warn --message="The service $service_name didn't fully executed the action ${action} before the timeout." ynh_print_warn --message="Please find here an extract of the end of the log of the service $service_name:" - ynh_exec_warn journalctl --no-pager --lines=$length --unit=$service_name + ynh_exec_warn journalctl --quiet --no-hostname --no-pager --lines=$length --unit=$service_name if [ -e "$log_path" ] then ynh_print_warn --message="\-\-\-" diff --git a/data/helpers.d/utils b/data/helpers.d/utils index 9c2f40618..95f8ddc52 100644 --- a/data/helpers.d/utils +++ b/data/helpers.d/utils @@ -144,8 +144,13 @@ ynh_setup_source () { then # Use the local source file if it is present cp $local_src $src_filename else # If not, download the source + # NB. we have to declare the var as local first, + # otherwise 'local foo=$(false) || echo 'pwet'" does'nt work + # because local always return 0 ... + local out # Timeout option is here to enforce the timeout on dns query and tcp connect (c.f. man wget) - local out=`wget --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1` || ynh_print_err --message="$out" + out=$(wget --tries 3 --no-dns-cache --timeout 900 --no-verbose --output-document=$src_filename $src_url 2>&1) \ + || ynh_die --message="$out" fi # Check the control sum @@ -431,9 +436,8 @@ ynh_app_upstream_version () { local manifest # Manage arguments with getopts ynh_handle_getopts_args "$@" - manifest="${manifest:-../manifest.json}" - version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version") + version_key=$YNH_APP_MANIFEST_VERSION echo "${version_key/~ynh*/}" } @@ -456,9 +460,8 @@ ynh_app_package_version () { local manifest # Manage arguments with getopts ynh_handle_getopts_args "$@" - manifest="${manifest:-../manifest.json}" - version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version") + version_key=$YNH_APP_MANIFEST_VERSION echo "${version_key/*~ynh/}" } @@ -511,3 +514,49 @@ ynh_check_app_version_changed () { fi echo $return_value } + +# Compare the current package version against another version given as an argument. +# This is really useful when we need to do some actions only for some old package versions. +# +# example: ynh_compare_current_package_version --comparison lt --version 2.3.2~ynh1 +# This example will check if the installed version is lower than (lt) the version 2.3.2~ynh1 +# +# Generally you might probably use it as follow in the upgrade script +# +# if ynh_compare_current_package_version --comparaison lt --version 2.3.2~ynh1 +# then +# # Do something that is needed for the package version older than 2.3.2~ynh1 +# fi +# +# usage: ynh_compare_current_package_version --comparison lt|le|eq|ne|ge|gt +# | arg: --comparison - Comparison type. Could be : lt (lower than), le (lower or equal), +# | eq (equal), ne (not equal), ge (greater or equal), gt (greater than) +# | arg: --version - The version to compare. Need to be a version in the yunohost package version type (like 2.3.1~ynh4) +# +# Return 0 if the evaluation is true. 1 if false. +# +# Requires YunoHost version 3.8.0 or higher. +ynh_compare_current_package_version() { + local legacy_args=cv + declare -Ar args_array=( [c]=comparison= [v]=version= ) + local version + local comparison + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + + local current_version=$YNH_APP_CURRENT_VERSION + + # Check the syntax of the versions + if [[ ! $version =~ '~ynh' ]] || [[ ! $current_version =~ '~ynh' ]] + then + ynh_die "Invalid argument for version." + fi + + # Check validity of the comparator + if [[ ! $comparison =~ (lt|le|eq|ne|ge|gt) ]]; then + ynh_die "Invialid comparator must be : lt, le, eq, ne, ge, gt" + fi + + # Return the return value of dpkg --compare-versions + dpkg --compare-versions $current_version $comparison $version +} diff --git a/data/hooks/backup/05-conf_ldap b/data/hooks/backup/05-conf_ldap index 75b4c2075..e3e8e455d 100755 --- a/data/hooks/backup/05-conf_ldap +++ b/data/hooks/backup/05-conf_ldap @@ -10,7 +10,8 @@ source /usr/share/yunohost/helpers backup_dir="${1}/conf/ldap" # Backup the configuration -ynh_backup "/etc/ldap/slapd.conf" "${backup_dir}/slapd.conf" +ynh_backup "/etc/ldap/ldap.conf" "${backup_dir}/ldap.conf" +ynh_backup "/etc/ldap/slapd.ldif" "${backup_dir}/slapd.ldif" slapcat -b cn=config -l "${backup_dir}/cn=config.master.ldif" # Backup the database diff --git a/data/hooks/backup/11-conf_ynh_mysql b/data/hooks/backup/11-conf_ynh_mysql deleted file mode 100755 index 031707337..000000000 --- a/data/hooks/backup/11-conf_ynh_mysql +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Exit hook on subcommand error or unset variable -set -eu - -# Source YNH helpers -source /usr/share/yunohost/helpers - -# Backup destination -backup_dir="${1}/conf/ynh/mysql" - -# Save MySQL root password -ynh_backup "/etc/yunohost/mysql" "${backup_dir}/root_pwd" diff --git a/data/hooks/conf_regen/01-yunohost b/data/hooks/conf_regen/01-yunohost index 236619079..c4120d487 100755 --- a/data/hooks/conf_regen/01-yunohost +++ b/data/hooks/conf_regen/01-yunohost @@ -55,14 +55,63 @@ do_pre_regen() { fi # add cron job for diagnosis to be ran at 7h and 19h + a random delay between - # 0 and 10min, meant to avoid every instances running their diagnosis at + # 0 and 20min, meant to avoid every instances running their diagnosis at # exactly the same time, which may overload the diagnosis server. mkdir -p $pending_dir/etc/cron.d/ cat > $pending_dir/etc/cron.d/yunohost-diagnosis << EOF SHELL=/bin/bash -0 7,19 * * * root : YunoHost Diagnosis; sleep \$((RANDOM\\%600)); yunohost diagnosis run > /dev/null +0 7,19 * * * root : YunoHost Automatic Diagnosis; sleep \$((RANDOM\\%1200)); yunohost diagnosis run --email > /dev/null 2>/dev/null || echo "Running the automatic diagnosis failed miserably" EOF + # legacy stuff to avoid yunohost reporting etckeeper as manually modified + # (this make sure that the hash is null / file is flagged as to-delete) + mkdir -p $pending_dir/etc/etckeeper + touch $pending_dir/etc/etckeeper/etckeeper.conf + + # Skip ntp if inside a container (inspired from the conf of systemd-timesyncd) + mkdir -p ${pending_dir}/etc/systemd/system/ntp.service.d/ + echo " +[Unit] +ConditionCapability=CAP_SYS_TIME +ConditionVirtualization=!container +" > ${pending_dir}/etc/systemd/system/ntp.service.d/ynh-override.conf + + # Make nftable conflict with yunohost-firewall + mkdir -p ${pending_dir}/etc/systemd/system/nftables.service.d/ + cat > ${pending_dir}/etc/systemd/system/nftables.service.d/ynh-override.conf << EOF +[Unit] +# yunohost-firewall and nftables conflict with each other +Conflicts=yunohost-firewall.service +ConditionFileIsExecutable=!/etc/init.d/yunohost-firewall +ConditionPathExists=!/etc/systemd/system/multi-user.target.wants/yunohost-firewall.service +EOF +} + +do_post_regen() { + regen_conf_files=$1 + + ###################### + # Enfore permissions # + ###################### + + # Certs + # We do this with find because there could be a lot of them... + chown -R root:ssl-cert /etc/yunohost/certs + chmod 750 /etc/yunohost/certs + find /etc/yunohost/certs/ -type f -exec chmod 640 {} \; + find /etc/yunohost/certs/ -type d -exec chmod 750 {} \; + + # Misc configuration / state files + chown root:root $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null) + chmod 600 $(ls /etc/yunohost/{*.yml,*.yaml,*.json,mysql,psql} 2>/dev/null) + + # Apps folder, custom hooks folder + [[ ! -e /etc/yunohost/hooks.d ]] || (chown root /etc/yunohost/hooks.d && chmod 700 /etc/yunohost/hooks.d) + [[ ! -e /etc/yunohost/apps ]] || (chown root /etc/yunohost/apps && chmod 700 /etc/yunohost/apps) + + # Propagates changes in systemd service config overrides + [[ ! "$regen_conf_files" =~ "ntp.service.d/ynh-override.conf" ]] || { systemctl daemon-reload; systemctl restart ntp; } + [[ ! "$regen_conf_files" =~ "nftables.service.d/ynh-override.conf" ]] || systemctl daemon-reload } _update_services() { @@ -74,7 +123,7 @@ with open('services.yml') as f: new_services = yaml.load(f) with open('/etc/yunohost/services.yml') as f: - services = yaml.load(f) + services = yaml.load(f) or {} updated = False @@ -132,6 +181,7 @@ case "$1" in do_pre_regen $4 ;; post) + do_post_regen $4 ;; init) do_init_regen diff --git a/data/hooks/conf_regen/02-ssl b/data/hooks/conf_regen/02-ssl index a893b21e1..310a5d526 100755 --- a/data/hooks/conf_regen/02-ssl +++ b/data/hooks/conf_regen/02-ssl @@ -69,12 +69,11 @@ do_init_regen() { -out "${ssl_dir}/certs/yunohost_crt.pem" \ -batch >>$LOGFILE 2>&1 - last_cert=$(ls $ssl_dir/newcerts/*.pem | sort -V | tail -n 1) chmod 640 "${ssl_dir}/certs/yunohost_key.pem" - chmod 640 "$last_cert" + chmod 640 "${ssl_dir}/certs/yunohost_crt.pem" cp "${ssl_dir}/certs/yunohost_key.pem" "$ynh_key" - cp "$last_cert" "$ynh_crt" + cp "${ssl_dir}/certs/yunohost_crt.pem" "$ynh_crt" ln -sf "$ynh_crt" /etc/ssl/certs/yunohost_crt.pem ln -sf "$ynh_key" /etc/ssl/private/yunohost_key.pem fi diff --git a/data/hooks/conf_regen/06-slapd b/data/hooks/conf_regen/06-slapd index 9b2c20138..9f808b58e 100755 --- a/data/hooks/conf_regen/06-slapd +++ b/data/hooks/conf_regen/06-slapd @@ -12,27 +12,52 @@ do_init_regen() { do_pre_regen "" - # fix some permissions - chown root:openldap /etc/ldap/slapd.conf + systemctl daemon-reload + + _regenerate_slapd_conf + + # Enforce permissions + chown root:openldap /etc/ldap/slapd.ldif chown -R openldap:openldap /etc/ldap/schema/ usermod -aG ssl-cert openldap - # check the slapd config file at first - slaptest -Q -u -f /etc/ldap/slapd.conf - - # regenerate LDAP config directory from slapd.conf - rm -Rf /etc/ldap/slapd.d - mkdir /etc/ldap/slapd.d - slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ 2>&1 - chown -R openldap:openldap /etc/ldap/slapd.d/ - service slapd restart } +_regenerate_slapd_conf() { + + # Validate the new slapd config + # To do so, we have to use the .ldif to generate the config directory + # so we use a temporary directory slapd_new.d + rm -Rf /etc/ldap/slapd_new.d + mkdir /etc/ldap/slapd_new.d + slapadd -n0 -l /etc/ldap/slapd.ldif -F /etc/ldap/slapd_new.d/ 2>&1 + # Actual validation (-Q is for quiet, -u is for dry-run) + slaptest -Q -u -F /etc/ldap/slapd_new.d + + # "Commit" / apply the new config (meaning we delete the old one and replace + # it with the new one) + rm -Rf /etc/ldap/slapd.d + mv /etc/ldap/slapd_new.d /etc/ldap/slapd.d + + chown -R openldap:openldap /etc/ldap/slapd.d/ +} + do_pre_regen() { pending_dir=$1 - cd /usr/share/yunohost/templates/slapd + # remove temporary backup file + rm -f "$tmp_backup_dir_file" + + # Define if we need to migrate from hdb to mdb + curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2>/dev/null | awk '{print $2}') + if [ -e /etc/ldap/slapd.conf ] && [ -n "$curr_backend" ] && \ + [ $curr_backend != 'mdb' ]; then + backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)" + mkdir -p "$backup_dir" + slapcat -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif" + echo "$backup_dir" > "$tmp_backup_dir_file" + fi # create needed directories ldap_dir="${pending_dir}/etc/ldap" @@ -40,28 +65,15 @@ do_pre_regen() { mkdir -p "$ldap_dir" "$schema_dir" # remove legacy configuration file - [ ! -f /etc/ldap/slapd-yuno.conf ] \ - || touch "${pending_dir}/etc/ldap/slapd-yuno.conf" + [ ! -f /etc/ldap/slapd-yuno.conf ] || touch "${ldap_dir}/slapd-yuno.conf" + [ ! -f /etc/ldap/slapd.conf ] || touch "${ldap_dir}/slapd.conf" + [ ! -f /etc/ldap/schema/yunohost.schema ] || touch "${schema_dir}/yunohost.schema" - # remove temporary backup file - rm -f "$tmp_backup_dir_file" - - # retrieve current and new backends - curr_backend=$(grep '^database' /etc/ldap/slapd.conf 2>/dev/null | awk '{print $2}') - new_backend=$(grep '^database' slapd.conf | awk '{print $2}') - - # save current database before any conf changes - if [[ -n "$curr_backend" && "$curr_backend" != "$new_backend" ]]; then - backup_dir="/var/backups/dc=yunohost,dc=org-${curr_backend}-$(date +%s)" - mkdir -p "$backup_dir" - slapcat -b dc=yunohost,dc=org \ - -l "${backup_dir}/dc=yunohost-dc=org.ldif" - echo "$backup_dir" > "$tmp_backup_dir_file" - fi + cd /usr/share/yunohost/templates/slapd # copy configuration files - cp -a ldap.conf slapd.conf "$ldap_dir" - cp -a sudo.schema mailserver.schema yunohost.schema "$schema_dir" + cp -a ldap.conf slapd.ldif "$ldap_dir" + cp -a sudo.ldif mailserver.ldif permission.ldif "$schema_dir" mkdir -p ${pending_dir}/etc/systemd/system/slapd.service.d/ cp systemd-override.conf ${pending_dir}/etc/systemd/system/slapd.service.d/ynh-override.conf @@ -72,19 +84,13 @@ do_pre_regen() { do_post_regen() { regen_conf_files=$1 - # ensure that slapd.d exists - mkdir -p /etc/ldap/slapd.d - # fix some permissions - echo "Making sure we have the right permissions needed ..." + echo "Enforce permissions on ldap/slapd directories and certs ..." # penldap user should be in the ssl-cert group to let it access the certificate for TLS usermod -aG ssl-cert openldap - chown root:openldap /etc/ldap/slapd.conf + chown root:openldap /etc/ldap/slapd.ldif chown -R openldap:openldap /etc/ldap/schema/ chown -R openldap:openldap /etc/ldap/slapd.d/ - chown -R root:ssl-cert /etc/yunohost/certs/yunohost.org/ - chmod o-rwx /etc/yunohost/certs/yunohost.org/ - chmod -R g+rx /etc/yunohost/certs/yunohost.org/ # If we changed the systemd ynh-override conf if echo "$regen_conf_files" | sed 's/,/\n/g' | grep -q "^/etc/systemd/system/slapd.service.d/ynh-override.conf$" @@ -95,29 +101,17 @@ do_post_regen() { [ -z "$regen_conf_files" ] && exit 0 - # check the slapd config file at first - slaptest -Q -u -f /etc/ldap/slapd.conf + # regenerate LDAP config directory from slapd.conf + echo "Regenerate LDAP config directory from slapd.ldif" + _regenerate_slapd_conf - # check if a backup should be restored + # If there's a backup, re-import its data backup_dir=$(cat "$tmp_backup_dir_file" 2>/dev/null || true) if [[ -n "$backup_dir" && -f "${backup_dir}/dc=yunohost-dc=org.ldif" ]]; then # regenerate LDAP config directory and import database as root - # since the admin user may be unavailable - echo "Regenerate LDAP config directory and import the database using slapadd" - sh -c "rm -Rf /etc/ldap/slapd.d; - mkdir /etc/ldap/slapd.d; - slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d; - chown -R openldap:openldap /etc/ldap/slapd.d; - slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org \ - -l '${backup_dir}/dc=yunohost-dc=org.ldif'; - chown -R openldap:openldap /var/lib/ldap" 2>&1 - else - # regenerate LDAP config directory from slapd.conf - echo "Regenerate LDAP config directory from slapd.conf" - rm -Rf /etc/ldap/slapd.d - mkdir /etc/ldap/slapd.d - slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/ 2>&1 - chown -R openldap:openldap /etc/ldap/slapd.d/ + echo "Import the database using slapadd" + slapadd -F /etc/ldap/slapd.d -b dc=yunohost,dc=org -l "${backup_dir}/dc=yunohost-dc=org.ldif" + chown -R openldap:openldap /var/lib/ldap 2>&1 fi echo "Running slapdindex" @@ -157,6 +151,9 @@ case "$1" in init) do_init_regen ;; + apply_config) + do_post_regen /etc/ldap/slapd.ldif + ;; *) echo "hook called with unknown argument \`$1'" >&2 exit 1 diff --git a/data/hooks/conf_regen/10-apt b/data/hooks/conf_regen/10-apt new file mode 100755 index 000000000..4ce838e4c --- /dev/null +++ b/data/hooks/conf_regen/10-apt @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e + +do_pre_regen() { + pending_dir=$1 + + mkdir --parents "${pending_dir}/etc/apt/preferences.d" + + for package in "php" "php-fpm" "php-mysql" "php-xml" "php-zip" "php-mbstring" "php-ldap" "php-gd" "php-curl" "php-bz2" "php-json" "php-sqlite3" "php-intl" "openssl" "libssl1.1" "libssl-dev" + do + echo " +Package: $package +Pin: origin \"packages.sury.org\" +Pin-Priority: -1" >> "/etc/apt/preferences.d/extra_php_version" + done +} + +do_post_regen() { + regen_conf_files=$1 +} + +FORCE=${2:-0} +DRY_RUN=${3:-0} + +case "$1" in + pre) + do_pre_regen $4 + ;; + post) + do_post_regen $4 + ;; + *) + echo "hook called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/data/hooks/conf_regen/12-metronome b/data/hooks/conf_regen/12-metronome index 7e8c7eb0c..31d11555a 100755 --- a/data/hooks/conf_regen/12-metronome +++ b/data/hooks/conf_regen/12-metronome @@ -57,6 +57,9 @@ do_post_regen() { done # fix some permissions + + # metronome should be in ssl-cert group to let it access SSL certificates + usermod -aG ssl-cert metronome chown -R metronome: /var/lib/metronome/ chown -R metronome: /etc/metronome/conf.d/ diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 4924b6f91..a7574b070 100755 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -26,6 +26,9 @@ do_init_regen() { ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc" ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf" + mkdir -p $nginx_conf_dir/default.d/ + cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/ + # Restart nginx if conf looks good, otherwise display error and exit unhappy nginx -t 2>/dev/null || { nginx -t; exit 1; } systemctl restart nginx || { journalctl --no-pager --lines=10 -u nginx >&2; exit 1; } @@ -77,6 +80,8 @@ do_pre_regen() { done ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf" + mkdir -p $nginx_conf_dir/default.d/ + cp "redirect_to_admin.conf" $nginx_conf_dir/default.d/ # remove old domain conf files conf_files=$(ls -1 /etc/nginx/conf.d \ diff --git a/data/hooks/conf_regen/31-rspamd b/data/hooks/conf_regen/31-rspamd index 861549e27..87ed722a7 100755 --- a/data/hooks/conf_regen/31-rspamd +++ b/data/hooks/conf_regen/31-rspamd @@ -42,6 +42,8 @@ do_post_regen() { chown _rspamd /etc/dkim/*.mail.key chmod 400 /etc/dkim/*.mail.key + [ ! -e /var/log/rspamd ] || chown -R _rspamd:_rspamd /var/log/rspamd + regen_conf_files=$1 [ -z "$regen_conf_files" ] && exit 0 diff --git a/data/hooks/conf_regen/34-mysql b/data/hooks/conf_regen/34-mysql index 43f9fdde1..ac2395f34 100755 --- a/data/hooks/conf_regen/34-mysql +++ b/data/hooks/conf_regen/34-mysql @@ -15,6 +15,18 @@ do_pre_regen() { do_post_regen() { regen_conf_files=$1 + # mysql is supposed to be an alias to mariadb... but in some weird case is not + # c.f. https://forum.yunohost.org/t/mysql-ne-fonctionne-pas/11661 + # Playing with enable/disable allows to recreate the proper symlinks. + if [ ! -e /etc/systemd/system/mysql.service ] + then + systemctl stop mysql -q + systemctl disable mysql -q + systemctl disable mariadb -q + systemctl enable mariadb -q + systemctl is-active mariadb -q || systemctl start mariadb + fi + if [ ! -f /etc/yunohost/mysql ]; then # ensure that mysql is running diff --git a/data/hooks/conf_regen/40-glances b/data/hooks/conf_regen/40-glances deleted file mode 100755 index 70b8f4b5a..000000000 --- a/data/hooks/conf_regen/40-glances +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -set -e - -do_pre_regen() { - pending_dir=$1 - - cd /usr/share/yunohost/templates/glances - - install -D -m 644 glances.default "${pending_dir}/etc/default/glances" -} - -do_post_regen() { - regen_conf_files=$1 - - [[ -z "$regen_conf_files" ]] \ - || service glances restart -} - -FORCE=${2:-0} -DRY_RUN=${3:-0} - -case "$1" in - pre) - do_pre_regen $4 - ;; - post) - do_post_regen $4 - ;; - *) - echo "hook called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/data/hooks/conf_regen/43-dnsmasq b/data/hooks/conf_regen/43-dnsmasq index 8a2985f34..e7b0531e8 100755 --- a/data/hooks/conf_regen/43-dnsmasq +++ b/data/hooks/conf_regen/43-dnsmasq @@ -27,14 +27,13 @@ do_pre_regen() { ipv6=$(curl -s -6 https://ip6.yunohost.org 2>/dev/null || true) ynh_validate_ip6 "$ipv6" || ipv6='' + export ipv4 + export ipv6 + # add domain conf files for domain in $YNH_DOMAINS; do - cat domain.tpl \ - | sed "s/{{ domain }}/${domain}/g" \ - | sed "s/{{ ip }}/${ipv4}/g" \ - > "${dnsmasq_dir}/${domain}" - [[ -n $ipv6 ]] \ - && echo "address=/${domain}/${ipv6}" >> "${dnsmasq_dir}/${domain}" + export domain + ynh_render_template "domain.tpl" "${dnsmasq_dir}/${domain}" done # remove old domain conf files @@ -64,8 +63,21 @@ do_post_regen() { systemctl restart resolvconf fi - [[ -z "$regen_conf_files" ]] \ - || service dnsmasq restart + # Some stupid things like rabbitmq-server used by onlyoffice won't work if + # the *short* hostname doesn't exists in /etc/hosts -_- + short_hostname=$(hostname -s) + grep -q "127.0.0.1.*$short_hostname" /etc/hosts || echo -e "\n127.0.0.1\t$short_hostname" >>/etc/hosts + + [[ -n "$regen_conf_files" ]] || return + + # Remove / disable services likely to conflict with dnsmasq + for SERVICE in systemd-resolved bind9 + do + systemctl is-enabled $SERVICE &>/dev/null && systemctl disable $SERVICE 2>/dev/null + systemctl is-active $SERVICE &>/dev/null && systemctl stop $SERVICE + done + + systemctl restart dnsmasq } FORCE=${2:-0} diff --git a/data/hooks/diagnosis/00-basesystem.py b/data/hooks/diagnosis/00-basesystem.py index 51926924a..8773f8b53 100644 --- a/data/hooks/diagnosis/00-basesystem.py +++ b/data/hooks/diagnosis/00-basesystem.py @@ -1,9 +1,11 @@ #!/usr/bin/env python import os +import json +import subprocess from moulinette.utils.process import check_output -from moulinette.utils.filesystem import read_file +from moulinette.utils.filesystem import read_file, read_json, write_to_json from yunohost.diagnosis import Diagnoser from yunohost.utils.packages import ynh_packages_version @@ -32,7 +34,7 @@ class BaseSystemDiagnoser(Diagnoser): # Also possibly the board name if os.path.exists("/proc/device-tree/model"): - model = read_file('/proc/device-tree/model').strip() + model = read_file('/proc/device-tree/model').strip().replace('\x00', '') hardware["data"]["model"] = model hardware["details"] = ["diagnosis_basesystem_hardware_board"] @@ -61,10 +63,10 @@ class BaseSystemDiagnoser(Diagnoser): ynh_core_version = ynh_packages["yunohost"]["version"] consistent_versions = all(infos["version"][:3] == ynh_core_version[:3] for infos in ynh_packages.values()) ynh_version_details = [("diagnosis_basesystem_ynh_single_version", - {"package":package, + {"package": package, "version": infos["version"], "repo": infos["repo"]} - ) + ) for package, infos in ynh_packages.items()] yield dict(meta={"test": "ynh_versions"}, @@ -73,6 +75,75 @@ class BaseSystemDiagnoser(Diagnoser): summary="diagnosis_basesystem_ynh_main_version" if consistent_versions else "diagnosis_basesystem_ynh_inconsistent_versions", details=ynh_version_details) + if self.is_vulnerable_to_meltdown(): + yield dict(meta={"test": "meltdown"}, + status="ERROR", + summary="diagnosis_security_vulnerable_to_meltdown", + details=["diagnosis_security_vulnerable_to_meltdown_details"] + ) + + def is_vulnerable_to_meltdown(self): + # meltdown CVE: https://security-tracker.debian.org/tracker/CVE-2017-5754 + + # We use a cache file to avoid re-running the script so many times, + # which can be expensive (up to around 5 seconds on ARM) + # and make the admin appear to be slow (c.f. the calls to diagnosis + # from the webadmin) + # + # The cache is in /tmp and shall disappear upon reboot + # *or* we compare it to dpkg.log modification time + # such that it's re-ran if there was package upgrades + # (e.g. from yunohost) + cache_file = "/tmp/yunohost-meltdown-diagnosis" + dpkg_log = "/var/log/dpkg.log" + if os.path.exists(cache_file): + if not os.path.exists(dpkg_log) or os.path.getmtime(cache_file) > os.path.getmtime(dpkg_log): + self.logger_debug("Using cached results for meltdown checker, from %s" % cache_file) + return read_json(cache_file)[0]["VULNERABLE"] + + # script taken from https://github.com/speed47/spectre-meltdown-checker + # script commit id is store directly in the script + SCRIPT_PATH = "/usr/lib/moulinette/yunohost/vendor/spectre-meltdown-checker/spectre-meltdown-checker.sh" + + # '--variant 3' corresponds to Meltdown + # example output from the script: + # [{"NAME":"MELTDOWN","CVE":"CVE-2017-5754","VULNERABLE":false,"INFOS":"PTI mitigates the vulnerability"}] + try: + self.logger_debug("Running meltdown vulnerability checker") + call = subprocess.Popen("bash %s --batch json --variant 3" % + SCRIPT_PATH, shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + # TODO / FIXME : here we are ignoring error messages ... + # in particular on RPi2 and other hardware, the script complains about + # "missing some kernel info (see -v), accuracy might be reduced" + # Dunno what to do about that but we probably don't want to harass + # users with this warning ... + output, err = call.communicate() + assert call.returncode in (0, 2, 3), "Return code: %s" % call.returncode + + # If there are multiple lines, sounds like there was some messages + # in stdout that are not json >.> ... Try to get the actual json + # stuff which should be the last line + output = output.strip() + if "\n" in output: + self.logger_debug("Original meltdown checker output : %s" % output) + output = output.split("\n")[-1] + + CVEs = json.loads(output) + assert len(CVEs) == 1 + assert CVEs[0]["NAME"] == "MELTDOWN" + except Exception as e: + import traceback + traceback.print_exc() + self.logger_warning("Something wrong happened when trying to diagnose Meltdown vunerability, exception: %s" % e) + raise Exception("Command output for failed meltdown check: '%s'" % output) + + self.logger_debug("Writing results from meltdown checker to cache file, %s" % cache_file) + write_to_json(cache_file, CVEs) + return CVEs[0]["VULNERABLE"] + def main(args, env, loggers): return BaseSystemDiagnoser(args, env, loggers).diagnose() diff --git a/data/hooks/diagnosis/10-ip.py b/data/hooks/diagnosis/10-ip.py index fe4993935..b18b4f435 100644 --- a/data/hooks/diagnosis/10-ip.py +++ b/data/hooks/diagnosis/10-ip.py @@ -108,7 +108,7 @@ class IPDiagnoser(Diagnoser): return False # If we are indeed connected in ipv4 or ipv6, we should find a default route - routes = check_output("ip -%s route" % protocol).split("\n") + routes = check_output("ip -%s route show table all" % protocol).split("\n") def is_default_route(r): # Typically the default route starts with "default" diff --git a/data/hooks/diagnosis/12-dnsrecords.py b/data/hooks/diagnosis/12-dnsrecords.py index 560127bb0..91dec7006 100644 --- a/data/hooks/diagnosis/12-dnsrecords.py +++ b/data/hooks/diagnosis/12-dnsrecords.py @@ -12,9 +12,7 @@ from yunohost.utils.network import dig from yunohost.diagnosis import Diagnoser from yunohost.domain import domain_list, _build_dns_conf, _get_maindomain -# We put here domains we know has dyndns provider, but that are not yet -# registered in the public suffix list -PENDING_SUFFIX_LIST = ['ynh.fr', 'netlib.re'] +YNH_DYNDNS_DOMAINS = ['nohost.me', 'noho.st', 'ynh.fr'] class DNSRecordsDiagnoser(Diagnoser): @@ -38,7 +36,7 @@ class DNSRecordsDiagnoser(Diagnoser): psl = PublicSuffixList() domains_from_registrar = [psl.get_public_suffix(domain) for domain in all_domains] domains_from_registrar = [domain for domain in domains_from_registrar if "." in domain] - domains_from_registrar = set(domains_from_registrar) - set(PENDING_SUFFIX_LIST) + domains_from_registrar = set(domains_from_registrar) - set(YNH_DYNDNS_DOMAINS + ["netlib.re"]) for report in self.check_expiration_date(domains_from_registrar): yield report @@ -100,7 +98,13 @@ class DNSRecordsDiagnoser(Diagnoser): summary=summary) if discrepancies: - output["details"] = ["diagnosis_dns_point_to_doc"] + discrepancies + # For ynh-managed domains (nohost.me etc...), tell people to try to "yunohost dyndns update --force" + if any(domain.endswith(ynh_dyndns_domain) for ynh_dyndns_domain in YNH_DYNDNS_DOMAINS): + output["details"] = ["diagnosis_dns_try_dyndns_update_force"] + # Otherwise point to the documentation + else: + output["details"] = ["diagnosis_dns_point_to_doc"] + output["details"] += discrepancies yield output diff --git a/data/hooks/diagnosis/14-ports.py b/data/hooks/diagnosis/14-ports.py index bd68c60d6..b74b3907e 100644 --- a/data/hooks/diagnosis/14-ports.py +++ b/data/hooks/diagnosis/14-ports.py @@ -3,9 +3,9 @@ import os from yunohost.diagnosis import Diagnoser -from yunohost.utils.error import YunohostError from yunohost.service import _get_services + class PortsDiagnoser(Diagnoser): id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] @@ -87,7 +87,7 @@ class PortsDiagnoser(Diagnoser): # If any AAAA record is set, IPv6 is important... def ipv6_is_important(): dnsrecords = Diagnoser.get_cached_report("dnsrecords") or {} - return any(record["data"]["AAAA:@"] in ["OK", "WRONG"] for record in dnsrecords.get("items", [])) + return any(record["data"].get("AAAA:@") in ["OK", "WRONG"] for record in dnsrecords.get("items", [])) if failed == 4 or ipv6_is_important(): yield dict(meta={"port": port}, diff --git a/data/hooks/diagnosis/21-web.py b/data/hooks/diagnosis/21-web.py index c1f6d912a..94665a6e6 100644 --- a/data/hooks/diagnosis/21-web.py +++ b/data/hooks/diagnosis/21-web.py @@ -8,7 +8,6 @@ from moulinette.utils.filesystem import read_file from yunohost.diagnosis import Diagnoser from yunohost.domain import domain_list -from yunohost.utils.error import YunohostError DIAGNOSIS_SERVER = "diagnosis.yunohost.org" diff --git a/data/hooks/diagnosis/24-mail.py b/data/hooks/diagnosis/24-mail.py index bc159c3b7..fca9345ab 100644 --- a/data/hooks/diagnosis/24-mail.py +++ b/data/hooks/diagnosis/24-mail.py @@ -47,7 +47,6 @@ class MailDiagnoser(Diagnoser): status="SUCCESS", summary="diagnosis_mail_" + name + "_ok") - def check_outgoing_port_25(self): """ Check outgoing port 25 is open and not blocked by router @@ -64,7 +63,6 @@ class MailDiagnoser(Diagnoser): details=["diagnosis_mail_outgoing_port_25_blocked_details", "diagnosis_mail_outgoing_port_25_blocked_relay_vpn"]) - def check_ehlo(self): """ Check the server is reachable from outside and it's the good one @@ -99,7 +97,6 @@ class MailDiagnoser(Diagnoser): summary="diagnosis_mail_ehlo_wrong", details=["diagnosis_mail_ehlo_wrong_details"]) - def check_fcrdns(self): """ Check the reverse DNS is well defined by doing a Forward-confirmed @@ -126,7 +123,7 @@ class MailDiagnoser(Diagnoser): query += '.ip6.arpa' # Do the DNS Query - status, value = dig(query, 'PTR') + status, value = dig(query, 'PTR', resolvers="force_external") if status == "nok": yield dict(meta={"test": "mail_fcrdns", "ipversion": ipversion}, data={"ip": ip, "ehlo_domain": self.ehlo_domain}, @@ -148,7 +145,6 @@ class MailDiagnoser(Diagnoser): summary="diagnosis_mail_fcrdns_different_from_ehlo_domain", details=details) - def check_blacklist(self): """ Check with dig onto blacklist DNS server @@ -225,7 +221,6 @@ class MailDiagnoser(Diagnoser): status="SUCCESS", summary="diagnosis_mail_queue_ok") - def get_ips_checked(self): outgoing_ipversions = [] outgoing_ips = [] @@ -245,5 +240,6 @@ class MailDiagnoser(Diagnoser): outgoing_ips.append(global_ipv6) return (outgoing_ipversions, outgoing_ips) + def main(args, env, loggers): return MailDiagnoser(args, env, loggers).diagnose() diff --git a/data/hooks/diagnosis/30-services.py b/data/hooks/diagnosis/30-services.py index 6217d89d3..562d48d6d 100644 --- a/data/hooks/diagnosis/30-services.py +++ b/data/hooks/diagnosis/30-services.py @@ -5,6 +5,7 @@ import os from yunohost.diagnosis import Diagnoser from yunohost.service import service_status + class ServicesDiagnoser(Diagnoser): id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] @@ -21,7 +22,7 @@ class ServicesDiagnoser(Diagnoser): data={"status": result["status"], "configuration": result["configuration"]}) if result["status"] != "running": - item["status"] = "ERROR" + item["status"] = "ERROR" if result["status"] != "unknown" else "WARNING" item["summary"] = "diagnosis_services_bad_status" item["details"] = ["diagnosis_services_bad_status_tip"] @@ -36,5 +37,6 @@ class ServicesDiagnoser(Diagnoser): yield item + def main(args, env, loggers): return ServicesDiagnoser(args, env, loggers).diagnose() diff --git a/data/hooks/diagnosis/50-systemresources.py b/data/hooks/diagnosis/50-systemresources.py index 66d27866a..f0fac4974 100644 --- a/data/hooks/diagnosis/50-systemresources.py +++ b/data/hooks/diagnosis/50-systemresources.py @@ -1,9 +1,13 @@ #!/usr/bin/env python import os import psutil +import subprocess +import datetime +import re from yunohost.diagnosis import Diagnoser + class SystemResourcesDiagnoser(Diagnoser): id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] @@ -13,7 +17,7 @@ class SystemResourcesDiagnoser(Diagnoser): def run(self): MB = 1024**2 - GB = MB*1024 + GB = MB * 1024 # # RAM @@ -45,14 +49,15 @@ class SystemResourcesDiagnoser(Diagnoser): item = dict(meta={"test": "swap"}, data={"total": human_size(swap.total), "recommended": "512 MiB"}) if swap.total <= 1 * MB: - item["status"] = "ERROR" + item["status"] = "INFO" item["summary"] = "diagnosis_swap_none" - elif swap.total < 500 * MB: - item["status"] = "WARNING" + elif swap.total < 450 * MB: + item["status"] = "INFO" item["summary"] = "diagnosis_swap_notsomuch" else: item["status"] = "SUCCESS" item["summary"] = "diagnosis_swap_ok" + item["details"] = ["diagnosis_swap_tip"] yield item # FIXME : add a check that swapiness is low if swap is on a sdcard... @@ -75,7 +80,7 @@ class SystemResourcesDiagnoser(Diagnoser): # N.B.: we do not use usage.total because we want # to take into account the 5% security margin # correctly (c.f. the doc of psutil ...) - "total": human_size(usage.used+usage.free), + "total": human_size(usage.used + usage.free), "free": human_size(usage.free), "free_percent": free_percent}) @@ -92,13 +97,54 @@ class SystemResourcesDiagnoser(Diagnoser): item["status"] = "SUCCESS" item["summary"] = "diagnosis_diskusage_ok" - yield item + # + # Recent kills by oom_reaper + # + + kills_count = self.recent_kills_by_oom_reaper() + if kills_count: + kills_summary = "\n".join(["%s (x%s)" % (proc, count) for proc, count in kills_count]) + + yield dict(meta={"test": "oom_reaper"}, + status="WARNING", + summary="diagnosis_processes_killed_by_oom_reaper", + data={"kills_summary": kills_summary}) + + def recent_kills_by_oom_reaper(self): + if not os.path.exists("/var/log/kern.log"): + return [] + + def analyzed_kern_log(): + + cmd = 'tail -n 10000 /var/log/kern.log | grep "oom_reaper: reaped process" || true' + out = subprocess.check_output(cmd, shell=True).strip() + lines = out.split("\n") if out else [] + + now = datetime.datetime.now() + + for line in reversed(lines): + # Lines look like : + # Aug 25 18:48:21 yolo kernel: [ 9623.613667] oom_reaper: reaped process 11509 (uwsgi), now anon-rss:0kB, file-rss:0kB, shmem-rss:328kB + date_str = str(now.year) + " " + " ".join(line.split()[:3]) + date = datetime.datetime.strptime(date_str, '%Y %b %d %H:%M:%S') + diff = now - date + if diff.days >= 1: + break + process_killed = re.search(r"\(.*\)", line).group().strip("()") + yield process_killed + + processes = list(analyzed_kern_log()) + kills_count = [(p, len([p_ for p_ in processes if p_ == p])) for p in set(processes)] + kills_count = sorted(kills_count, key=lambda p: p[1], reverse=True) + + return kills_count + def human_size(bytes_): # Adapted from https://stackoverflow.com/a/1094933 - for unit in ['','ki','Mi','Gi','Ti','Pi','Ei','Zi']: + for unit in ['', 'ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: if abs(bytes_) < 1024.0: return "%s %sB" % (round_(bytes_), unit) bytes_ /= 1024.0 @@ -113,5 +159,6 @@ def round_(n): n = int(round(n)) return n + def main(args, env, loggers): return SystemResourcesDiagnoser(args, env, loggers).diagnose() diff --git a/data/hooks/diagnosis/70-regenconf.py b/data/hooks/diagnosis/70-regenconf.py index 0dff71b5b..396f64a0f 100644 --- a/data/hooks/diagnosis/70-regenconf.py +++ b/data/hooks/diagnosis/70-regenconf.py @@ -2,7 +2,6 @@ import os -import subprocess from yunohost.diagnosis import Diagnoser from yunohost.regenconf import _get_regenconf_infos, _calculate_hash diff --git a/data/hooks/diagnosis/90-security.py b/data/hooks/diagnosis/90-security.py deleted file mode 100644 index d281042b0..000000000 --- a/data/hooks/diagnosis/90-security.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python - -import os -import json -import subprocess - -from yunohost.diagnosis import Diagnoser -from moulinette.utils.filesystem import read_json, write_to_json - - -class SecurityDiagnoser(Diagnoser): - - id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] - cache_duration = 3600 - dependencies = [] - - def run(self): - - "CVE-2017-5754" - - if self.is_vulnerable_to_meltdown(): - yield dict(meta={"test": "meltdown"}, - status="ERROR", - summary="diagnosis_security_vulnerable_to_meltdown", - details=["diagnosis_security_vulnerable_to_meltdown_details"] - ) - else: - yield dict(meta={}, - status="SUCCESS", - summary="diagnosis_security_all_good" - ) - - - def is_vulnerable_to_meltdown(self): - # meltdown CVE: https://security-tracker.debian.org/tracker/CVE-2017-5754 - - # We use a cache file to avoid re-running the script so many times, - # which can be expensive (up to around 5 seconds on ARM) - # and make the admin appear to be slow (c.f. the calls to diagnosis - # from the webadmin) - # - # The cache is in /tmp and shall disappear upon reboot - # *or* we compare it to dpkg.log modification time - # such that it's re-ran if there was package upgrades - # (e.g. from yunohost) - cache_file = "/tmp/yunohost-meltdown-diagnosis" - dpkg_log = "/var/log/dpkg.log" - if os.path.exists(cache_file): - if not os.path.exists(dpkg_log) or os.path.getmtime(cache_file) > os.path.getmtime(dpkg_log): - self.logger_debug("Using cached results for meltdown checker, from %s" % cache_file) - return read_json(cache_file)[0]["VULNERABLE"] - - # script taken from https://github.com/speed47/spectre-meltdown-checker - # script commit id is store directly in the script - SCRIPT_PATH = "/usr/lib/moulinette/yunohost/vendor/spectre-meltdown-checker/spectre-meltdown-checker.sh" - - # '--variant 3' corresponds to Meltdown - # example output from the script: - # [{"NAME":"MELTDOWN","CVE":"CVE-2017-5754","VULNERABLE":false,"INFOS":"PTI mitigates the vulnerability"}] - try: - self.logger_debug("Running meltdown vulnerability checker") - call = subprocess.Popen("bash %s --batch json --variant 3" % - SCRIPT_PATH, shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - - # TODO / FIXME : here we are ignoring error messages ... - # in particular on RPi2 and other hardware, the script complains about - # "missing some kernel info (see -v), accuracy might be reduced" - # Dunno what to do about that but we probably don't want to harass - # users with this warning ... - output, err = call.communicate() - assert call.returncode in (0, 2, 3), "Return code: %s" % call.returncode - - # If there are multiple lines, sounds like there was some messages - # in stdout that are not json >.> ... Try to get the actual json - # stuff which should be the last line - output = output.strip() - if "\n" in output: - self.logger_debug("Original meltdown checker output : %s" % output) - output = output.split("\n")[-1] - - CVEs = json.loads(output) - assert len(CVEs) == 1 - assert CVEs[0]["NAME"] == "MELTDOWN" - except Exception as e: - import traceback - traceback.print_exc() - self.logger_warning("Something wrong happened when trying to diagnose Meltdown vunerability, exception: %s" % e) - raise Exception("Command output for failed meltdown check: '%s'" % output) - - self.logger_debug("Writing results from meltdown checker to cache file, %s" % cache_file) - write_to_json(cache_file, CVEs) - return CVEs[0]["VULNERABLE"] - - -def main(args, env, loggers): - return SecurityDiagnoser(args, env, loggers).diagnose() diff --git a/data/hooks/restore/05-conf_ldap b/data/hooks/restore/05-conf_ldap index 74093136d..bdc1ebcdf 100644 --- a/data/hooks/restore/05-conf_ldap +++ b/data/hooks/restore/05-conf_ldap @@ -39,6 +39,9 @@ else # Restore the configuration mv /etc/ldap/slapd.d "$TMPDIR" mkdir -p /etc/ldap/slapd.d + cp -a "${backup_dir}/ldap.conf" /etc/ldap/ldap.conf + cp -a "${backup_dir}/slapd.ldif" /etc/ldap/slapd.ldif + # Legacy thing but we need it to force the regen-conf in case of it exist cp -a "${backup_dir}/slapd.conf" /etc/ldap/slapd.conf slapadd -F /etc/ldap/slapd.d -b cn=config \ -l "${backup_dir}/cn=config.master.ldif" \ diff --git a/data/hooks/restore/11-conf_ynh_mysql b/data/hooks/restore/11-conf_ynh_mysql index f54641d6f..11353425a 100644 --- a/data/hooks/restore/11-conf_ynh_mysql +++ b/data/hooks/restore/11-conf_ynh_mysql @@ -1,42 +1,5 @@ -backup_dir="$1/conf/ynh/mysql" -MYSQL_PKG="$(dpkg --list | sed -ne 's/^ii \(mariadb-server-[[:digit:].]\+\) .*$/\1/p')" +# We don't backup/restore mysql password anymore +# c.f. https://github.com/YunoHost/yunohost/pull/912 -. /usr/share/yunohost/helpers - -# ensure that mysql is running -service mysql status >/dev/null 2>&1 \ - || service mysql start - -# retrieve current and new password -[ -f /etc/yunohost/mysql ] \ - && curr_pwd=$(cat /etc/yunohost/mysql) -new_pwd=$(cat "${backup_dir}/root_pwd" || cat "${backup_dir}/mysql") -[ -z "$curr_pwd" ] && curr_pwd="yunohost" -[ -z "$new_pwd" ] && { - new_pwd=$(ynh_string_random 10) -} - -# attempt to change it -mysqladmin -s -u root -p"$curr_pwd" password "$new_pwd" || { - - echo "It seems that you have already configured MySQL." \ - "YunoHost needs to have a root access to MySQL to runs its" \ - "applications, and is going to reset the MySQL root password." \ - "You can find this new password in /etc/yunohost/mysql." >&2 - - # set new password with debconf - debconf-set-selections << EOF -$MYSQL_PKG mysql-server/root_password password $new_pwd -$MYSQL_PKG mysql-server/root_password_again password $new_pwd -EOF - - # reconfigure Debian package - dpkg-reconfigure -freadline -u "$MYSQL_PKG" 2>&1 -} - -# store new root password -echo "$new_pwd" | tee /etc/yunohost/mysql -chmod 400 /etc/yunohost/mysql - -# reload the grant tables -mysqladmin -s -u root -p"$new_pwd" reload +# This is a dummy empty file as a workaround for +# https://github.com/YunoHost/issues/issues/1553 until it is fixed diff --git a/data/other/ffdhe2048.pem b/data/other/ffdhe2048.pem new file mode 100644 index 000000000..9b182b720 --- /dev/null +++ b/data/other/ffdhe2048.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== +-----END DH PARAMETERS----- diff --git a/data/templates/dnsmasq/domain.tpl b/data/templates/dnsmasq/domain.tpl index bbfc2864c..f4c8d6c4c 100644 --- a/data/templates/dnsmasq/domain.tpl +++ b/data/templates/dnsmasq/domain.tpl @@ -1,4 +1,9 @@ -address=/{{ domain }}/{{ ip }} +address=/{{ domain }}/{{ ipv4 }} +address=/xmpp-upload.{{ domain }}/{{ ipv4 }} +{% if ipv6 %} +address=/{{ domain }}/{{ ipv6 }} +address=/xmpp-upload.{{ domain }}/{{ ipv6 }} +{% endif %} txt-record={{ domain }},"v=spf1 mx a -all" mx-host={{ domain }},{{ domain }},5 srv-host=_xmpp-client._tcp.{{ domain }},{{ domain }},5222,0,5 diff --git a/data/templates/dovecot/dovecot.conf b/data/templates/dovecot/dovecot.conf index 8fc0e75ae..ee8511f83 100644 --- a/data/templates/dovecot/dovecot.conf +++ b/data/templates/dovecot/dovecot.conf @@ -14,18 +14,19 @@ mail_plugins = $mail_plugins quota ############################################################################### -# generated 2020-04-03, Mozilla Guideline v5.4, Dovecot 2.2.27, OpenSSL 1.1.0l, intermediate configuration -# https://ssl-config.mozilla.org/#server=dovecot&version=2.2.27&config=intermediate&openssl=1.1.0l&guideline=5.4 +# generated 2020-08-18, Mozilla Guideline v5.6, Dovecot 2.3.4, OpenSSL 1.1.1d, intermediate configuration +# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.4&config=intermediate&openssl=1.1.1d&guideline=5.6 ssl = required ssl_cert = /path/to/dhparam +ssl_dh = openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048 -#ssl_dhparam /etc/ssl/private/dh2048.pem; +# Pre-defined FFDHE group (RFC 7919) +# From https://ssl-config.mozilla.org/ffdhe2048.txt +# https://security.stackexchange.com/a/149818 +ssl_dhparam /usr/share/yunohost/other/ffdhe2048.pem; +{% endif %} + # Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners # https://wiki.mozilla.org/Security/Guidelines/Web_Security # https://observatory.mozilla.org/ more_set_headers "Content-Security-Policy : upgrade-insecure-requests"; -more_set_headers "Content-Security-Policy-Report-Only : default-src https: data: 'unsafe-inline' 'unsafe-eval'"; +more_set_headers "Content-Security-Policy-Report-Only : default-src https: data: 'unsafe-inline' 'unsafe-eval' "; more_set_headers "X-Content-Type-Options : nosniff"; more_set_headers "X-XSS-Protection : 1; mode=block"; more_set_headers "X-Download-Options : noopen"; diff --git a/data/templates/nginx/server.tpl.conf b/data/templates/nginx/server.tpl.conf index 29af9f532..8bd689a92 100644 --- a/data/templates/nginx/server.tpl.conf +++ b/data/templates/nginx/server.tpl.conf @@ -14,7 +14,7 @@ server { include /etc/nginx/conf.d/{{ domain }}.d/*.conf; - location /yunohost/admin { + location /yunohost { return 301 https://$http_host$request_uri; } @@ -60,6 +60,7 @@ server { include /etc/nginx/conf.d/{{ domain }}.d/*.conf; + include /etc/nginx/conf.d/yunohost_sso.conf.inc; include /etc/nginx/conf.d/yunohost_admin.conf.inc; include /etc/nginx/conf.d/yunohost_api.conf.inc; diff --git a/data/templates/nginx/yunohost_admin.conf b/data/templates/nginx/yunohost_admin.conf index 3df838c4a..8a7a40231 100644 --- a/data/templates/nginx/yunohost_admin.conf +++ b/data/templates/nginx/yunohost_admin.conf @@ -2,13 +2,7 @@ server { listen 80 default_server; listen [::]:80 default_server; - location / { - return 302 https://$http_host/yunohost/admin; - } - - location /yunohost/admin { - return 301 https://$http_host$request_uri; - } + include /etc/nginx/conf.d/default.d/*.conf; } server { @@ -22,23 +16,13 @@ server { more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload"; more_set_headers "Referrer-Policy : 'same-origin'"; - more_set_headers "Content-Security-Policy : upgrade-insecure-requests; object-src 'none'; script-src https: 'unsafe-eval'"; - - location / { - return 302 https://$http_host/yunohost/admin; - } location /yunohost { - # Block crawlers bot - if ($http_user_agent ~ (crawl|Googlebot|Slurp|spider|bingbot|tracker|click|parser|spider|facebookexternalhit) ) { - return 403; - } - # X-Robots-Tag to precise the rules applied. - add_header X-Robots-Tag "nofollow, noindex, noarchive, nosnippet"; # Redirect most of 404 to maindomain.tld/yunohost/sso access_by_lua_file /usr/share/ssowat/access.lua; } include /etc/nginx/conf.d/yunohost_admin.conf.inc; include /etc/nginx/conf.d/yunohost_api.conf.inc; + include /etc/nginx/conf.d/default.d/*.conf; } diff --git a/data/templates/nslcd/nslcd.conf b/data/templates/nslcd/nslcd.conf index 091ecb7cc..7cfe73e07 100644 --- a/data/templates/nslcd/nslcd.conf +++ b/data/templates/nslcd/nslcd.conf @@ -15,6 +15,18 @@ base dc=yunohost,dc=org # The LDAP protocol version to use. #ldap_version 3 +# The DN to bind with for normal lookups. +#binddn cn=annonymous,dc=example,dc=net +#bindpw secret + +# The DN used for password modifications by root. +#rootpwmoddn cn=admin,dc=example,dc=com + +# SSL options +#ssl off +#tls_reqcert never +tls_cacertfile /etc/ssl/certs/ca-certificates.crt + # The search scope. #scope sub diff --git a/data/templates/nsswitch/nsswitch.conf b/data/templates/nsswitch/nsswitch.conf index b55e01b02..8f46e4f5d 100644 --- a/data/templates/nsswitch/nsswitch.conf +++ b/data/templates/nsswitch/nsswitch.conf @@ -1,12 +1,8 @@ # /etc/nsswitch.conf -# -# Example configuration of GNU Name Service Switch functionality. -# If you have the `glibc-doc-reference' and `info' packages installed, try: -# `info libc "Name Service Switch"' for information about this file. -passwd: compat ldap -group: compat ldap -shadow: compat ldap +passwd: files systemd ldap +group: files systemd ldap +shadow: files ldap gshadow: files hosts: files myhostname mdns4_minimal [NOTFOUND=return] dns diff --git a/data/templates/postfix/main.cf b/data/templates/postfix/main.cf index 4d27498c4..61aa27211 100644 --- a/data/templates/postfix/main.cf +++ b/data/templates/postfix/main.cf @@ -19,34 +19,35 @@ readme_directory = no # -- TLS for incoming connections ############################################################################### -# generated 2020-04-03, Mozilla Guideline v5.4, Postfix 3.1.14, OpenSSL 1.1.0l, intermediate configuration -# https://ssl-config.mozilla.org/#server=postfix&version=3.1.14&config=intermediate&openssl=1.1.0l&guideline=5.4 - -# (No modern conf support until we're on buster...) -# {% if compatibility == "intermediate" %} {% else %} {% endif %} - smtpd_use_tls = yes smtpd_tls_security_level = may smtpd_tls_auth_only = yes smtpd_tls_cert_file = /etc/yunohost/certs/{{ main_domain }}/crt.pem smtpd_tls_key_file = /etc/yunohost/certs/{{ main_domain }}/key.pem + +{% if compatibility == "intermediate" %} +# generated 2020-08-18, Mozilla Guideline v5.6, Postfix 3.4.14, OpenSSL 1.1.1d, intermediate configuration +# https://ssl-config.mozilla.org/#server=postfix&version=3.4.14&config=intermediate&openssl=1.1.1d&guideline=5.6 + smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 -# smtpd_tls_mandatory_ciphers = medium # (c.f. below) +smtpd_tls_mandatory_ciphers = medium # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem # not actually 1024 bits, this applies to all DHE >= 1024 bits -# smtpd_tls_dh1024_param_file = /path/to/dhparam.pem +smtpd_tls_dh1024_param_file = /usr/share/yunohost/other/ffdhe2048.pem + +tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 +{% else %} +# generated 2020-08-18, Mozilla Guideline v5.6, Postfix 3.4.14, OpenSSL 1.1.1d, modern configuration +# https://ssl-config.mozilla.org/#server=postfix&version=3.4.14&config=modern&openssl=1.1.1d&guideline=5.6 + +smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2 +smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1, !TLSv1.2 +{% endif %} -# This custom medium cipherlist recommendation only works if we have a DH ... which we don't, c.f. https://github.com/YunoHost/issues/issues/93 -# On the other hand, the postfix doc strongly discourage tweaking this list ... So whatever, let's keep the mandatory_ciphers to high like we did before applying the Mozilla recommendation ... -#tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 tls_preempt_cipherlist = no - -# Custom Yunohost stuff ... because we can't use the recommendation about medium cipher list ... -smtpd_tls_mandatory_ciphers=high -smtpd_tls_eecdh_grade = ultra ############################################################################### smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache smtpd_tls_loglevel=1 @@ -178,7 +179,7 @@ smtpd_milters = inet:localhost:11332 milter_default_action = accept # Avoid to send simultaneously too many emails -smtp_destination_concurrency_limit = 1 +smtp_destination_concurrency_limit = 2 default_destination_rate_delay = 5s # Avoid email adress scanning diff --git a/data/templates/slapd/mailserver.schema b/data/templates/slapd/mailserver.ldif similarity index 79% rename from data/templates/slapd/mailserver.schema rename to data/templates/slapd/mailserver.ldif index 23d0d24bd..849d1d9e1 100644 --- a/data/templates/slapd/mailserver.schema +++ b/data/templates/slapd/mailserver.ldif @@ -2,58 +2,62 @@ ## Version 0.1 ## Adrien Beudin +dn: cn=mailserver,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: mailserver +# # Attributes -attributetype ( 1.3.6.1.4.1.40328.1.20.2.1 +olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.1 NAME 'maildrop' DESC 'Mail addresses where mails are forwarded -- ie forwards' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) - -attributetype ( 1.3.6.1.4.1.40328.1.20.2.2 +# +olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.2 NAME 'mailalias' DESC 'Mail addresses accepted by this account -- ie aliases' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) - -attributetype ( 1.3.6.1.4.1.40328.1.20.2.3 +# +olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.3 NAME 'mailenable' DESC 'Mail Account validity' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{8}) - -attributetype ( 1.3.6.1.4.1.40328.1.20.2.4 +# +olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.4 NAME 'mailbox' DESC 'Mailbox path where mails are delivered' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) - -attributetype ( 1.3.6.1.4.1.40328.1.20.2.5 +# +olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.5 NAME 'virtualdomain' DESC 'A mail domain name' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) - -attributetype ( 1.3.6.1.4.1.40328.1.20.2.6 +# +olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.6 NAME 'virtualdomaindescription' DESC 'Virtual domain description' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}) - -attributetype ( 1.3.6.1.4.1.40328.1.20.2.7 +# +olcAttributeTypes: ( 1.3.6.1.4.1.40328.1.20.2.7 NAME 'mailuserquota' DESC 'Mailbox quota for a user' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} SINGLE-VALUE ) - +# # Mail Account Objectclass -objectclass ( 1.3.6.1.4.1.40328.1.1.2.1 +olcObjectClasses: ( 1.3.6.1.4.1.40328.1.1.2.1 NAME 'mailAccount' DESC 'Mail Account' SUP top @@ -65,9 +69,9 @@ objectclass ( 1.3.6.1.4.1.40328.1.1.2.1 mailalias $ maildrop $ mailenable $ mailbox $ mailuserquota ) ) - +# # Mail Domain Objectclass -objectclass ( 1.3.6.1.4.1.40328.1.1.2.2 +olcObjectClasses: ( 1.3.6.1.4.1.40328.1.1.2.2 NAME 'mailDomain' DESC 'Domain mail entry' SUP top @@ -79,9 +83,9 @@ objectclass ( 1.3.6.1.4.1.40328.1.1.2.2 virtualdomaindescription $ mailuserquota ) ) - +# # Mail Group Objectclass -objectclass ( 1.3.6.1.4.1.40328.1.1.2.3 +olcObjectClasses: ( 1.3.6.1.4.1.40328.1.1.2.3 NAME 'mailGroup' SUP top AUXILIARY DESC 'Mail Group' MUST ( mail ) diff --git a/data/templates/slapd/yunohost.schema b/data/templates/slapd/permission.ldif similarity index 55% rename from data/templates/slapd/yunohost.schema rename to data/templates/slapd/permission.ldif index 7da60a20c..a97249d07 100644 --- a/data/templates/slapd/yunohost.schema +++ b/data/templates/slapd/permission.ldif @@ -1,33 +1,35 @@ -#dn: cn=yunohost,cn=schema,cn=config -#objectClass: olcSchemaConfig -#cn: yunohost +# Yunohost schema for group and permission support + +dn: cn=yunohost,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: yunohost # ATTRIBUTES # For Permission -attributetype ( 1.3.6.1.4.1.17953.9.1.1 NAME 'permission' +olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.1 NAME 'permission' DESC 'Yunohost permission on user and group side' SUP distinguishedName ) -attributetype ( 1.3.6.1.4.1.17953.9.1.2 NAME 'groupPermission' +olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.2 NAME 'groupPermission' DESC 'Yunohost permission for a group on permission side' SUP distinguishedName ) -attributetype ( 1.3.6.1.4.1.17953.9.1.3 NAME 'inheritPermission' +olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.3 NAME 'inheritPermission' DESC 'Yunohost permission for user on permission side' SUP distinguishedName ) -attributetype ( 1.3.6.1.4.1.17953.9.1.4 NAME 'URL' +olcAttributeTypes: ( 1.3.6.1.4.1.17953.9.1.4 NAME 'URL' DESC 'Yunohost application URL' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) # OBJECTCLASS # For Applications -objectclass ( 1.3.6.1.4.1.17953.9.2.1 NAME 'groupOfNamesYnh' +olcObjectClasses: ( 1.3.6.1.4.1.17953.9.2.1 NAME 'groupOfNamesYnh' DESC 'Yunohost user group' SUP top AUXILIARY MAY ( member $ businessCategory $ seeAlso $ owner $ ou $ o $ permission ) ) -objectclass ( 1.3.6.1.4.1.17953.9.2.2 NAME 'permissionYnh' +olcObjectClasses: ( 1.3.6.1.4.1.17953.9.2.2 NAME 'permissionYnh' DESC 'a Yunohost application' SUP top AUXILIARY MUST cn MAY ( groupPermission $ inheritPermission $ URL ) ) # For User -objectclass ( 1.3.6.1.4.1.17953.9.2.3 NAME 'userPermissionYnh' +olcObjectClasses: ( 1.3.6.1.4.1.17953.9.2.3 NAME 'userPermissionYnh' DESC 'a Yunohost application' SUP top AUXILIARY MAY ( permission ) ) diff --git a/data/templates/slapd/slapd.conf b/data/templates/slapd/slapd.conf deleted file mode 100644 index 0750b43aa..000000000 --- a/data/templates/slapd/slapd.conf +++ /dev/null @@ -1,154 +0,0 @@ -# This is the main slapd configuration file. See slapd.conf(5) for more -# info on the configuration options. - -####################################################################### -# Global Directives: - -# Features to permit -#allow bind_v2 - -# Schema and objectClass definitions -include /etc/ldap/schema/core.schema -include /etc/ldap/schema/cosine.schema -include /etc/ldap/schema/nis.schema -include /etc/ldap/schema/inetorgperson.schema -include /etc/ldap/schema/mailserver.schema -include /etc/ldap/schema/sudo.schema -include /etc/ldap/schema/yunohost.schema - -# Where the pid file is put. The init.d script -# will not stop the server if you change this. -pidfile /var/run/slapd/slapd.pid - -# List of arguments that were passed to the server -argsfile /var/run/slapd/slapd.args - -# Read slapd.conf(5) for possible values -loglevel none - -# Hashes to be used in generation of user passwords -password-hash {SSHA} - -# Where the dynamically loaded modules are stored -modulepath /usr/lib/ldap -moduleload back_mdb -moduleload memberof - -# The maximum number of entries that is returned for a search operation -sizelimit 500 - -# The tool-threads parameter sets the actual amount of cpu's that is used -# for indexing. -tool-threads 1 - -# TLS Support -TLSCertificateFile /etc/yunohost/certs/yunohost.org/crt.pem -TLSCertificateKeyFile /etc/yunohost/certs/yunohost.org/key.pem - -####################################################################### -# Specific Backend Directives for mdb: -# Backend specific directives apply to this backend until another -# 'backend' directive occurs -backend mdb - -####################################################################### -# Specific Directives for database #1, of type mdb: -# Database specific directives apply to this databasse until another -# 'database' directive occurs -database mdb - -# The base of your directory in database #1 -suffix "dc=yunohost,dc=org" - -# rootdn directive for specifying a superuser on the database. This is needed -# for syncrepl. -# rootdn "cn=admin,dc=yunohost,dc=org" - -# Where the database file are physically stored for database #1 -directory "/var/lib/ldap" - -# Indexing options for database #1 -index objectClass eq -index uid,sudoUser eq,sub -index entryCSN,entryUUID eq -index cn,mail eq -index gidNumber,uidNumber eq -index member,memberUid,uniqueMember eq -index virtualdomain eq -index permission eq - -# Save the time that the entry gets modified, for database #1 -lastmod on - -# Checkpoint the BerkeleyDB database periodically in case of system -# failure and to speed slapd shutdown. -checkpoint 512 30 - -# The userPassword by default can be changed -# by the entry owning it if they are authenticated. -# Others should not be able to see it, except the -# admin entry below -# These access lines apply to database #1 only -access to attrs=userPassword,shadowLastChange - by dn="cn=admin,dc=yunohost,dc=org" write - by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write - by anonymous auth - by self write - by * none - -# Personnal information can be changed by the entry -# owning it if they are authenticated. -# Others should be able to see it. -access to attrs=cn,gecos,givenName,mail,maildrop,displayName,sn - by dn="cn=admin,dc=yunohost,dc=org" write - by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write - by self write - by * read - -# Ensure read access to the base for things like -# supportedSASLMechanisms. Without this you may -# have problems with SASL not knowing what -# mechanisms are available and the like. -# Note that this is covered by the 'access to *' -# ACL below too but if you change that as people -# are wont to do you'll still need this if you -# want SASL (and possible other things) to work -# happily. -access to dn.base="" by * read - -# The admin dn has full write access, everyone else -# can read everything. -access to * - by dn="cn=admin,dc=yunohost,dc=org" write - by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write - by group/groupOfNames/Member="cn=admin,ou=groups,dc=yunohost,dc=org" write - by * read - -# Configure Memberof Overlay (used for Yunohost permission) - -# Link user <-> group -#dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config -overlay memberof -memberof-group-oc groupOfNamesYnh -memberof-member-ad member -memberof-memberof-ad memberOf -memberof-dangling error -memberof-refint TRUE - -# Link permission <-> groupes -#dn: olcOverlay={1}memberof,olcDatabase={1}mdb,cn=config -overlay memberof -memberof-group-oc permissionYnh -memberof-member-ad groupPermission -memberof-memberof-ad permission -memberof-dangling error -memberof-refint TRUE - -# Link permission <-> user -#dn: olcOverlay={2}memberof,olcDatabase={1}mdb,cn=config -overlay memberof -memberof-group-oc permissionYnh -memberof-member-ad inheritPermission -memberof-memberof-ad permission -memberof-dangling error -memberof-refint TRUE diff --git a/data/templates/slapd/slapd.ldif b/data/templates/slapd/slapd.ldif new file mode 100644 index 000000000..d3ed2e053 --- /dev/null +++ b/data/templates/slapd/slapd.ldif @@ -0,0 +1,235 @@ +# OpenLDAP server configuration for Yunohost +# ------------------------------------------ +# +# Because of the Yunohost's regen-conf mechanism, it is NOT POSSIBLE to +# edit the config database using an LDAP request. +# +# If you wish to edit the config database, you should edit THIS file +# and update the config database based on this file. +# +# Config database customization: +# 1. Edit this file as you want. +# 2. Apply your modifications. For this just run this following command in a shell: +# $ /usr/share/yunohost/hooks/conf_regen/06-slapd apply_config +# +# Note that if you customize this file, YunoHost's regen-conf will NOT +# overwrite this file. But that also means that you should be careful about +# upgrades, because they may ship important/necessary changes to this +# configuration that you will have to propagate yourself. + +# +# Main configuration +# +dn: cn=config +objectClass: olcGlobal +cn: config +olcConfigFile: /etc/ldap/slapd.conf +olcConfigDir: /etc/ldap/slapd.d/ +# List of arguments that were passed to the server +olcArgsFile: /var/run/slapd/slapd.args +# +olcAttributeOptions: lang- +olcAuthzPolicy: none +olcConcurrency: 0 +olcConnMaxPending: 100 +olcConnMaxPendingAuth: 1000 +olcIdleTimeout: 0 +olcIndexSubstrIfMaxLen: 4 +olcIndexSubstrIfMinLen: 2 +olcIndexSubstrAnyLen: 4 +olcIndexSubstrAnyStep: 2 +olcIndexIntLen: 4 +olcListenerThreads: 1 +olcLocalSSF: 71 +# Read slapd.conf(5) for possible values +olcLogLevel: None +# Where the pid file is put. The init.d script +# will not stop the server if you change this. +olcPidFile: /var/run/slapd/slapd.pid +olcReverseLookup: FALSE +olcThreads: 16 +# TLS Support +olcTLSCertificateFile: /etc/yunohost/certs/yunohost.org/crt.pem +olcTLSCertificateKeyFile: /etc/yunohost/certs/yunohost.org/key.pem +olcTLSVerifyClient: never +olcTLSProtocolMin: 0.0 +# The tool-threads parameter sets the actual amount of cpu's that is used +# for indexing. +olcToolThreads: 1 +structuralObjectClass: olcGlobal + +# +# Schema and objectClass definitions +# +dn: cn=schema,cn=config +objectClass: olcSchemaConfig +cn: schema + +include: file:///etc/ldap/schema/core.ldif +include: file:///etc/ldap/schema/cosine.ldif +include: file:///etc/ldap/schema/nis.ldif +include: file:///etc/ldap/schema/inetorgperson.ldif +include: file:///etc/ldap/schema/mailserver.ldif +include: file:///etc/ldap/schema/sudo.ldif +include: file:///etc/ldap/schema/permission.ldif + +# +# Module management +# +dn: cn=module{0},cn=config +objectClass: olcModuleList +cn: module{0} +# Where the dynamically loaded modules are stored +olcModulePath: /usr/lib/ldap +olcModuleLoad: {0}back_mdb +olcModuleLoad: {1}memberof +structuralObjectClass: olcModuleList + +# +# Frontend database +# +dn: olcDatabase={-1}frontend,cn=config +objectClass: olcDatabaseConfig +objectClass: olcFrontendConfig +olcDatabase: {-1}frontend +olcAddContentAcl: FALSE +olcLastMod: TRUE +olcSchemaDN: cn=Subschema +# Hashes to be used in generation of user passwords +olcPasswordHash: {SSHA} +structuralObjectClass: olcDatabaseConfig + +# +# Config database Configuration (#0) +# +dn: olcDatabase={0}config,cn=config +objectClass: olcDatabaseConfig +olcDatabase: {0}config +# Give access to root user. +# This give the possiblity to the admin to customize the LDAP configuration +olcAccess: {0}to * by * none +olcAddContentAcl: TRUE +olcLastMod: TRUE +olcRootDN: cn=config +structuralObjectClass: olcDatabaseConfig + +# +# Main database Configuration (#1) +# +dn: olcDatabase={1}mdb,cn=config +objectClass: olcDatabaseConfig +objectClass: olcMdbConfig +olcDatabase: {1}mdb +# The base of your directory in database #1 +olcSuffix: dc=yunohost,dc=org +# +# The userPassword by default can be changed +# by the entry owning it if they are authenticated. +# Others should not be able to see it, except the +# admin entry below +# These access lines apply to database #1 only +olcAccess: {0}to attrs=userPassword,shadowLastChange + by dn.base="cn=admin,dc=yunohost,dc=org" write + by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write + by anonymous auth + by self write + by * none +# +# Personnal information can be changed by the entry +# owning it if they are authenticated. +# Others should be able to see it. +olcAccess: {1}to attrs=cn,gecos,givenName,mail,maildrop,displayName,sn + by dn.base="cn=admin,dc=yunohost,dc=org" write + by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write + by self write + by * read +# +# Ensure read access to the base for things like +# supportedSASLMechanisms. Without this you may +# have problems with SASL not knowing what +# mechanisms are available and the like. +# Note that this is covered by the 'access to *' +# ACL below too but if you change that as people +# are wont to do you'll still need this if you +# want SASL (and possible other things) to work +# happily. +olcAccess: {2}to dn.base="" + by * read +# +# The admin dn has full write access, everyone else +# can read everything. +olcAccess: {3}to * + by dn.base="cn=admin,dc=yunohost,dc=org" write + by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write + by group/groupOfNames/member.exact="cn=admin,ou=groups,dc=yunohost,dc=org" write + by * read +# +olcAddContentAcl: FALSE +# Save the time that the entry gets modified, for database #1 +olcLastMod: TRUE +# Where the database file are physically stored for database #1 +olcDbDirectory: /var/lib/ldap +# Checkpoint the BerkeleyDB database periodically in case of system +# failure and to speed slapd shutdown. +olcDbCheckpoint: 512 30 +olcDbNoSync: FALSE +# Indexing options for database #1 +olcDbIndex: objectClass eq +olcDbIndex: entryUUID eq +olcDbIndex: entryCSN eq +olcDbIndex: cn eq +olcDbIndex: uid eq,sub +olcDbIndex: uidNumber eq +olcDbIndex: gidNumber eq +olcDbIndex: sudoUser eq,sub +olcDbIndex: member eq +olcDbIndex: mail eq +olcDbIndex: memberUid eq +olcDbIndex: uniqueMember eq +olcDbIndex: virtualdomain eq +olcDbIndex: permission eq +olcDbMaxSize: 10485760 +structuralObjectClass: olcMdbConfig + +# +# Configure Memberof Overlay (used for Yunohost permission) +# + +# Link user <-> group +dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config +objectClass: olcOverlayConfig +objectClass: olcMemberOf +olcOverlay: {0}memberof +olcMemberOfDangling: error +olcMemberOfDanglingError: constraintViolation +olcMemberOfRefInt: TRUE +olcMemberOfGroupOC: groupOfNamesYnh +olcMemberOfMemberAD: member +olcMemberOfMemberOfAD: memberOf +structuralObjectClass: olcMemberOf + +# Link permission <-> groupes +dn: olcOverlay={1}memberof,olcDatabase={1}mdb,cn=config +objectClass: olcOverlayConfig +objectClass: olcMemberOf +olcOverlay: {1}memberof +olcMemberOfDangling: error +olcMemberOfDanglingError: constraintViolation +olcMemberOfRefInt: TRUE +olcMemberOfGroupOC: permissionYnh +olcMemberOfMemberAD: groupPermission +olcMemberOfMemberOfAD: permission +structuralObjectClass: olcMemberOf + +# Link permission <-> user +dn: olcOverlay={2}memberof,olcDatabase={1}mdb,cn=config +objectClass: olcOverlayConfig +objectClass: olcMemberOf +olcOverlay: {2}memberof +olcMemberOfDangling: error +olcMemberOfDanglingError: constraintViolation +olcMemberOfRefInt: TRUE +olcMemberOfGroupOC: permissionYnh +olcMemberOfMemberAD: inheritPermission +olcMemberOfMemberOfAD: permission +structuralObjectClass: olcMemberOf diff --git a/data/templates/slapd/sudo.schema b/data/templates/slapd/sudo.ldif similarity index 72% rename from data/templates/slapd/sudo.schema rename to data/templates/slapd/sudo.ldif index d3e95e00c..a7088c855 100644 --- a/data/templates/slapd/sudo.schema +++ b/data/templates/slapd/sudo.ldif @@ -1,76 +1,78 @@ # # OpenLDAP schema file for Sudo -# Save as /etc/openldap/schema/sudo.schema +# Save as /etc/openldap/schema/sudo.ldif # -attributetype ( 1.3.6.1.4.1.15953.9.1.1 +dn: cn=sudo,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: sudo +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.2 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.3 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.4 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.5 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.6 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.7 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.8 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Start of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) - -attributetype ( 1.3.6.1.4.1.15953.9.1.9 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'End of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) - -attributeTypes ( 1.3.6.1.4.1.15953.9.1.10 +# +olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an integer to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) - -objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL +# +olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) - MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ - description ) + MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ description ) ) diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config index 8dc0e8dfc..bd3efdef3 100644 --- a/data/templates/ssh/sshd_config +++ b/data/templates/ssh/sshd_config @@ -27,9 +27,6 @@ HostKey {{ key }}{% endfor %} MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com {% endif %} -# Use kernel sandbox mechanisms where possible in unprivileged processes -UsePrivilegeSeparation sandbox - # LogLevel VERBOSE logs user's key fingerprint on login. # Needed to have a clear audit track of which key was using to log in. SyslogFacility AUTH diff --git a/data/templates/unattended/02periodic b/data/templates/unattended/02periodic deleted file mode 100644 index f16105466..000000000 --- a/data/templates/unattended/02periodic +++ /dev/null @@ -1,5 +0,0 @@ -# https://wiki.debian.org/UnattendedUpgrades#automatic_call_via_.2Fetc.2Fapt.2Fapt.conf.d.2F02periodic -APT::Periodic::Enable "1"; -APT::Periodic::Update-Package-Lists "1"; -APT::Periodic::Unattended-Upgrade "1"; -APT::Periodic::Verbose "1"; diff --git a/data/templates/unattended/50unattended-upgrades b/data/templates/unattended/50unattended-upgrades deleted file mode 100644 index 49b600a3b..000000000 --- a/data/templates/unattended/50unattended-upgrades +++ /dev/null @@ -1,36 +0,0 @@ -// Automatically upgrade packages from these (origin, archive) pairs -Unattended-Upgrade::Allowed-Origins { - "${distro_id} stable"; - "${distro_id} testing"; - "Depot-Debian testing"; - "${distro_id} ${distro_codename}-security"; - "${distro_id} ${distro_codename}-updates"; -// "${distro_id} ${distro_codename}-proposed-updates"; -}; - -// List of packages to not update -Unattended-Upgrade::Package-Blacklist { -// "vim"; -// "libc6"; -// "libc6-dev"; -// "libc6-i686"; -}; - -// Send email to this address for problems or packages upgrades -// If empty or unset then no email is sent, make sure that you -// have a working mail setup on your system. The package 'mailx' -// must be installed or anything that provides /usr/bin/mail. -//Unattended-Upgrade::Mail "root@localhost"; - -// Do automatic removal of new unused dependencies after the upgrade -// (equivalent to apt-get autoremove) -Unattended-Upgrade::Remove-Unused-Dependencies "true"; - -// Automatically reboot *WITHOUT CONFIRMATION* if a -// the file /var/run/reboot-required is found after the upgrade -Unattended-Upgrade::Automatic-Reboot "false"; - - -// Use apt bandwidth limit feature, this example limits the download -// speed to 70kb/sec -//Acquire::http::Dl-Limit "70"; diff --git a/data/templates/yunohost/services.yml b/data/templates/yunohost/services.yml index e1dd57e55..73ae9403e 100644 --- a/data/templates/yunohost/services.yml +++ b/data/templates/yunohost/services.yml @@ -20,10 +20,9 @@ nginx: test_conf: nginx -t needs_exposed_ports: [80, 443] category: web -nslcd: {} -php7.0-fpm: - log: /var/log/php7.0-fpm.log - test_conf: php-fpm7.0 --test +php7.3-fpm: + log: /var/log/php7.3-fpm.log + test_conf: php-fpm7.3 --test category: web postfix: log: [/var/log/mail.log,/var/log/mail.err] @@ -64,3 +63,5 @@ postgrey: null spamassassin: null rmilter: null php5-fpm: null +php7.0-fpm: null +nslcd: null diff --git a/debian/changelog b/debian/changelog index c119d57e7..d6ba6d553 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,303 @@ +yunohost (4.1.0) testing; urgency=low + + - Tmp bump of the version number to fix CI (c.f. Breaks: yunohost(<<4.1) in moulinette) + +yunohost (4.0.7) stable; urgency=low + + - [fix] Require explicitly php7.3-foo packages because in some cases Sury's php7.4- packages are installed and php7.3-fpm doesn't get installed ... (1288159a) + - [fix] Make sure app nginx confs do not prevent the loading of /yunohost/sso (#1044) + + Thanks to all contributors <3 ! (Kayou, ljf) + + -- Alexandre Aubin Fri, 04 Sep 2020 14:32:07 +0200 + +yunohost (4.0.6.1) stable; urgency=low + + - [fix] Stupid syntax issue in dovecot conf + + -- Alexandre Aubin Tue, 01 Sep 2020 02:00:19 +0200 + +yunohost (4.0.6) stable; urgency=low + + - [mod] Add apt conf regen hook to manage sury pinning policy (#1041) + - [fix] Use proper templating + handle xmpp-upload.domain.tld in dnsmasq conf (bc7344b6, 503e08b5) + - [fix] Explicitly require php-fpm >= 7.3 ... (41813744) + - [i18n] Translations updated for Catalan, French, German + + Thanks to all contributors <3 ! (Christian W., Titus PiJean, xaloc33) + + -- Alexandre Aubin Mon, 31 Aug 2020 19:57:24 +0200 + +yunohost (4.0.5) testing; urgency=low + + - [enh] Update postfix, dovecot, nginx configuration according to Mozilla guidelines (Buster + DH params) (f3a4334a, 89bcf1ba, 2d661737) + - [enh] Update acme_tiny to 4.1.0 (#1037) + - [fix] ref to variable in i18n string (c.f. issue 1647) (7b1f02e0) + - [fix] Recursively enforce ownership for rspamd (8454f2ec) + - [fix] Stupid encoding issue when fetching service description (6ec0e7b6) + - [fix] Misc fixes for CI (ca0a42f2, 485c65a9, #1038, a891d20a) + + Thanks to all contributors <3 ! (Eric G., Kay0u) + + -- Alexandre Aubin Tue, 25 Aug 2020 19:32:27 +0200 + +yunohost (4.0.4) stable; urgency=low + + - Debugging and robustness improvements for postgresql 9.6 -> 11 and xtables->nftables migrations (accc2da4, 59bd7d66, 4cb6f7fd, 4b14402c) + + -- Alexandre Aubin Wed, 12 Aug 2020 18:14:00 +0200 + +yunohost (4.0.3) stable; urgency=low + + - Bump version number for stable release + + -- Alexandre Aubin Wed, 29 Jul 2020 17:00:00 +0200 + +yunohost (4.0.2~beta) testing; urgency=low + + - [mod] Rebase on stretch-unstable to include recent changes + - [fix] Create admin's home during postinstall (#1021) + + Thanks to all contributors <3 ! (Kay0u) + + -- Alexandre Aubin Fri, 19 Jun 2020 15:16:26 +0200 + +yunohost (4.0.1~alpha) testing; urgency=low + + - [fix] It just make no sense to backup/restore the mysql password... (#911) + - [fix] Fix getopts and helpers (#885, #886) + - [fix] Explicitly create home using mkhomedir_helper instead of obscure pam rule that doesn't work anymore (b67ff314) + - [fix] Ldap interface seems to expect lists everywhere now? (fb8c2b7b) + - [deb] Clean control file, remove some legacy Conflicts and Replaces (ca0d4933) + - [deb] Add conflicts with versions from backports for critical dependencies (#967) + - [cleanup] Stale / legacy code (217aaa36, d77da6a0, af047468, 82d468a3) + - [conf] Automatically disable/stop systemd-resolved that conflicts with dnsmasq on fresh setups ... (e7214b37) + - [conf] Remove deprecated option in sshd conf, c.f. https://patchwork.openembedded.org/patch/139981/ (2723d245) + - [conf] Small tweak in dovecot conf (deprecated settings) (dc0481e2) + - [conf] Update nslcd and nsswitch stuff using new Buster's default configs + get rid of nslcd service, only keep the regen-conf part (6ef3520f) + - [php] Migrate from php7.0 to php7.3 (3374e653, 9be10506, dd9564d3, 9679c291, 212a15e4, 25fcaa19, c4ad66f5) + - [psql] Migrate from psql 11 to 9.6 (e88aed72, 4920d4f9, c70b0ae4) + - [firewall] Migrate from xtable to nftable (05fb58f2, 2c4a8b73, 625d5372) + - [slapd] Rework slapd regenconf to use new backend (#984) + + Thanks to all contributors <3 ! (Étienne M., Josué, Kay0u) + + -- Alexandre Aubin Fri, 05 Jun 2020 03:10:09 +0200 + +yunohost (3.8.5.5) stable; urgency=low + + - [enh] Allow to extend the nginx default_server configuration (f1bfc521) + - [mod] Move redirect to /yunohost/admin to a separate nginx conf file to allow customizing it more easily (ac9182d6) + - [enh] Make sure to validate/upgrade that we don't have any active weak certificate used by nginx at the beginning of the buster migration, otherwise nginx will later miserably fail to start (d4358897) + - [fix] get_files_diff crashing if {orig,new}_file is None (7bfe564a) + - [enh] Remove some useless message about file that "wasn't deleted because it doesn't exist." (#1024) + - [mod] Remove useless robot protection code (#1026) + - [fix] Let's not redefine the value for the 'service' var ... (1a2f26dc) + - [fix] More general stretch->buster patching for sources.list (#1028) + - [mod] Tweak custom disclaimer about the migration still being a bit touchy in preparation for stable release (852dea07) + - [mod] Typo/wording in en.json (#1030) + - [i18n] Translations updated for Catalan, French, Italian, Occitan + + Thanks to all contributors <3 ! (É. Gaspar, Kay0u, L. Noferini, ppr, Quentí, xaloc33) + + -- Alexandre Aubin Mon, 27 Jul 2020 19:03:33 +0200 + +yunohost (3.8.5.4) testing; urgency=low + + - [fix] Fix unscd version parsing *again* + - [fix] Enforce permissions on rspamd log directory + - [enh] Ignore stupid warnings about sudo-ldap that is already provided + + -- Alexandre Aubin Sun, 21 Jun 2020 23:37:09 +0200 + +yunohost (3.8.5.3) testing; urgency=low + + - [fix] Fix the fix about unscd downgrade :/ + + -- Alexandre Aubin Fri, 19 Jun 2020 18:50:58 +0200 + +yunohost (3.8.5.2) testing; urgency=low + + - [fix] Small issue with unscd upgrade/downgrade ... new version ain't always 0.53.1, so find it using dirty scrapping + + -- Alexandre Aubin Thu, 18 Jun 2020 16:19:35 +0200 + +yunohost (3.8.5.1) testing; urgency=low + + - [fix] Update Stretch->Buster migration disclaimer to make it clear that this is alpha-stage + + -- Alexandre Aubin Sat, 06 Jun 2020 03:30:00 +0200 + +yunohost (3.8.5) testing; urgency=low + + - [enh] Add migration procedure for Stretch->Buster (a2b83c0f, a26411db, 9f1211e9, e544bf3e, a0511cca) + - [fix] Disable/skip ntp when inside a container (9d0c0924) + + -- Alexandre Aubin Sat, 06 Jun 2020 02:11:51 +0200 + +yunohost (3.8.4.9) stable; urgency=low + + - [fix] Force lowercase on domain names (804f4b3e) + - [fix] Add dirmngr to Depends:, needed for apt-key / gpg (cd115ed8) + - [fix] Improve debugging when diagnosis ain't happy when renewing certs (0f0194be) + - [enh] Add yunohost version to logs metadata (d615546b) + - [enh] Alway filter irrelevant log lines when sharing it (38704cba, 51d53be5) + - [fix] Regen-conf outputing many 'forget-about-it' because of files flagged as to be removed (f4525488) + - [fix] postfix per-domain destination concurrency (#988) + - [fix] Call regenconf for ssh before the general regenconf during the postinstall to avoid an irrelevant warning (7805837b) + - [i18n] Translations updated for Catalan, French, German + + Thanks to all contributors <3 ! (taziden, ljf, ppr, xaloc33, Yasss Gurl) + + -- Alexandre Aubin Thu, 18 Jun 2020 15:13:01 +0200 + +yunohost (3.8.4.8) stable; urgency=low + + - [fix] Don't add unprotected_urls if it's already in skipped_urls (#1005) + - [enh] Add pre-defined DHE group and set up Nginx to use it (#1007) + - [fix] Make sure to propagate change in slapd systemd conf during initial install (2d42480f) + - [fix] More accurate grep to avoid mistakenly grepping commented lines... (2408a620) + - [enh] Update n to 6.5.1 (#1012) + - [fix] Set sury default pinning to 600 (653c5fde) + - [enh] Clean stale file/hashes in regen-conf (#1009) + - [fix] Weirdness in regen-conf mechanism for SSH conf (#1014) + + Thanks to all contributors <3 ! (É. Gaspar, Josué, SohKa) + + -- Alexandre Aubin Sat, 06 Jun 2020 01:59:08 +0200 + +yunohost (3.8.4.7) stable; urgency=low + + - [fix] Remove some remains of glances (17eec25e) + - [fix] Force external resolution for reverse DNS dig (852cd14c) + - [fix] Make sure mysql is an alias to mariadb (e24191ce, ca89607d) + - [fix] Path for ynh_add_fpm_config template in restore (#1001) + - [fix] Add -o Acquire::Retries=3 to fix some stupid network issues happening sometimes with apt (03432349) + - [fix] ynh_setup_source: Retry wget on non-critical failures to try to avoid tmp dns issues (3d66eaec) + - [fix] ynh_setup_source: Calling ynh_print_err in case of error didn't work, and we probably want a ynh_die here (55036fad) + - [i18n] Translations updated for Catalan, French, Italian, Occitan + + Thanks to all contributors <3 ! (JimboJoe, Leandro N., ppr, Quentí, xaloc33, yalh76) + + -- Alexandre Aubin Thu, 04 Jun 2020 02:28:33 +0200 + +yunohost (3.8.4.6) stable; urgency=low + + - [fix] Bump server_names_hash_bucket_size to 128 to avoid nginx exploding for stupid reasons (b3db4d92) + - [fix] More sensible strategy for sury pinning (#1006) + - [fix] Stop trying to fetch log categories that are not implemented yet T.T (77bd9ae3) + - [enh] Add logging and persistent as default config for new muc room (#1008) + - [tests] Moar tests for app args parsing (#1004) + + Thanks to all contributors <3 ! (Gabriel, Kay0u, Bram) + + -- Alexandre Aubin Thu, 28 May 2020 00:22:10 +0200 + +yunohost (3.8.4.5) stable; urgency=low + + - [enh] Tell systemctl to stfu about creating symlinks when enabling/disabling services (6637c8a8) + - [enh] Add maindomain in diagnosis email subject (e30e25fa) + - [fix] Webpath should also be normalized for args_list, so that we can get rid of the 'malformed path' check of the CI... (58ce6e5e) + - [fix] Increase time window for auto diagnosis cron to avoid remote diagnosis server overload (dc221495) + - [fix] encoding bullshit (4c600125, 64596bc1) + - [fix] Typo in diagnosis message + fix FR translation report format of bad DNS conf (#1002, b8f8ea14) + - [fix] Flag old etckeeper.conf as 'should not exist' in regenconf (5a3b382f) + - [enh] Detect dyndns-domains managed by yunohost and advice to use yunohost dyndns update --force (8b169f13) + - [enh] Complain if apps savagely edit system configurations during install and upgrade (a23f02db) + - [i18n] Translations updated for Arabic, Catalan, French, German, Italian + - [tests] CI V2 : Rework CI workflow (#991) + + Thanks to all contributors <3 ! (ButterflyOfFire, Kay0u, L. Noferini, rynas, V. Rubiolo, xaloc33, Yasss Gurl) + + -- Alexandre Aubin Tue, 26 May 2020 03:20:39 +0200 + +yunohost (3.8.4.4) stable; urgency=low + + - [fix] Crash when the services file is empty (85f1802) + - [fix] IPv6 detection when using wg-quick (#997) + - [fix] Use a .get() to avoid crash if key doesn't exist (1f1b2338) + - [enh] Don't display the hostname when calling journalctl, this takes horizontal space for nothing (2bcfb5a1) + - [fix] Add --quiet, otherwise getopts is confused by "-- Logs" at the beginning (bdbf1822) + - [mod] We don't need those color codes... and warnings are already warnings... (2a631fa2) + - [fix] psql_setup_db: Do not create a new password if the user already exists (#998) + - [enh] Add an exception if packaging format is not recognized (f0cc6798) + + Thanks to all contributors <3 ! (Aleks, Julien Rabier, Kayou) + + -- Kay0u Fri, 22 May 2020 19:26:05 +0000 + +yunohost (3.8.4.3) stable; urgency=low + + - [fix] Workaround for the sury pinning issues when installing dependencies + - [i18n] Translations updated for Catalan, French, Occitan + + Thanks to all contributors <3 ! (Aleks, clecle226, Kay0u, ppr, Quenti) + + -- Kay0u Wed, 20 May 2020 18:41:49 +0000 + +yunohost (3.8.4.2) testing; urgency=low + + - [enh] During failed upgrades: Only mention packages that couldn't be upgraded (26fcfed7) + - [enh] Also run dpkg --audit to check if dpkg is in a broken state (09d8500f, 97199d19) + - [enh] Improve logs readability (c6f18496, 9cbd368d, 5850bf61, 413778d2, 5c8c07b8, f73c34bf, 94ea8265) + - [enh] Crash early about apps already installed when attempting to restore (f9e4c96c) + - [fix] Add the damn short hostname to /etc/hosts automagically (c.f. rabbitmq-server) (e67dc791) + - [fix] Don't miserably crash if doveadm fails to run (c9b22138) + - [fix] Diagnosis: Try to not have weird warnings if no diagnosis ran yet... (65c87d55) + - [fix] Diagnosis: Change logic of --email to avoid sending empty mail if some issues are found but ignored (4cd4938e) + - [enh] Diagnosis/services: Report the service status as warning/unknown if service type is oneshot and status exited (dd09758f, 1cd7ffea) + - [fix] Rework ynh_psql_test_if_first_run (#993) + - [tests] Tests for args parsing (#989, 108a3ca4) + + Thanks to all contributors <3 ! (Bram, Kayou) + + -- Alexandre Aubin Tue, 19 May 2020 20:08:47 +0200 + +yunohost (3.8.4.1) testing; urgency=low + + - [mod] Tweak diagnosis threshold for swap warning (429df8c4) + - [fix] Make sure we have a list for log_list + make sure item is in list before using .remove()... (afbeb145, 43facfd5) + - [fix] Sometimes tree-model has a weird \x00 which breaks yunopaste (c346f5f1) + + -- Alexandre Aubin Mon, 11 May 2020 00:50:34 +0200 + +yunohost (3.8.4) testing; urgency=low + + - [fix] Restoration of custom hooks / missing restore hooks (#927) + - [enh] Real CSP headers for the webadmin (#961) + - [enh] Simplify / optimize reading version of yunohost packages... (#968) + - [fix] handle new auto restart of ldap in moulinette (#975) + - [enh] service.py cleanup + add tests for services (#979, #986) + - [fix] Enforce permissions for stuff in /etc/yunohost/ (#963) + - [mod] Remove security diagnosis category for now, Move meltdown check to base system (a799740a) + - [mod] Change warning/errors about swap as info instead ... add a tip about the fact that having swap on SD or SSD is dangerous (23147161) + - [enh] Improve auto diagnosis cron UX, add a --human-readable option to diagnosis_show() (aecbb14a) + - [enh] Rely on new diagnosis for letsencrypt elligibility (#985) + - [i18n] Translations updated for Catalan, Esperanto, French, Spanish + + Thanks to all contributors <3 ! (amirale qt, autra, Bram, clecle226, I. Hernández, Kay0u, xaloc33) + + -- Alexandre Aubin Sat, 09 May 2020 21:20:00 +0200 + +yunohost (3.8.3) testing; urgency=low + + - [fix] Remove dot in reverse DNS check + - [fix] Upgrade of multi-instance apps was broken (#976) + - [fix] Check was broken if an apps with no domain setting was installed (#978) + - [enh] Add a timeout to wget (#972) + - [fix] ynh_get_ram: Enforce choosing --free or --total (#972) + - [fix] Simplify / improve robustness of backup list + - [enh] Make nodejs helpers easier to use (#939) + - [fix] Misc tweak for disk usage diagnosis, some values were inconsistent / bad UX / ... + - [enh] Assert slapd is running to avoid miserably crashing with weird ldap errors + - [enh] Try to show smarter / more useful logs by filtering irrelevant lines like set +x etc + - Technical tweaks for metronome 3.14.0 support + - Misc improvements for tests and linters + + Thanks to all contributors <3 ! (Bram, Kay0u, Maniack C., ljf, Maranda) + + -- Alexandre Aubin Thu, 07 Apr 2020 04:00:00 +0000 + yunohost (3.8.2.2) testing; urgency=low Aleks broke everything /again/ *.* @@ -1626,7 +1926,7 @@ yunohost (2.5.2) testing; urgency=low Other fixes and improvements: * [enh] remove timeout from cli interface - * [fix] [#662](https://dev.yunohost.org/issues/662): missing 'python-openssl' dependency for Let's Encrypt integration. + * [fix] #662: missing 'python-openssl' dependency for Let's Encrypt integration. * [fix] --no-remove-on-failure for app install should behave as a flag. * [fix] don't remove trailing char if it's not a slash diff --git a/debian/conf/pam/mkhomedir b/debian/conf/pam/mkhomedir deleted file mode 100644 index eedc8b745..000000000 --- a/debian/conf/pam/mkhomedir +++ /dev/null @@ -1,6 +0,0 @@ -Name: Create home directory during login -Default: yes -Priority: 900 -Session-Type: Additional -Session: - required pam_mkhomedir.so umask=0022 skel=/etc/skel diff --git a/debian/control b/debian/control index 5061ad4f2..696f13f2c 100644 --- a/debian/control +++ b/debian/control @@ -11,45 +11,42 @@ Package: yunohost Essential: yes Architecture: all Depends: ${python:Depends}, ${misc:Depends} - , moulinette (>= 3.7), ssowat (>= 3.7) + , moulinette (>= 4.1), ssowat (>= 4.0) , python-psutil, python-requests, python-dnspython, python-openssl - , python-apt, python-miniupnpc, python-dbus, python-jinja2 - , python-toml - , apt, apt-transport-https - , nginx, nginx-extras (>=1.6.2) - , php-fpm, php-ldap, php-intl - , mariadb-server, php-mysql | php-mysqlnd + , python-miniupnpc, python-dbus, python-jinja2 + , python-toml, python-packaging, python-publicsuffix + , apt, apt-transport-https, dirmngr + , php7.3-common, php7.3-fpm, php7.3-ldap, php7.3-intl + , mariadb-server, php7.3-mysql , openssh-server, iptables, fail2ban, dnsutils, bind9utils , openssl, ca-certificates, netcat-openbsd, iproute2 , slapd, ldap-utils, sudo-ldap, libnss-ldapd, unscd, libpam-ldapd , dnsmasq, avahi-daemon, libnss-mdns, resolvconf, libnss-myhostname , postfix, postfix-ldap, postfix-policyd-spf-perl, postfix-pcre , dovecot-core, dovecot-ldap, dovecot-lmtpd, dovecot-managesieved, dovecot-antispam - , rspamd (>= 1.6.0), opendkim-tools, postsrsd, procmail, mailutils + , rspamd, opendkim-tools, postsrsd, procmail, mailutils , redis-server - , metronome - , git, curl, wget, cron, unzip, jq - , lsb-release, haveged, fake-hwclock, equivs, lsof, whois, python-publicsuffix + , metronome (>=3.14.0) + , git, curl, wget, cron, unzip, jq, bc + , lsb-release, haveged, fake-hwclock, equivs, lsof, whois Recommends: yunohost-admin , ntp, inetutils-ping | iputils-ping , bash-completion, rsyslog - , php-gd, php-curl, php-gettext, php-mcrypt + , php7.3-gd, php7.3-curl, php-gettext , python-pip , unattended-upgrades , libdbd-ldap-perl, libnet-dns-perl Suggests: htop, vim, rsync, acpi-support-base, udisks2 Conflicts: iptables-persistent - , moulinette-yunohost, yunohost-config - , yunohost-config-others, yunohost-config-postfix - , yunohost-config-dovecot, yunohost-config-slapd - , yunohost-config-nginx, yunohost-config-amavis - , yunohost-config-mysql, yunohost-predepends - , apache2, bind9 -Replaces: moulinette-yunohost, yunohost-config - , yunohost-config-others, yunohost-config-postfix - , yunohost-config-dovecot, yunohost-config-slapd - , yunohost-config-nginx, yunohost-config-amavis - , yunohost-config-mysql, yunohost-predepends + , apache2 + , bind9 + , nginx-extras (>= 1.16) + , openssl (>= 1.1.1g) + , slapd (>= 2.4.49) + , dovecot-core (>= 1:2.3.7) + , redis-server (>= 5:5.0.7) + , fail2ban (>= 0.11) + , iptables (>= 1.8.3) Description: manageable and configured self-hosting server YunoHost aims to make self-hosting accessible to everyone. It configures an email, Web and IM server alongside a LDAP base. It also provides diff --git a/debian/install b/debian/install index a814d1617..1691a4849 100644 --- a/debian/install +++ b/debian/install @@ -8,11 +8,11 @@ data/other/yunoprompt.service /etc/systemd/system/ data/other/password/* /usr/share/yunohost/other/password/ data/other/dpkg-origins/yunohost /etc/dpkg/origins data/other/dnsbl_list.yml /usr/share/yunohost/other/ +data/other/ffdhe2048.pem /usr/share/yunohost/other/ data/other/* /usr/share/yunohost/yunohost-config/moulinette/ data/templates/* /usr/share/yunohost/templates/ data/helpers /usr/share/yunohost/ data/helpers.d/* /usr/share/yunohost/helpers.d/ -debian/conf/pam/* /usr/share/pam-configs/ lib/metronome/modules/* /usr/lib/metronome/modules/ locales/* /usr/lib/moulinette/yunohost/locales/ src/yunohost /usr/lib/moulinette diff --git a/debian/postinst b/debian/postinst index 9c78c8432..4b43b2506 100644 --- a/debian/postinst +++ b/debian/postinst @@ -29,11 +29,6 @@ do_configure() { # Yunoprompt systemctl enable yunoprompt.service - - # remove old PAM config and update it - [[ ! -f /usr/share/pam-configs/my_mkhomedir ]] \ - || rm /usr/share/pam-configs/my_mkhomedir - pam-auth-update --package } # summary of how this script can be called: diff --git a/doc/generate_helper_doc.py b/doc/generate_helper_doc.py index a7866b85b..a97d424eb 100644 --- a/doc/generate_helper_doc.py +++ b/doc/generate_helper_doc.py @@ -4,12 +4,13 @@ import os import glob import datetime + def render(helpers): - data = { "helpers": helpers, - "date": datetime.datetime.now().strftime("%m/%d/%Y"), - "version": open("../debian/changelog").readlines()[0].split()[1].strip("()") - } + data = {"helpers": helpers, + "date": datetime.datetime.now().strftime("%m/%d/%Y"), + "version": open("../debian/changelog").readlines()[0].split()[1].strip("()") + } from jinja2 import Template from ansi2html import Ansi2HTMLConverter @@ -22,13 +23,14 @@ def render(helpers): return conv.convert(shell, False) template = open("helper_doc_template.html", "r").read() - t = Template(template) + t = Template(template) t.globals['now'] = datetime.datetime.utcnow result = t.render(data=data, convert=shell_to_html, shell_css=shell_css) open("helpers.html", "w").write(result) ############################################################################## + class Parser(): def __init__(self, filename): @@ -42,15 +44,15 @@ class Parser(): self.blocks = [] current_reading = "void" - current_block = { "name": None, - "line": -1, - "comments": [], - "code": [] } + current_block = {"name": None, + "line": -1, + "comments": [], + "code": []} for i, line in enumerate(self.file): if line.startswith("#!/bin/bash"): - continue + continue line = line.rstrip().replace("\t", " ") @@ -73,7 +75,7 @@ class Parser(): elif line.strip() == "": # Well eh that was not an actual helper definition ... start over ? current_reading = "void" - current_block = { "name": None, + current_block = {"name": None, "line": -1, "comments": [], "code": [] @@ -101,10 +103,10 @@ class Parser(): # (we ignore helpers containing [internal] ...) if not "[internal]" in current_block["comments"]: self.blocks.append(current_block) - current_block = { "name": None, - "line": -1, - "comments": [], - "code": [] } + current_block = {"name": None, + "line": -1, + "comments": [], + "code": []} else: current_block["code"].append(line) @@ -180,13 +182,14 @@ class Parser(): b["usage"] = b["usage"].strip() - def is_global_comment(line): return line.startswith('#') + def malformed_error(line_number): return "Malformed file line {} ?".format(line_number) + def main(): helper_files = sorted(glob.glob("../data/helpers.d/*")) @@ -204,5 +207,5 @@ def main(): render(helpers) -main() +main() diff --git a/doc/helper_doc_template.html b/doc/helper_doc_template.html index 92611c737..f96a0190e 100644 --- a/doc/helper_doc_template.html +++ b/doc/helper_doc_template.html @@ -2,6 +2,8 @@

App helpers

+

Doc auto-generated by this script on {{data.date}} (Yunohost version {{data.version}})

+ {% for category, helpers in data.helpers %}

{{ category }}

@@ -70,7 +72,7 @@

{% endif %}

- Dude, show me the code ! + Dude, show me the code !

@@ -81,9 +83,6 @@ {% endfor %} {% endfor %} -

Generated by this script on {{data.date}} (Yunohost version {{data.version}})

- -