diff --git a/.gitattributes b/.gitattributes index 45c10d7b..01d20f30 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,5 +4,5 @@ docs/speeches export-ignore docs/video export-ignore docs/src/man7 export-ignore -bin/build-helper export-ignore +bin/cdist-build-helper export-ignore README-maintainers export-ignore diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1cc17995..a4bc67aa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,18 +1,23 @@ +--- +image: code.ungleich.ch:5050/ungleich-public/cdist/cdist-ci:latest + stages: - test -unit_tests: - stage: test - script: - - ./bin/build-helper version - - ./bin/build-helper test - -pycodestyle: - stage: test - script: - - ./bin/build-helper pycodestyle +before_script: + - ./bin/cdist-build-helper version shellcheck: stage: test script: - - ./bin/build-helper shellcheck + - ./bin/cdist-build-helper shellcheck + +pycodestyle: + stage: test + script: + - ./bin/cdist-build-helper pycodestyle + +unit_tests: + stage: test + script: + - ./bin/cdist-build-helper test diff --git a/Makefile b/Makefile index f89ac1e7..3712511c 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,7 @@ version: } # Manpages #3: generic part -man: version $(MANTYPES) $(DOCSREF) +man: version configskel $(MANTYPES) $(DOCSREF) $(DOCSTYPESREF) $(SPHINXM) html: version configskel $(MANTYPES) $(DOCSREF) $(DOCSTYPESREF) @@ -104,7 +104,7 @@ DOTMANTYPES=$(subst /man.rst,.rst,$(DOTMANTYPEPREFIX)) $(DOTMAN7DSTDIR)/cdist-type%.rst: $(DOTTYPEDIR)/%/man.rst ln -sf "$^" $@ -dotman: version $(DOTMANTYPES) +dotman: version configskel $(DOTMANTYPES) $(DOCSREF) $(DOCSTYPESREF) $(SPHINXM) ################################################################################ diff --git a/README b/README deleted file mode 100644 index caf2dac8..00000000 --- a/README +++ /dev/null @@ -1,7 +0,0 @@ -cdist ------ - -cdist is a usable configuration management system. - -For the web documentation have a look at https://www.cdi.st/ -or at docs/src for reStructuredText manual. diff --git a/README-maintainers b/README-maintainers index af57f475..5766dd7d 100644 --- a/README-maintainers +++ b/README-maintainers @@ -1,4 +1,4 @@ -Maintainers should use ./bin/build-helper script. +Maintainers should use ./bin/cdist-build-helper script. Makefile is intended for end users. It can be used for non-maintaining targets that can be run from pure source (without git repository). diff --git a/README.md b/README.md new file mode 100644 index 00000000..de6901c7 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# cdist + +**cdist** is a usable configuration management system. + +It adheres to the [**KISS principle**](https://en.wikipedia.org/wiki/KISS_principle) +and is being used in small up to enterprise grade environments. + +For more information have a look at [**homepage**](https://cdi.st) +or at **``docs/src``** for manual in **reStructuredText** format. + +## Contributing + +Merge/Pull requests can be made in both +[upstream **GitLab**](https://code.ungleich.ch/ungleich-public/cdist/merge_requests) +(managed by [**ungleich**](https://ungleich.ch)) +and [**GitHub** project](https://github.com/ungleich/cdist/pulls). + +Issues can be made and other project management activites happen +[**only in GitLab**](https://code.ungleich.ch/ungleich-public/cdist) +(needs [**ungleich** account](https://account.ungleich.ch)). + +For community-maintained types there is +[**cdist-contrib** project](https://code.ungleich.ch/ungleich-public/cdist-contrib). + +## Participating + +IRC: ``#cdist`` @ freenode + +Matrix: ``#cdist:ungleich.ch`` + +Mattermost: https://chat.ungleich.ch/ungleich/channels/cdist diff --git a/bin/cdist b/bin/cdist index 645020a1..ddaffa7f 100755 --- a/bin/cdist +++ b/bin/cdist @@ -1,7 +1,8 @@ -#!/bin/sh +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# 2012 Nico Schottelius (nico-cdist at schottelius.org) +# 2010-2016 Nico Schottelius (nico-cdist at schottelius.org) +# 2016 Darko Poljak (darko.poljak at gmail.com) # # This file is part of cdist. # @@ -20,14 +21,81 @@ # # -# Wrapper for real script to allow execution from checkout -dir=${0%/*} +import logging +import os +import sys -# Ensure version is present - the bundled/shipped version contains a static version, -# the git version contains a dynamic version -"$dir/build-helper" version +# See if this file's parent is cdist module +# and if so add it to module search path. +cdist_dir = os.path.realpath( + os.path.join( + os.path.dirname(os.path.realpath(__file__)), + os.pardir)) +cdist_init_dir = os.path.join(cdist_dir, 'cdist', '__init__.py') +if os.path.exists(cdist_init_dir): + sys.path.insert(0, cdist_dir) -libdir=$(cd "${dir}/../" && pwd -P) -export PYTHONPATH="${libdir}" +import cdist # noqa 402 +import cdist.argparse # noqa 402 +import cdist.banner # noqa 402 +import cdist.config # noqa 402 +import cdist.install # noqa 402 +import cdist.shell # noqa 402 +import cdist.inventory # noqa 402 -"$dir/../scripts/cdist" "$@" + +def commandline(): + """Parse command line""" + + # preos subcommand hack + if len(sys.argv) > 1 and sys.argv[1] == 'preos': + return cdist.preos.PreOS.commandline(sys.argv[1:]) + parser, cfg = cdist.argparse.parse_and_configure(sys.argv[1:]) + args = cfg.get_args() + + # Work around python 3.3 bug: + # http://bugs.python.org/issue16308 + # http://bugs.python.org/issue9253 + + # FIXME: catching AttributeError also hides + # real problems.. try a different way + + # FIXME: we always print main help, not + # the help of the actual parser being used! + try: + getattr(args, "func") + except AttributeError: + parser['main'].print_help() + sys.exit(0) + + args.func(args) + + +if __name__ == "__main__": + if sys.version < cdist.MIN_SUPPORTED_PYTHON_VERSION: + print('Python >= {} is required on the source host.'.format( + cdist.MIN_SUPPORTED_PYTHON_VERSIO), file=sys.stderr) + sys.exit(1) + + exit_code = 0 + + try: + import re + import os + + if re.match("__", os.path.basename(sys.argv[0])): + import cdist.emulator + emulator = cdist.emulator.Emulator(sys.argv) + emulator.run() + else: + commandline() + + except KeyboardInterrupt: + exit_code = 2 + + except cdist.Error as e: + log = logging.getLogger("cdist") + log.error(e) + exit_code = 1 + + sys.exit(exit_code) diff --git a/bin/build-helper b/bin/cdist-build-helper similarity index 93% rename from bin/build-helper rename to bin/cdist-build-helper index ed41e438..0380b3f8 100755 --- a/bin/build-helper +++ b/bin/cdist-build-helper @@ -45,7 +45,7 @@ usage() { shellcheck-manifests shellcheck-local-gencodes shellcheck-remote-gencodes - shellcheck-scripts + shellcheck-bin shellcheck-gencodes shellcheck-types shellcheck @@ -100,7 +100,7 @@ case "$option" in if (\$0 ~ /^$end/) { exit } else { - print \$0 + print \$0 } } }" "$basedir/docs/changelog" @@ -135,7 +135,7 @@ case "$option" in version=$1; shift - ( + ( cat << eof Subject: cdist $version has been released @@ -336,7 +336,7 @@ eof make docs-clean make docs - ############################################################# + ############################################################# # Everything green, let's do the release # Tag the current commit @@ -371,7 +371,6 @@ eof Manual steps post release: - cdist-web - send generated mailinglist.tmp mail - - twitter eof ;; @@ -406,7 +405,7 @@ eof ;; pycodestyle|pep8) - pycodestyle "${basedir}" "${basedir}/scripts/cdist" + pycodestyle "${basedir}" "${basedir}/bin/cdist" ;; check-pycodestyle) @@ -461,27 +460,34 @@ eof test ! -s "${SHELLCHECKTMP}" || { cat "${SHELLCHECKTMP}"; exit 1; } ;; - shellcheck-scripts) + # NOTE: shellcheck-scripts is kept for compatibility + shellcheck-bin|shellcheck-scripts) # shellcheck disable=SC2086 - ${SHELLCHECKCMD} scripts/cdist-dump scripts/cdist-new-type > "${SHELLCHECKTMP}" + ${SHELLCHECKCMD} bin/cdist-dump bin/cdist-new-type > "${SHELLCHECKTMP}" test ! -s "${SHELLCHECKTMP}" || { cat "${SHELLCHECKTMP}"; exit 1; } ;; shellcheck-gencodes) - "$0" shellcheck-local-gencodes || exit 1 - "$0" shellcheck-remote-gencodes || exit 1 + errors=false + "$0" shellcheck-local-gencodes || errors=true + "$0" shellcheck-remote-gencodes || errors=true + ! $errors || exit 1 ;; shellcheck-types) - "$0" shellcheck-type-explorers || exit 1 - "$0" shellcheck-manifests || exit 1 - "$0" shellcheck-gencodes || exit 1 + errors=false + "$0" shellcheck-type-explorers || errors=true + "$0" shellcheck-manifests || errors=true + "$0" shellcheck-gencodes || errors=true + ! $errors || exit 1 ;; shellcheck) - "$0" shellcheck-global-explorers || exit 1 - "$0" shellcheck-types || exit 1 - "$0" shellcheck-scripts || exit 1 + errors=false + "$0" shellcheck-global-explorers || errors=true + "$0" shellcheck-types || errors=true + "$0" shellcheck-bin || errors=true + ! $errors || exit 1 ;; shellcheck-type-files) @@ -491,12 +497,14 @@ eof ;; shellcheck-with-files) - "$0" shellcheck || exit 1 - "$0" shellcheck-type-files || exit 1 + errors=false + "$0" shellcheck || errors=true + "$0" shellcheck-type-files || errors=true + ! $errors || exit 1 ;; shellcheck-build-helper) - ${SHELLCHECKCMD} ./bin/build-helper + ${SHELLCHECKCMD} ./bin/cdist-build-helper ;; check-shellcheck) diff --git a/scripts/cdist-dump b/bin/cdist-dump similarity index 99% rename from scripts/cdist-dump rename to bin/cdist-dump index 83b09eb8..d29e5985 100755 --- a/scripts/cdist-dump +++ b/bin/cdist-dump @@ -224,6 +224,7 @@ hor_line() if [ "${do_global_explorer}" ] then print_verbose 2 "Dumping global explorers" + # shellcheck disable=SC2086 set -- "$@" ${or} \( \ -path "*/explorer/*" -a \ ! -path "*/conf/*" -a \ diff --git a/scripts/cdist-new-type b/bin/cdist-new-type similarity index 100% rename from scripts/cdist-new-type rename to bin/cdist-new-type diff --git a/cdist/__init__.py b/cdist/__init__.py index c673b3ba..44366cd0 100644 --- a/cdist/__init__.py +++ b/cdist/__init__.py @@ -22,11 +22,27 @@ import os import hashlib +import subprocess import cdist.log -import cdist.version -VERSION = cdist.version.VERSION + +VERSION = 'unknown version' + +try: + import cdist.version + VERSION = cdist.version.VERSION +except ModuleNotFoundError: + cdist_dir = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir)) + if os.path.isdir(os.path.join(cdist_dir, '.git')): + try: + VERSION = subprocess.check_output( + ['git', 'describe', '--always'], + cwd=cdist_dir, + universal_newlines=True) + except Exception: + pass BANNER = """ .. . .x+=:. s @@ -48,6 +64,9 @@ REMOTE_EXEC = "ssh -o User=root" REMOTE_CMDS_CLEANUP_PATTERN = "ssh -o User=root -O exit -S {}" +MIN_SUPPORTED_PYTHON_VERSION = '3.5' + + class Error(Exception): """Base exception class for this project""" pass diff --git a/cdist/argparse.py b/cdist/argparse.py index 611c484a..88759d7b 100644 --- a/cdist/argparse.py +++ b/cdist/argparse.py @@ -5,12 +5,14 @@ import logging import collections import functools import cdist.configuration +import cdist.log import cdist.preos import cdist.info +import cdist.scan.commandline # set of beta sub-commands -BETA_COMMANDS = set(('install', 'inventory', )) +BETA_COMMANDS = set(('install', 'inventory', 'scan', )) # set of beta arguments for sub-commands BETA_ARGS = { 'config': set(('tag', 'all_tagged_hosts', 'use_archiving', )), @@ -125,6 +127,14 @@ def get_parsers(): 'value.'), action='count', default=None) + parser['colored_output'] = argparse.ArgumentParser(add_help=False) + parser['colored_output'].add_argument( + '--colors', metavar='WHEN', + help="Colorize cdist's output based on log level; " + "WHEN is 'always', 'never', or 'auto'.", + action='store', dest='colored_output', required=False, + choices=cdist.configuration.ColoredOutputOption.CHOICES) + parser['beta'] = argparse.ArgumentParser(add_help=False) parser['beta'].add_argument( '-b', '--beta', @@ -197,6 +207,13 @@ def get_parsers(): 'supported. Without argument CPU count is used by default. '), action='store', dest='jobs', const=multiprocessing.cpu_count()) + parser['config_main'].add_argument( + '--log-server', + action='store_true', + help=('Start a log server for sub processes to use. ' + 'This is mainly useful when running cdist nested ' + 'from a code-local script. Log server is alwasy ' + 'implicitly started for \'install\' command.')) parser['config_main'].add_argument( '-n', '--dry-run', help='Do not execute code.', action='store_true') @@ -257,8 +274,7 @@ def get_parsers(): '-f', '--file', help=('Read specified file for a list of additional hosts to ' 'operate on or if \'-\' is given, read stdin (one host per ' - 'line). If no host or host file is specified then, by ' - 'default, read hosts from stdin.'), + 'line).'), dest='hostfile', required=False) parser['config_args'].add_argument( '-p', '--parallel', nargs='?', metavar='HOST_MAX', @@ -283,6 +299,7 @@ def get_parsers(): 'host', nargs='*', help='Host(s) to operate on.') parser['config'] = parser['sub'].add_parser( 'config', parents=[parser['loglevel'], parser['beta'], + parser['colored_output'], parser['common'], parser['config_main'], parser['inventory_common'], @@ -301,6 +318,7 @@ def get_parsers(): parser['add-host'] = parser['invsub'].add_parser( 'add-host', parents=[parser['loglevel'], parser['beta'], + parser['colored_output'], parser['common'], parser['inventory_common']]) parser['add-host'].add_argument( @@ -308,13 +326,12 @@ def get_parsers(): parser['add-host'].add_argument( '-f', '--file', help=('Read additional hosts to add from specified file ' - 'or from stdin if \'-\' (each host on separate line). ' - 'If no host or host file is specified then, by default, ' - 'read from stdin.'), + 'or from stdin if \'-\' (each host on separate line). '), dest='hostfile', required=False) parser['add-tag'] = parser['invsub'].add_parser( 'add-tag', parents=[parser['loglevel'], parser['beta'], + parser['colored_output'], parser['common'], parser['inventory_common']]) parser['add-tag'].add_argument( @@ -323,20 +340,12 @@ def get_parsers(): parser['add-tag'].add_argument( '-f', '--file', help=('Read additional hosts to add tags from specified file ' - 'or from stdin if \'-\' (each host on separate line). ' - 'If no host or host file is specified then, by default, ' - 'read from stdin. If no tags/tagfile nor hosts/hostfile' - ' are specified then tags are read from stdin and are' - ' added to all hosts.'), + 'or from stdin if \'-\' (each host on separate line). '), dest='hostfile', required=False) parser['add-tag'].add_argument( '-T', '--tag-file', help=('Read additional tags to add from specified file ' - 'or from stdin if \'-\' (each tag on separate line). ' - 'If no tag or tag file is specified then, by default, ' - 'read from stdin. If no tags/tagfile nor hosts/hostfile' - ' are specified then tags are read from stdin and are' - ' added to all hosts.'), + 'or from stdin if \'-\' (each tag on separate line). '), dest='tagfile', required=False) parser['add-tag'].add_argument( '-t', '--taglist', @@ -346,6 +355,7 @@ def get_parsers(): parser['del-host'] = parser['invsub'].add_parser( 'del-host', parents=[parser['loglevel'], parser['beta'], + parser['colored_output'], parser['common'], parser['inventory_common']]) parser['del-host'].add_argument( @@ -356,13 +366,12 @@ def get_parsers(): parser['del-host'].add_argument( '-f', '--file', help=('Read additional hosts to delete from specified file ' - 'or from stdin if \'-\' (each host on separate line). ' - 'If no host or host file is specified then, by default, ' - 'read from stdin.'), + 'or from stdin if \'-\' (each host on separate line). '), dest='hostfile', required=False) parser['del-tag'] = parser['invsub'].add_parser( 'del-tag', parents=[parser['loglevel'], parser['beta'], + parser['colored_output'], parser['common'], parser['inventory_common']]) parser['del-tag'].add_argument( @@ -375,20 +384,13 @@ def get_parsers(): parser['del-tag'].add_argument( '-f', '--file', help=('Read additional hosts to delete tags for from specified ' - 'file or from stdin if \'-\' (each host on separate line). ' - 'If no host or host file is specified then, by default, ' - 'read from stdin. If no tags/tagfile nor hosts/hostfile' - ' are specified then tags are read from stdin and are' - ' deleted from all hosts.'), + 'file or from stdin if \'-\' (each host on separate ' + 'line). '), dest='hostfile', required=False) parser['del-tag'].add_argument( '-T', '--tag-file', help=('Read additional tags from specified file ' - 'or from stdin if \'-\' (each tag on separate line). ' - 'If no tag or tag file is specified then, by default, ' - 'read from stdin. If no tags/tagfile nor' - ' hosts/hostfile are specified then tags are read from' - ' stdin and are added to all hosts.'), + 'or from stdin if \'-\' (each tag on separate line). '), dest='tagfile', required=False) parser['del-tag'].add_argument( '-t', '--taglist', @@ -398,6 +400,7 @@ def get_parsers(): parser['list'] = parser['invsub'].add_parser( 'list', parents=[parser['loglevel'], parser['beta'], + parser['colored_output'], parser['common'], parser['inventory_common']]) parser['list'].add_argument( @@ -430,7 +433,7 @@ def get_parsers(): # Shell parser['shell'] = parser['sub'].add_parser( - 'shell', parents=[parser['loglevel']]) + 'shell', parents=[parser['loglevel'], parser['colored_output']]) parser['shell'].add_argument( '-s', '--shell', help=('Select shell to use, defaults to current shell. Used shell' @@ -468,6 +471,35 @@ def get_parsers(): 'pattern', nargs='?', help='Glob pattern.') parser['info'].set_defaults(func=cdist.info.Info.commandline) + # Scan = config + further + parser['scan'] = parser['sub'].add_parser('scan', add_help=False, + parents=[parser['config']]) + + parser['scan'] = parser['sub'].add_parser( + 'scan', parents=[parser['loglevel'], + parser['beta'], + parser['colored_output'], + parser['common'], + parser['config_main']]) + + parser['scan'].add_argument( + '-m', '--mode', help='Which modes should run', + action='append', default=[], + choices=['scan', 'trigger']) + parser['scan'].add_argument( + '--config', + action='store_true', + help='Try to configure detected hosts') + parser['scan'].add_argument( + '-I', '--interfaces', + action='append', default=[], + help='On which interfaces to scan/trigger') + parser['scan'].add_argument( + '-d', '--delay', + action='store', default=3600, + help='How long to wait before reconfiguring after last try') + parser['scan'].set_defaults(func=cdist.scan.commandline.commandline) + for p in parser: parser[p].epilog = EPILOG @@ -478,7 +510,12 @@ def handle_loglevel(args): if hasattr(args, 'quiet') and args.quiet: args.verbose = _verbosity_level_off - logging.root.setLevel(_verbosity_level[args.verbose]) + logging.getLogger().setLevel(_verbosity_level[args.verbose]) + + +def handle_log_colors(args): + if cdist.configuration.ColoredOutputOption.translate(args.colored_output): + cdist.log.CdistFormatter.USE_COLORS = True def parse_and_configure(argv, singleton=True): @@ -492,6 +529,7 @@ def parse_and_configure(argv, singleton=True): raise cdist.Error(str(e)) # Loglevels are handled globally in here handle_loglevel(args) + handle_log_colors(args) log = logging.getLogger("cdist") diff --git a/cdist/conf/explorer/cpu_cores b/cdist/conf/explorer/cpu_cores index a52bddac..81e5294e 100755 --- a/cdist/conf/explorer/cpu_cores +++ b/cdist/conf/explorer/cpu_cores @@ -32,6 +32,11 @@ case "$os" in sysctl -n hw.ncpuonline ;; + "freebsd"|"netbsd") + PATH=$(getconf PATH) + sysctl -n hw.ncpu + ;; + *) if [ -r /proc/cpuinfo ]; then cores="$(grep "core id" /proc/cpuinfo | sort | uniq | wc -l)" diff --git a/cdist/conf/explorer/disks b/cdist/conf/explorer/disks index 87a6b5c6..56d62d10 100755 --- a/cdist/conf/explorer/disks +++ b/cdist/conf/explorer/disks @@ -1,27 +1,66 @@ -#!/bin/sh +#!/bin/sh -e +# +# based on previous work by other people, modified by: +# 2020 Dennis Camera +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# Finds disks of the system (excl. ram disks, floppy, cdrom) uname_s="$(uname -s)" -case "${uname_s}" in +case $uname_s in FreeBSD) sysctl -n kern.disks ;; - OpenBSD|NetBSD) - sysctl -n hw.disknames | grep -Eo '[lsw]d[0-9]+' | xargs + OpenBSD) + sysctl -n hw.disknames | grep -Eo '[lsw]d[0-9]+' + ;; + NetBSD) + PATH=$(getconf PATH) + sysctl -n hw.disknames | awk -v RS=' ' '/^[lsw]d[0-9]+/' ;; Linux) - if command -v lsblk > /dev/null + # list of major device numbers toexclude: + # ram disks, floppies, cdroms + # https://www.kernel.org/doc/Documentation/admin-guide/devices.txt + ign_majors='1 2 11' + + if command -v lsblk >/dev/null 2>&1 then - # exclude ram disks, floppies and cdroms - # https://www.kernel.org/doc/Documentation/admin-guide/devices.txt - lsblk -e 1,2,11 -dno name | xargs + lsblk -e "$(echo "$ign_majors" | tr ' ' ',')" -dno name + elif test -d /sys/block/ + then + # shellcheck disable=SC2012 + ls -1 /sys/block/ \ + | awk -v ign_majors="$(echo "$ign_majors" | tr ' ' '|')" ' + { + devfile = "/sys/block/" $0 "/dev" + getline devno < devfile + close(devfile) + if (devno !~ "^(" ign_majors "):") print + }' else - printf "Don't know how to list disks for %s operating system without lsblk, if you can please submit a patch\n" "${uname_s}" >&2 + echo "Don't know how to list disks on Linux without lsblk and sysfs." >&2 + echo 'If you can, please submit a patch.'>&2 fi ;; *) - printf "Don't know how to list disks for %s operating system, if you can please submit a patch\n" "${uname_s}" >&2 + printf "Don't know how to list disks for %s operating system.\n" "${uname_s}" >&2 + printf 'If you can please submit a patch\n' >&2 ;; -esac - -exit 0 +esac \ +| xargs diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index 1b921c68..f27c77ef 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -221,6 +221,7 @@ check_systemstarter() { check_sysvinit() ( init_path=${1:-/sbin/init} + test -x "${init_path}" || return 1 grep -q 'INIT_VERSION=sysvinit-[0-9.]*' "${init_path}" || return 1 # It is quite common to use SysVinit to stack other init systemd diff --git a/cdist/conf/explorer/machine_type b/cdist/conf/explorer/machine_type index bb21f69c..1c84f4d7 100755 --- a/cdist/conf/explorer/machine_type +++ b/cdist/conf/explorer/machine_type @@ -2,6 +2,7 @@ # # 2014 Daniel Heule (hda at sfs.biz) # 2014 Thomas Oettli (otho at sfs.biz) +# 2020 Evilham (contact at evilham.com) # # This file is part of cdist. # @@ -18,63 +19,91 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # -# -# FIXME: other system types (not linux ...) +os=$("$__explorer/os") -if [ -d "/proc/vz" ] && [ ! -d "/proc/bc" ]; then - echo openvz - exit -fi - -if [ -e "/proc/1/environ" ] && - tr '\000' '\n' < "/proc/1/environ" | grep -Eiq '^container='; then - echo lxc - exit -fi - -if [ -r /proc/cpuinfo ]; then - # this should only exist on virtual guest machines, - # tested on vmware, xen, kvm - if grep -q "hypervisor" /proc/cpuinfo; then - # this file is aviable in xen guest systems - if [ -r /sys/hypervisor/type ]; then - if grep -q -i "xen" /sys/hypervisor/type; then - echo virtual_by_xen - exit +vendor_string_to_machine_type() { + for vendor in vmware bochs kvm qemu virtualbox bhyve; do + if echo "${1}" | grep -q -i "${vendor}"; then + if [ "${vendor}" = "bochs" ] || [ "${vendor}" = "qemu" ]; then + vendor="kvm" fi - else - if [ -r /sys/class/dmi/id/product_name ]; then - if grep -q -i 'vmware' /sys/class/dmi/id/product_name; then - echo "virtual_by_vmware" - exit - elif grep -q -i 'bochs' /sys/class/dmi/id/product_name; then - echo "virtual_by_kvm" - exit - elif grep -q -i 'virtualbox' /sys/class/dmi/id/product_name; then - echo "virtual_by_virtualbox" - exit - fi - fi - - if [ -r /sys/class/dmi/id/sys_vendor ]; then - if grep -q -i 'qemu' /sys/class/dmi/id/sys_vendor; then - echo "virtual_by_kvm" - exit - fi - fi - - if [ -r /sys/class/dmi/id/chassis_vendor ]; then - if grep -q -i 'qemu' /sys/class/dmi/id/chassis_vendor; then - echo "virtual_by_kvm" - exit - fi - fi + echo "virtual_by_${vendor}" + exit fi - echo "virtual_by_unknown" - else - echo "physical" - fi -else - echo "unknown" -fi + done +} + +case "$os" in + "freebsd") + # FreeBSD does not have /proc/cpuinfo even when procfs is used. + # Instead there is a sysctl kern.vm_guest. + # Which is 'none' if physical, else the virtualisation. + vm_guest="$(sysctl -n kern.vm_guest 2>/dev/null || true)" + if [ -n "${vm_guest}" ]; then + if [ "${vm_guest}" = "none" ]; then + echo "physical" + exit + fi + echo "virtual_by_${vm_guest}" + exit + fi + ;; + + "openbsd") + # OpenBSD can also use the sysctl's: hw.vendor or hw.product. + # Note we can be reasonably sure about a machine being virtualised + # as long as we can identify the virtualisation technology. + # But not so much about it being physical... + # Patches are welcome / reach out if you have better ideas. + for sysctl in hw.vendor hw.product; do + # This exits if we can make a reasonable judgement + vendor_string_to_machine_type "$(sysctl -n "${sysctl}")" + done + ;; + + *) + # Defaulting to linux for compatibility with previous cdist behaviour + + if [ -d "/proc/vz" ] && [ ! -d "/proc/bc" ]; then + echo openvz + exit + fi + + if [ -e "/proc/1/environ" ] && + tr '\000' '\n' < "/proc/1/environ" | grep -Eiq '^container='; then + echo lxc + exit + fi + + if [ -r /proc/cpuinfo ]; then + # this should only exist on virtual guest machines, + # tested on vmware, xen, kvm, bhyve + if grep -q "hypervisor" /proc/cpuinfo; then + # this file is aviable in xen guest systems + if [ -r /sys/hypervisor/type ]; then + if grep -q -i "xen" /sys/hypervisor/type; then + echo virtual_by_xen + exit + fi + else + for vendor_file in /sys/class/dmi/id/product_name \ + /sys/class/dmi/id/sys_vendor \ + /sys/class/dmi/id/chasis_vendor; do + if [ -r ${vendor_file} ]; then + # This exits if we can make a reasonable judgement + vendor_string_to_machine_type "$(cat "${vendor_file}")" + fi + done + fi + echo "virtual_by_unknown" + exit + else + echo "physical" + exit + fi + fi + ;; +esac + +echo "unknown" diff --git a/cdist/conf/explorer/memory b/cdist/conf/explorer/memory index 4e3efff8..5ea15ada 100755 --- a/cdist/conf/explorer/memory +++ b/cdist/conf/explorer/memory @@ -29,7 +29,8 @@ case "$os" in echo "$(sysctl -n hw.memsize)/1024" | bc ;; - "openbsd") + *"bsd") + PATH=$(getconf PATH) echo "$(sysctl -n hw.physmem) / 1048576" | bc ;; diff --git a/cdist/conf/explorer/os b/cdist/conf/explorer/os index 563fa4cf..46d87f3e 100755 --- a/cdist/conf/explorer/os +++ b/cdist/conf/explorer/os @@ -143,6 +143,13 @@ case "$uname_s" in esac if [ -f /etc/os-release ]; then + # after sles15, suse don't provide an /etc/SuSE-release anymore, but there is almost no difference between sles and opensuse leap, so call it suse + # shellcheck disable=SC1091 + if (. /etc/os-release && echo "${ID_LIKE}" | grep -q '\(^\|\ \)suse\($\|\ \)') + then + echo suse + exit 0 + fi # already lowercase, according to: # https://www.freedesktop.org/software/systemd/man/os-release.html awk -F= '/^ID=/ { if ($2 ~ /^'"'"'(.*)'"'"'$/ || $2 ~ /^"(.*)"$/) { print substr($2, 2, length($2) - 2) } else { print $2 } }' /etc/os-release diff --git a/cdist/conf/explorer/os_version b/cdist/conf/explorer/os_version index 1d54ea60..3b02dedd 100755 --- a/cdist/conf/explorer/os_version +++ b/cdist/conf/explorer/os_version @@ -31,7 +31,32 @@ case "$("$__explorer/os")" in cat /etc/arch-release ;; debian) - cat /etc/debian_version + debian_version=$(cat /etc/debian_version) + case $debian_version + in + testing/unstable) + # previous to Debian 4.0 testing/unstable was used + # cf. https://metadata.ftp-master.debian.org/changelogs/main/b/base-files/base-files_11_changelog + echo 3.99 + ;; + */sid) + # sid versions don't have a number, so we decode by codename: + case $(expr "$debian_version" : '\([a-z]\{1,\}\)/') + in + bullseye) echo 10.99 ;; + buster) echo 9.99 ;; + stretch) echo 8.99 ;; + jessie) echo 7.99 ;; + wheezy) echo 6.99 ;; + squeeze) echo 5.99 ;; + lenny) echo 4.99 ;; + *) exit 1 + esac + ;; + *) + echo "$debian_version" + ;; + esac ;; devuan) cat /etc/devuan_version @@ -45,6 +70,11 @@ case "$("$__explorer/os")" in macosx) sw_vers -productVersion ;; + freebsd) + # Apparently uname -r is not a reliable way to get the patch level. + # See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=251743 + freebsd-version + ;; *bsd|solaris) uname -r ;; @@ -73,4 +103,4 @@ case "$("$__explorer/os")" in alpine) cat /etc/alpine-release ;; -esac \ No newline at end of file +esac diff --git a/cdist/conf/type/__acl/explorer/getent b/cdist/conf/type/__acl/explorer/getent new file mode 100755 index 00000000..7e6c2c30 --- /dev/null +++ b/cdist/conf/type/__acl/explorer/getent @@ -0,0 +1,4 @@ +#!/bin/sh -e + +getent passwd | awk -F: '{print "user:"$1}' +getent group | awk -F: '{print "group:"$1}' diff --git a/cdist/conf/type/__acl/gencode-remote b/cdist/conf/type/__acl/gencode-remote index e5404a9d..32318e91 100755 --- a/cdist/conf/type/__acl/gencode-remote +++ b/cdist/conf/type/__acl/gencode-remote @@ -22,8 +22,8 @@ file_is="$( cat "$__object/explorer/file_is" )" if [ "$file_is" = 'missing' ] \ && [ -z "$__cdist_dry_run" ] \ - && \( [ ! -f "$__object/parameter/file" ] \ - || [ ! -f "$__object/parameter/directory" ] \) + && [ ! -f "$__object/parameter/file" ] \ + && [ ! -f "$__object/parameter/directory" ] then exit 0 fi @@ -47,28 +47,26 @@ then elif [ -f "$__object/parameter/entry" ] then acl_should="$( cat "$__object/parameter/entry" )" -elif [ -f "$__object/parameter/acl" ] -then - acl_should="$( cat "$__object/parameter/acl" )" -elif - [ -f "$__object/parameter/user" ] \ - || [ -f "$__object/parameter/group" ] \ - || [ -f "$__object/parameter/mask" ] \ - || [ -f "$__object/parameter/other" ] -then - acl_should="$( for param in user group mask other - do - [ ! -f "$__object/parameter/$param" ] && continue - - echo "$param" | grep -Eq 'mask|other' && sep=:: || sep=: - - echo "$param$sep$( cat "$__object/parameter/$param" )" - done )" else echo 'no parameters set' >&2 exit 1 fi +# instead of setfacl's non-helpful message "Option -m: Invalid argument near character X" +# let's check if target has necessary users and groups, since mistyped or missing +# users/groups in target is most common reason. +echo "$acl_should" \ + | grep -Po '(user|group):[^:]+' \ + | sort -u \ + | while read -r l + do + if ! grep "$l" -Fxq "$__object/explorer/getent" + then + echo "no $l' in target" | sed "s/:/ '/" >&2 + exit 1 + fi + done + if [ -f "$__object/parameter/default" ] then acl_should="$( echo "$acl_should" \ diff --git a/cdist/conf/type/__acl/man.rst b/cdist/conf/type/__acl/man.rst index 28412871..307be72b 100644 --- a/cdist/conf/type/__acl/man.rst +++ b/cdist/conf/type/__acl/man.rst @@ -12,11 +12,14 @@ Fully supported and tested on Linux (ext4 filesystem), partial support for FreeB See ``setfacl`` and ``acl`` manpages for more details. +One of ``--entry`` or ``--source`` must be used. -REQUIRED MULTIPLE PARAMETERS + +OPTIONAL MULTIPLE PARAMETERS ---------------------------- entry Set ACL entry following ``getfacl`` output syntax. + Must be used if ``--source`` is not used. OPTIONAL PARAMETERS @@ -25,6 +28,7 @@ source Read ACL entries from stdin or file. Ordering of entries is not important. When reading from file, comments and empty lines are ignored. + Must be used if ``--entry`` is not used. file Create/change file with ``__file`` using ``user:group:mode`` pattern. @@ -48,12 +52,6 @@ remove ``mask`` and ``other`` entries can't be removed, but only changed. -DEPRECATED PARAMETERS ---------------------- -Parameters ``acl``, ``user``, ``group``, ``mask`` and ``other`` are deprecated and they -will be removed in future versions. Please use ``entry`` parameter instead. - - EXAMPLES -------- diff --git a/cdist/conf/type/__acl/parameter/deprecated/acl b/cdist/conf/type/__acl/parameter/deprecated/acl deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/acl +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/group b/cdist/conf/type/__acl/parameter/deprecated/group deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/group +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/mask b/cdist/conf/type/__acl/parameter/deprecated/mask deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/mask +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/other b/cdist/conf/type/__acl/parameter/deprecated/other deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/other +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/deprecated/user b/cdist/conf/type/__acl/parameter/deprecated/user deleted file mode 100644 index 94e14159..00000000 --- a/cdist/conf/type/__acl/parameter/deprecated/user +++ /dev/null @@ -1 +0,0 @@ -see manual for details diff --git a/cdist/conf/type/__acl/parameter/optional b/cdist/conf/type/__acl/parameter/optional index cdcbc0b8..5a0c29a3 100644 --- a/cdist/conf/type/__acl/parameter/optional +++ b/cdist/conf/type/__acl/parameter/optional @@ -1,5 +1,3 @@ -mask -other source file directory diff --git a/cdist/conf/type/__acl/parameter/optional_multiple b/cdist/conf/type/__acl/parameter/optional_multiple index c615d507..4c884f03 100644 --- a/cdist/conf/type/__acl/parameter/optional_multiple +++ b/cdist/conf/type/__acl/parameter/optional_multiple @@ -1,4 +1 @@ entry -acl -user -group diff --git a/cdist/conf/type/__apt_backports/man.rst b/cdist/conf/type/__apt_backports/man.rst new file mode 100644 index 00000000..7036fb84 --- /dev/null +++ b/cdist/conf/type/__apt_backports/man.rst @@ -0,0 +1,104 @@ +cdist-type__debian_backports(7) +=============================== + +NAME +---- +cdist-type__apt_backports - Install backports + + +DESCRIPTION +----------- +This singleton type installs backports for the current OS release. +It aborts if backports are not supported for the specified OS or +no version codename could be fetched (like Debian unstable). + +The package index will be automatically updated if required. + +It supports backports from following OSes: + +- Debian +- Devuan +- Ubuntu + + +REQUIRED PARAMETERS +------------------- +None. + + +OPTIONAL PARAMETERS +------------------- +state + Represents the state of the backports repository. ``present`` or + ``absent``, defaults to ``present``. + + Will be directly passed to :strong:`cdist-type__apt_source`\ (7). + +mirror + The mirror to fetch the backports from. Will defaults to the generic + mirror of the current OS. + + Will be directly passed to :strong:`cdist-type__apt_source`\ (7). + + +BOOLEAN PARAMETERS +------------------ +None. + + +MESSAGES +-------- +None. + + +EXAMPLES +-------- + +.. code-block:: sh + + # setup the backports + __apt_backports + __apt_backports --state absent + __apt_backports --state present --mirror "http://ftp.de.debian.org/debian/" + + # install a backports package + # currently for the buster release backports + require="__apt_backports" __package_apt wireguard \ + --target-release buster-backports + + +ABORTS +------ +Aborts if the detected os is not Debian. + +Aborts if no distribuition codename could be detected. This is common for the +unstable distribution, but there is no backports repository for it already. + + +CAVEATS +------- +For Ubuntu, it setup all componenents for the backports repository: ``main``, +``restricted``, ``universe`` and ``multiverse``. The user may not want to +install proprietary packages, which will only be installed if the user +explicitly uses the backports target-release. The user may change this behavior +to install backports packages without the need of explicitly select it. + + +SEE ALSO +-------- +`Official Debian Backports site `_ + +:strong:`cdist-type__apt_source`\ (7) + + +AUTHORS +------- +Matthias Stecher + + +COPYING +------- +Copyright \(C) 2020 Matthias Stecher. You can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. diff --git a/cdist/conf/type/__apt_backports/manifest b/cdist/conf/type/__apt_backports/manifest new file mode 100755 index 00000000..bc47d8de --- /dev/null +++ b/cdist/conf/type/__apt_backports/manifest @@ -0,0 +1,81 @@ +#!/bin/sh -e +# __apt_backports/manifest +# +# 2020 Matthias Stecher (matthiasstecher at gmx.de) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# +# Enables/disables backports repository. Utilises __apt_source for it. +# + + +# Get the distribution codename by /etc/os-release. +# is already executed in a subshell by string substitution +# lsb_release may not be given in all installations +codename_os_release() { + # shellcheck disable=SC1090 + . "$__global/explorer/os_release" + printf "%s" "$VERSION_CODENAME" +} + +# detect backport distribution +os="$(cat "$__global/explorer/os")" +case "$os" in + debian) + dist="$( codename_os_release )" + components="main" + mirror="http://deb.debian.org/debian/" + ;; + devuan) + dist="$( codename_os_release )" + components="main" + mirror="http://deb.devuan.org/merged" + ;; + ubuntu) + dist="$( codename_os_release )" + components="main restricted universe multiverse" + mirror="http://archive.ubuntu.com/ubuntu" + ;; + + *) + printf "Backports for %s are not supported!\n" "$os" >&2 + exit 1 + ;; +esac + +# error if no codename given (e.g. on Debian unstable) +if [ -z "$dist" ]; then + printf "No backports for unkown version of distribution %s!\n" "$os" >&2 + exit 1 +fi + + +# parameters +state="$(cat "$__object/parameter/state")" + +# mirror already set for the os, only override user-values +if [ -f "$__object/parameter/mirror" ]; then + mirror="$(cat "$__object/parameter/mirror")" +fi + + +# install the given backports repository +__apt_source "${dist}-backports" \ + --state "$state" \ + --distribution "${dist}-backports" \ + --component "$components" \ + --uri "$mirror" diff --git a/cdist/conf/type/__apt_backports/parameter/default/state b/cdist/conf/type/__apt_backports/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__apt_backports/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__apt_backports/parameter/optional b/cdist/conf/type/__apt_backports/parameter/optional new file mode 100644 index 00000000..4b05c235 --- /dev/null +++ b/cdist/conf/type/__apt_backports/parameter/optional @@ -0,0 +1,2 @@ +state +mirror diff --git a/cdist/conf/type/__coturn/singleton b/cdist/conf/type/__apt_backports/singleton similarity index 100% rename from cdist/conf/type/__coturn/singleton rename to cdist/conf/type/__apt_backports/singleton diff --git a/cdist/conf/type/__apt_norecommends/man.rst b/cdist/conf/type/__apt_norecommends/man.rst index 001fffe4..9297b518 100644 --- a/cdist/conf/type/__apt_norecommends/man.rst +++ b/cdist/conf/type/__apt_norecommends/man.rst @@ -32,11 +32,12 @@ EXAMPLES AUTHORS ------- Steven Armstrong +Dennis Camera COPYING ------- -Copyright \(C) 2014 Steven Armstrong. You can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. +Copyright \(C) 2014 Steven Armstrong, 2020 Dennis Camera. +You can redistribute it and/or modify it under the terms of the GNU General +Public License as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. diff --git a/cdist/conf/type/__apt_norecommends/manifest b/cdist/conf/type/__apt_norecommends/manifest index e737df89..fc187784 100755 --- a/cdist/conf/type/__apt_norecommends/manifest +++ b/cdist/conf/type/__apt_norecommends/manifest @@ -1,6 +1,7 @@ #!/bin/sh -e # # 2014 Steven Armstrong (steven-cdist at armstrong.cc) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -19,26 +20,28 @@ # -os=$(cat "$__global/explorer/os") +os=$(cat "${__global:?}/explorer/os") -case "$os" in - ubuntu|debian|devuan) - # No stinking recommends thank you very much. - # If I want something installed I will do so myself. - __file /etc/apt/apt.conf.d/99-no-recommends \ - --owner root --group root --mode 644 \ - --source - << DONE -APT::Install-Recommends "0"; -APT::Install-Suggests "0"; -APT::AutoRemove::RecommendsImportant "0"; -APT::AutoRemove::SuggestsImportant "0"; -DONE - ;; - *) - cat >&2 << DONE +case ${os} +in + (ubuntu|debian|devuan) + __file /etc/apt/apt.conf.d/00InstallRecommends --state present \ + --owner root --group root --mode 0644 --source - <<-'EOF' + APT::Install-Recommends "false"; + APT::Install-Suggests "false"; + APT::AutoRemove::RecommendsImportant "false"; + APT::AutoRemove::SuggestsImportant "false"; + EOF + + # TODO: Remove the following object after some time + require=__file/etc/apt/apt.conf.d/00InstallRecommends \ + __file /etc/apt/apt.conf.d/99-no-recommends --state absent + ;; + (*) + cat >&2 < "\$tmpfile" -mv -f "\$tmpfile" "$file" +}' $quoted_file > "\$tmpfile" +mv -f "\$tmpfile" $quoted_file DONE } +quoted_file="$(quote "$file")" case "$state_should" in present) if [ "$state_is" = "changed" ]; then @@ -77,7 +78,7 @@ case "$state_should" in echo add >> "$__messages_out" fi cat << DONE -cat >> "$file" << ${__type##*/}_DONE +cat >> $quoted_file << '${__type##*/}_DONE' $(cat "$block") ${__type##*/}_DONE DONE diff --git a/cdist/conf/type/__cdist/manifest b/cdist/conf/type/__cdist/manifest index a97cf288..0b0f1263 100755 --- a/cdist/conf/type/__cdist/manifest +++ b/cdist/conf/type/__cdist/manifest @@ -37,6 +37,7 @@ source="$(cat "$__object/parameter/source")" # out of it home=/home/$username +# shellcheck disable=SC2086 __user "$username" --home "$home" $shell require="__user/$username" __directory "$home" \ diff --git a/cdist/conf/type/__clean_path/explorer/list b/cdist/conf/type/__clean_path/explorer/list index 07d38127..2bdc63a5 100755 --- a/cdist/conf/type/__clean_path/explorer/list +++ b/cdist/conf/type/__clean_path/explorer/list @@ -18,7 +18,12 @@ # along with cdist. If not, see . # -path="/$__object_id" +if [ -f "$__object/parameter/path" ] +then + path="$( cat "$__object/parameter/path" )" +else + path="/$__object_id" +fi [ ! -d "$path" ] && exit 0 diff --git a/cdist/conf/type/__clean_path/gencode-remote b/cdist/conf/type/__clean_path/gencode-remote index 998a70d8..2899c4a5 100755 --- a/cdist/conf/type/__clean_path/gencode-remote +++ b/cdist/conf/type/__clean_path/gencode-remote @@ -20,7 +20,12 @@ [ ! -s "$__object/explorer/list" ] && exit 0 -path="/$__object_id" +if [ -f "$__object/parameter/path" ] +then + path="$( cat "$__object/parameter/path" )" +else + path="/$__object_id" +fi pattern="$( cat "$__object/parameter/pattern" )" diff --git a/cdist/conf/type/__clean_path/man.rst b/cdist/conf/type/__clean_path/man.rst index 826f4589..31d90701 100644 --- a/cdist/conf/type/__clean_path/man.rst +++ b/cdist/conf/type/__clean_path/man.rst @@ -10,7 +10,7 @@ DESCRIPTION ----------- Remove files and directories which match the pattern. -Provided path (as __object_id) must be a directory. +Provided path must be a directory. Patterns are passed to ``find``'s ``-regex`` - see ``find(1)`` for more details. @@ -29,6 +29,9 @@ pattern OPTIONAL PARAMETERS ------------------- +path + Path which will be cleaned. Defaults to ``$__object_id``. + exclude Pattern of files which are excluded from removal. @@ -46,6 +49,11 @@ EXAMPLES --exclude '.+\(charset\.conf\|security\.conf\)' \ --onchange 'service apache2 restart' + __clean_path apache2-conf-enabled \ + --path /etc/apache2/conf-enabled \ + --pattern '.+' \ + --exclude '.+\(charset\.conf\|security\.conf\)' \ + --onchange 'service apache2 restart' AUTHORS ------- diff --git a/cdist/conf/type/__clean_path/parameter/optional b/cdist/conf/type/__clean_path/parameter/optional index 6f313474..3b97f71c 100644 --- a/cdist/conf/type/__clean_path/parameter/optional +++ b/cdist/conf/type/__clean_path/parameter/optional @@ -1,2 +1,3 @@ exclude onchange +path diff --git a/cdist/conf/type/__consul_agent/manifest b/cdist/conf/type/__consul_agent/manifest index 0d819d45..7b54529c 100755 --- a/cdist/conf/type/__consul_agent/manifest +++ b/cdist/conf/type/__consul_agent/manifest @@ -1,7 +1,7 @@ #!/bin/sh -e # # 2015 Steven Armstrong (steven-cdist at armstrong.cc) -# 2015-2019 Nico Schottelius (nico-cdist at schottelius.org) +# 2015-2020 Nico Schottelius (nico-cdist at schottelius.org) # 2019 Timothée Floure (timothee.floure at ungleich.ch) # # This file is part of cdist. @@ -37,10 +37,22 @@ fi # Those are default that might be overriden by os-specific logic. data_dir="/var/lib/consul" -conf_dir="/etc/consul/conf.d" -conf_file="config.json" + + + tls_dir="$conf_dir/tls" +case "$os" in + alpine) + conf_dir="/etc/consul" + conf_file="server.json" + ;; + *) + conf_dir="/etc/consul/conf.d" + conf_file="config.json" + ;; +esac + ### # Sane deployment, based on distribution package when available. @@ -220,7 +232,7 @@ if [ -f "$__object/parameter/ca-file-source" ] || \ [ -f "$__object/parameter/cert-file-source" ] || \ [ -f "$__object/parameter/key-file-source" ]; then - requires="$config_deployment_requires" __directory $tls_dir \ + requires="$config_deployment_requires" __directory "$tls_dir" \ --owner root --group "$group" --mode 750 --state "$state" # Append to service restart requirements. diff --git a/cdist/conf/type/__coturn/files/turnserver.conf.sh b/cdist/conf/type/__coturn/files/turnserver.conf.sh deleted file mode 100755 index 0e2f2995..00000000 --- a/cdist/conf/type/__coturn/files/turnserver.conf.sh +++ /dev/null @@ -1,744 +0,0 @@ -#!/bin/sh - -generate_use_auth_secret () { - if [ $USE_AUTH_SECRET ]; then - echo 'use-auth-secret' - else - echo '#use-auth-secret' - fi -} - -generate_static_auth_secret () { - if [ "$STATIC_AUTH_SECRET" $! "" ]; then - echo "static-auth-secret=$STATIC_AUTH_SECRET" - else - echo "#static-auth-secret=north" - fi -} - -generate_realm () { - if [ "$REALM" != "" ]; then - echo "realm=$REALM" - else - echo "#realm=mycompany.org" - fi -} - -generate_no_tcp_relay () { - if [ $NO_TCP_RELAY ]; then - echo 'no-tcp-releay' - else - echo '#no-tcp-relay' - fi -} - -cat << EOF -# Coturn TURN SERVER configuration file -# -# Boolean values note: where boolean value is supposed to be used, -# you can use '0', 'off', 'no', 'false', 'f' as 'false, -# and you can use '1', 'on', 'yes', 'true', 't' as 'true' -# If the value is missed, then it means 'true'. -# - -# Listener interface device (optional, Linux only). -# NOT RECOMMENDED. -# -#listening-device=eth0 - -# TURN listener port for UDP and TCP (Default: 3478). -# Note: actually, TLS & DTLS sessions can connect to the -# "plain" TCP & UDP port(s), too - if allowed by configuration. -# -#listening-port=3478 - -# TURN listener port for TLS (Default: 5349). -# Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS -# port(s), too - if allowed by configuration. The TURN server -# "automatically" recognizes the type of traffic. Actually, two listening -# endpoints (the "plain" one and the "tls" one) are equivalent in terms of -# functionality; but we keep both endpoints to satisfy the RFC 5766 specs. -# For secure TCP connections, we currently support SSL version 3 and -# TLS version 1.0, 1.1 and 1.2. -# For secure UDP connections, we support DTLS version 1. -# -#tls-listening-port=5349 - -# Alternative listening port for UDP and TCP listeners; -# default (or zero) value means "listening port plus one". -# This is needed for RFC 5780 support -# (STUN extension specs, NAT behavior discovery). The TURN Server -# supports RFC 5780 only if it is started with more than one -# listening IP address of the same family (IPv4 or IPv6). -# RFC 5780 is supported only by UDP protocol, other protocols -# are listening to that endpoint only for "symmetry". -# -#alt-listening-port=0 - -# Alternative listening port for TLS and DTLS protocols. -# Default (or zero) value means "TLS listening port plus one". -# -#alt-tls-listening-port=0 - -# Listener IP address of relay server. Multiple listeners can be specified. -# If no IP(s) specified in the config file or in the command line options, -# then all IPv4 and IPv6 system IPs will be used for listening. -# -#listening-ip=172.17.19.101 -#listening-ip=10.207.21.238 -#listening-ip=2607:f0d0:1002:51::4 - -# Auxiliary STUN/TURN server listening endpoint. -# Aux servers have almost full TURN and STUN functionality. -# The (minor) limitations are: -# -# 1) Auxiliary servers do not have alternative ports and -# they do not support STUN RFC 5780 functionality (CHANGE REQUEST). -# -# 2) Auxiliary servers also are never returning ALTERNATIVE-SERVER reply. -# -# Valid formats are 1.2.3.4:5555 for IPv4 and [1:2::3:4]:5555 for IPv6. -# -# There may be multiple aux-server options, each will be used for listening -# to client requests. -# -#aux-server=172.17.19.110:33478 -#aux-server=[2607:f0d0:1002:51::4]:33478 - -# (recommended for older Linuxes only) -# Automatically balance UDP traffic over auxiliary servers (if configured). -# The load balancing is using the ALTERNATE-SERVER mechanism. -# The TURN client must support 300 ALTERNATE-SERVER response for this -# functionality. -# -#udp-self-balance - -# Relay interface device for relay sockets (optional, Linux only). -# NOT RECOMMENDED. -# -#relay-device=eth1 - -# Relay address (the local IP address that will be used to relay the -# packets to the peer). -# Multiple relay addresses may be used. -# The same IP(s) can be used as both listening IP(s) and relay IP(s). -# -# If no relay IP(s) specified, then the turnserver will apply the default -# policy: it will decide itself which relay addresses to be used, and it -# will always be using the client socket IP address as the relay IP address -# of the TURN session (if the requested relay address family is the same -# as the family of the client socket). -# -#relay-ip=172.17.19.105 -#relay-ip=2607:f0d0:1002:51::5 - -# For Amazon EC2 users: -# -# TURN Server public/private address mapping, if the server is behind NAT. -# In that situation, if a -X is used in form "-X " then that ip will be reported -# as relay IP address of all allocations. This scenario works only in a simple case -# when one single relay address is be used, and no RFC5780 functionality is required. -# That single relay address must be mapped by NAT to the 'external' IP. -# The "external-ip" value, if not empty, is returned in XOR-RELAYED-ADDRESS field. -# For that 'external' IP, NAT must forward ports directly (relayed port 12345 -# must be always mapped to the same 'external' port 12345). -# -# In more complex case when more than one IP address is involved, -# that option must be used several times, each entry must -# have form "-X ", to map all involved addresses. -# RFC5780 NAT discovery STUN functionality will work correctly, -# if the addresses are mapped properly, even when the TURN server itself -# is behind A NAT. -# -# By default, this value is empty, and no address mapping is used. -# -#external-ip=60.70.80.91 -# -#OR: -# -#external-ip=60.70.80.91/172.17.19.101 -#external-ip=60.70.80.92/172.17.19.102 - - -# Number of the relay threads to handle the established connections -# (in addition to authentication thread and the listener thread). -# If explicitly set to 0 then application runs relay process in a -# single thread, in the same thread with the listener process -# (the authentication thread will still be a separate thread). -# -# If this parameter is not set, then the default OS-dependent -# thread pattern algorithm will be employed. Usually the default -# algorithm is the most optimal, so you have to change this option -# only if you want to make some fine tweaks. -# -# In the older systems (Linux kernel before 3.9), -# the number of UDP threads is always one thread per network listening -# endpoint - including the auxiliary endpoints - unless 0 (zero) or -# 1 (one) value is set. -# -#relay-threads=0 - -# Lower and upper bounds of the UDP relay endpoints: -# (default values are 49152 and 65535) -# -#min-port=49152 -#max-port=65535 - -# Uncomment to run TURN server in 'normal' 'moderate' verbose mode. -# By default the verbose mode is off. -#verbose - -# Uncomment to run TURN server in 'extra' verbose mode. -# This mode is very annoying and produces lots of output. -# Not recommended under any normal circumstances. -# -#Verbose - -# Uncomment to use fingerprints in the TURN messages. -# By default the fingerprints are off. -# -#fingerprint - -# Uncomment to use long-term credential mechanism. -# By default no credentials mechanism is used (any user allowed). -# -#lt-cred-mech - -# This option is opposite to lt-cred-mech. -# (TURN Server with no-auth option allows anonymous access). -# If neither option is defined, and no users are defined, -# then no-auth is default. If at least one user is defined, -# in this file or in command line or in usersdb file, then -# lt-cred-mech is default. -# -#no-auth - -# TURN REST API flag. -# (Time Limited Long Term Credential) -# Flag that sets a special authorization option that is based upon authentication secret. -# -# This feature's purpose is to support "TURN Server REST API", see -# "TURN REST API" link in the project's page -# https://github.com/coturn/coturn/ -# -# This option is used with timestamp: -# -# usercombo -> "timestamp:userid" -# turn user -> usercombo -# turn password -> base64(hmac(secret key, usercombo)) -# -# This allows TURN credentials to be accounted for a specific user id. -# If you don't have a suitable id, the timestamp alone can be used. -# This option is just turning on secret-based authentication. -# The actual value of the secret is defined either by option static-auth-secret, -# or can be found in the turn_secret table in the database (see below). -# -# Read more about it: -# - https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00 -# - https://www.ietf.org/proceedings/87/slides/slides-87-behave-10.pdf -# -# Be aware that use-auth-secret overrides some part of lt-cred-mech. -# Notice that this feature depends internally on lt-cred-mech, so if you set -# use-auth-secret then it enables internally automatically lt-cred-mech option -# like if you enable both. -# -# You can use only one of the to auth mechanisms in the same time because, -# both mechanism use the username and password validation in different way. -# -# This way be aware that you can't use both auth mechnaism in the same time! -# Use in config either the lt-cred-mech or the use-auth-secret -# to avoid any confusion. -# -$(generate_use_auth_secret) - -# 'Static' authentication secret value (a string) for TURN REST API only. -# If not set, then the turn server -# will try to use the 'dynamic' value in turn_secret table -# in user database (if present). The database-stored value can be changed on-the-fly -# by a separate program, so this is why that other mode is 'dynamic'. -# -$(generate_static_auth_secret) - -# Server name used for -# the oAuth authentication purposes. -# The default value is the realm name. -# -#server-name=blackdow.carleon.gov - -# Flag that allows oAuth authentication. -# -#oauth - -# 'Static' user accounts for long term credentials mechanism, only. -# This option cannot be used with TURN REST API. -# 'Static' user accounts are NOT dynamically checked by the turnserver process, -# so that they can NOT be changed while the turnserver is running. -# -#user=username1:key1 -#user=username2:key2 -# OR: -#user=username1:password1 -#user=username2:password2 -# -# Keys must be generated by turnadmin utility. The key value depends -# on user name, realm, and password: -# -# Example: -# $ turnadmin -k -u ninefingers -r north.gov -p youhavetoberealistic -# Output: 0xbc807ee29df3c9ffa736523fb2c4e8ee -# ('0x' in the beginning of the key is what differentiates the key from -# password. If it has 0x then it is a key, otherwise it is a password). -# -# The corresponding user account entry in the config file will be: -# -#user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee -# Or, equivalently, with open clear password (less secure): -#user=ninefingers:youhavetoberealistic -# - -# SQLite database file name. -# -# Default file name is /var/db/turndb or /usr/local/var/db/turndb or -# /var/lib/turn/turndb. -# -#userdb=/var/db/turndb - -# PostgreSQL database connection string in the case that we are using PostgreSQL -# as the user database. -# This database can be used for long-term credential mechanism -# and it can store the secret value for secret-based timed authentication in TURN RESP API. -# See http://www.postgresql.org/docs/8.4/static/libpq-connect.html for 8.x PostgreSQL -# versions connection string format, see -# http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING -# for 9.x and newer connection string formats. -# -#psql-userdb="host= dbname= user= password= connect_timeout=30" - -# MySQL database connection string in the case that we are using MySQL -# as the user database. -# This database can be used for long-term credential mechanism -# and it can store the secret value for secret-based timed authentication in TURN RESP API. -# -# Optional connection string parameters for the secure communications (SSL): -# ca, capath, cert, key, cipher -# (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the -# command options description). -# -# Use string format as below (space separated parameters, all optional): -# -#mysql-userdb="host= dbname= user= password= port= connect_timeout= read_timeout=" - -# If you want to use in the MySQL connection string the password in encrypted format, -# then set in this option the MySQL password encryption secret key file. -# -# Warning: If this option is set, then mysql password must be set in "mysql-userdb" in encrypted format! -# If you want to use cleartext password then do not set this option! -# -# This is the file path which contain secret key of aes encryption while using password encryption. -# -#secret-key-file=/path/ - -# MongoDB database connection string in the case that we are using MongoDB -# as the user database. -# This database can be used for long-term credential mechanism -# and it can store the secret value for secret-based timed authentication in TURN RESP API. -# Use string format is described at http://hergert.me/docs/mongo-c-driver/mongoc_uri.html -# -#mongo-userdb="mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]" - -# Redis database connection string in the case that we are using Redis -# as the user database. -# This database can be used for long-term credential mechanism -# and it can store the secret value for secret-based timed authentication in TURN RESP API. -# Use string format as below (space separated parameters, all optional): -# -#redis-userdb="ip= dbname= password= port= connect_timeout=" - -# Redis status and statistics database connection string, if used (default - empty, no Redis stats DB used). -# This database keeps allocations status information, and it can be also used for publishing -# and delivering traffic and allocation event notifications. -# The connection string has the same parameters as redis-userdb connection string. -# Use string format as below (space separated parameters, all optional): -# -#redis-statsdb="ip= dbname= password= port= connect_timeout=" - -# The default realm to be used for the users when no explicit -# origin/realm relationship was found in the database, or if the TURN -# server is not using any database (just the commands-line settings -# and the userdb file). Must be used with long-term credentials -# mechanism or with TURN REST API. -# -# Note: If default realm is not specified at all, then realm falls back to the host domain name. -# If domain name is empty string, or '(None)', then it is initialized to am empty string. -# -$(generate_realm) - -# The flag that sets the origin consistency -# check: across the session, all requests must have the same -# main ORIGIN attribute value (if the ORIGIN was -# initially used by the session). -# -#check-origin-consistency - -# Per-user allocation quota. -# default value is 0 (no quota, unlimited number of sessions per user). -# This option can also be set through the database, for a particular realm. -# -#user-quota=0 - -# Total allocation quota. -# default value is 0 (no quota). -# This option can also be set through the database, for a particular realm. -# -#total-quota=0 - -# Max bytes-per-second bandwidth a TURN session is allowed to handle -# (input and output network streams are treated separately). Anything above -# that limit will be dropped or temporary suppressed (within -# the available buffer limits). -# This option can also be set through the database, for a particular realm. -# -#max-bps=0 - -# -# Maximum server capacity. -# Total bytes-per-second bandwidth the TURN server is allowed to allocate -# for the sessions, combined (input and output network streams are treated separately). -# -# bps-capacity=0 - -# Uncomment if no UDP client listener is desired. -# By default UDP client listener is always started. -# -#no-udp - -# Uncomment if no TCP client listener is desired. -# By default TCP client listener is always started. -# -#no-tcp - -# Uncomment if no TLS client listener is desired. -# By default TLS client listener is always started. -# -#no-tls - -# Uncomment if no DTLS client listener is desired. -# By default DTLS client listener is always started. -# -#no-dtls - -# Uncomment if no UDP relay endpoints are allowed. -# By default UDP relay endpoints are enabled (like in RFC 5766). -# -#no-udp-relay - -# Uncomment if no TCP relay endpoints are allowed. -# By default TCP relay endpoints are enabled (like in RFC 6062). -# -$(generate_no_tcp_relay) - -# Uncomment if extra security is desired, -# with nonce value having limited lifetime. -# By default, the nonce value is unique for a session, -# and has unlimited lifetime. -# Set this option to limit the nonce lifetime. -# It defaults to 600 secs (10 min) if no value is provided. After that delay, -# the client will get 438 error and will have to re-authenticate itself. -# -#stale-nonce=600 - -# Uncomment if you want to set the maximum allocation -# time before it has to be refreshed. -# Default is 3600s. -# -#max-allocate-lifetime=3600 - - -# Uncomment to set the lifetime for the channel. -# Default value is 600 secs (10 minutes). -# This value MUST not be changed for production purposes. -# -#channel-lifetime=600 - -# Uncomment to set the permission lifetime. -# Default to 300 secs (5 minutes). -# In production this value MUST not be changed, -# however it can be useful for test purposes. -# -#permission-lifetime=300 - -# Certificate file. -# Use an absolute path or path relative to the -# configuration file. -# -#cert=/usr/local/etc/turn_server_cert.pem - -# Private key file. -# Use an absolute path or path relative to the -# configuration file. -# Use PEM file format. -# -#pkey=/usr/local/etc/turn_server_pkey.pem - -# Private key file password, if it is in encoded format. -# This option has no default value. -# -#pkey-pwd=... - -# Allowed OpenSSL cipher list for TLS/DTLS connections. -# Default value is "DEFAULT". -# -#cipher-list="DEFAULT" - -# CA file in OpenSSL format. -# Forces TURN server to verify the client SSL certificates. -# By default it is not set: there is no default value and the client -# certificate is not checked. -# -# Example: -#CA-file=/etc/ssh/id_rsa.cert - -# Curve name for EC ciphers, if supported by OpenSSL -# library (TLS and DTLS). The default value is prime256v1, -# if pre-OpenSSL 1.0.2 is used. With OpenSSL 1.0.2+, -# an optimal curve will be automatically calculated, if not defined -# by this option. -# -#ec-curve-name=prime256v1 - -# Use 566 bits predefined DH TLS key. Default size of the key is 1066. -# -#dh566 - -# Use 2066 bits predefined DH TLS key. Default size of the key is 1066. -# -#dh2066 - -# Use custom DH TLS key, stored in PEM format in the file. -# Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file. -# -#dh-file= - -# Flag to prevent stdout log messages. -# By default, all log messages are going to both stdout and to -# the configured log file. With this option everything will be -# going to the configured log only (unless the log file itself is stdout). -# -#no-stdout-log - -# Option to set the log file name. -# By default, the turnserver tries to open a log file in -# /var/log, /var/tmp, /tmp and current directories directories -# (which open operation succeeds first that file will be used). -# With this option you can set the definite log file name. -# The special names are "stdout" and "-" - they will force everything -# to the stdout. Also, the "syslog" name will force everything to -# the system log (syslog). -# In the runtime, the logfile can be reset with the SIGHUP signal -# to the turnserver process. -# -#log-file=/var/tmp/turn.log - -# Option to redirect all log output into system log (syslog). -# -syslog - -# This flag means that no log file rollover will be used, and the log file -# name will be constructed as-is, without PID and date appendage. -# This option can be used, for example, together with the logrotate tool. -# -#simple-log - -# Option to set the "redirection" mode. The value of this option -# will be the address of the alternate server for UDP & TCP service in form of -# [:]. The server will send this value in the attribute -# ALTERNATE-SERVER, with error 300, on ALLOCATE request, to the client. -# Client will receive only values with the same address family -# as the client network endpoint address family. -# See RFC 5389 and RFC 5766 for ALTERNATE-SERVER functionality description. -# The client must use the obtained value for subsequent TURN communications. -# If more than one --alternate-server options are provided, then the functionality -# can be more accurately described as "load-balancing" than a mere "redirection". -# If the port number is omitted, then the default port -# number 3478 for the UDP/TCP protocols will be used. -# Colon (:) characters in IPv6 addresses may conflict with the syntax of -# the option. To alleviate this conflict, literal IPv6 addresses are enclosed -# in square brackets in such resource identifiers, for example: -# [2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 . -# Multiple alternate servers can be set. They will be used in the -# round-robin manner. All servers in the pool are considered of equal weight and -# the load will be distributed equally. For example, if we have 4 alternate servers, -# then each server will receive 25% of ALLOCATE requests. A alternate TURN server -# address can be used more than one time with the alternate-server option, so this -# can emulate "weighting" of the servers. -# -# Examples: -#alternate-server=1.2.3.4:5678 -#alternate-server=11.22.33.44:56789 -#alternate-server=5.6.7.8 -#alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 - -# Option to set alternative server for TLS & DTLS services in form of -# :. If the port number is omitted, then the default port -# number 5349 for the TLS/DTLS protocols will be used. See the previous -# option for the functionality description. -# -# Examples: -#tls-alternate-server=1.2.3.4:5678 -#tls-alternate-server=11.22.33.44:56789 -#tls-alternate-server=[2001:db8:85a3:8d3:1319:8a2e:370:7348]:3478 - -# Option to suppress TURN functionality, only STUN requests will be processed. -# Run as STUN server only, all TURN requests will be ignored. -# By default, this option is NOT set. -# -#stun-only - -# Option to suppress STUN functionality, only TURN requests will be processed. -# Run as TURN server only, all STUN requests will be ignored. -# By default, this option is NOT set. -# -#no-stun - -# This is the timestamp/username separator symbol (character) in TURN REST API. -# The default value is ':'. -# rest-api-separator=: - -# Flag that can be used to allow peers on the loopback addresses (127.x.x.x and ::1). -# This is an extra security measure. -# -# (To avoid any security issue that allowing loopback access may raise, -# the no-loopback-peers option is replaced by allow-loopback-peers.) -# -# Allow it only for testing in a development environment! -# In production it adds a possible security vulnerability, so for security reasons -# it is not allowed using it together with empty cli-password. -# -#allow-loopback-peers - -# Flag that can be used to disallow peers on well-known broadcast addresses (224.0.0.0 and above, and FFXX:*). -# This is an extra security measure. -# -#no-multicast-peers - -# Option to set the max time, in seconds, allowed for full allocation establishment. -# Default is 60 seconds. -# -#max-allocate-timeout=60 - -# Option to allow or ban specific ip addresses or ranges of ip addresses. -# If an ip address is specified as both allowed and denied, then the ip address is -# considered to be allowed. This is useful when you wish to ban a range of ip -# addresses, except for a few specific ips within that range. -# -# This can be used when you do not want users of the turn server to be able to access -# machines reachable by the turn server, but would otherwise be unreachable from the -# internet (e.g. when the turn server is sitting behind a NAT) -# -# Examples: -# denied-peer-ip=83.166.64.0-83.166.95.255 -# allowed-peer-ip=83.166.68.45 - -# File name to store the pid of the process. -# Default is /var/run/turnserver.pid (if superuser account is used) or -# /var/tmp/turnserver.pid . -# -#pidfile="/var/run/turnserver.pid" - -# Require authentication of the STUN Binding request. -# By default, the clients are allowed anonymous access to the STUN Binding functionality. -# -#secure-stun - -# Mobility with ICE (MICE) specs support. -# -#mobility - -# Allocate Address Family according -# If enabled then TURN server allocates address family according the TURN -# Client <=> Server communication address family. -# (By default coTURN works according RFC 6156.) -# !!Warning: Enabling this option breaks RFC6156 section-4.2 (violates use default IPv4)!! -# -#keep-address-family - - -# User name to run the process. After the initialization, the turnserver process -# will make an attempt to change the current user ID to that user. -# -#proc-user= - -# Group name to run the process. After the initialization, the turnserver process -# will make an attempt to change the current group ID to that group. -# -#proc-group= - -# Turn OFF the CLI support. -# By default it is always ON. -# See also options cli-ip and cli-port. -# -#no-cli - -#Local system IP address to be used for CLI server endpoint. Default value -# is 127.0.0.1. -# -#cli-ip=127.0.0.1 - -# CLI server port. Default is 5766. -# -#cli-port=5766 - -# CLI access password. Default is empty (no password). -# For the security reasons, it is recommended to use the encrypted -# for of the password (see the -P command in the turnadmin utility). -# -# Secure form for password 'qwerty': -# -#cli-password=$5$79a316b350311570$81df9cfb9af7f5e5a76eada31e7097b663a0670f99a3c07ded3f1c8e59c5658a -# -# Or unsecure form for the same password: -# -#cli-password=qwerty - -# Enable Web-admin support on https. By default it is Disabled. -# If it is enabled it also enables a http a simple static banner page -# with a small reminder that the admin page is available only on https. -# -#web-admin - -# Local system IP address to be used for Web-admin server endpoint. Default value is 127.0.0.1. -# -#web-admin-ip=127.0.0.1 - -# Web-admin server port. Default is 8080. -# -#web-admin-port=8080 - -# Web-admin server listen on STUN/TURN worker threads -# By default it is disabled for security resons! (Not recommended in any production environment!) -# -#web-admin-listen-on-workers - -# Server relay. NON-STANDARD AND DANGEROUS OPTION. -# Only for those applications when we want to run -# server applications on the relay endpoints. -# This option eliminates the IP permissions check on -# the packets incoming to the relay endpoints. -# -#server-relay - -# Maximum number of output sessions in ps CLI command. -# This value can be changed on-the-fly in CLI. The default value is 256. -# -#cli-max-output-sessions - -# Set network engine type for the process (for internal purposes). -# -#ne=[1|2|3] - -# Do not allow an TLS/DTLS version of protocol -# -#no-tlsv1 -#no-tlsv1_1 -#no-tlsv1_2 -EOF diff --git a/cdist/conf/type/__coturn/man.rst b/cdist/conf/type/__coturn/man.rst deleted file mode 100644 index 219da4ea..00000000 --- a/cdist/conf/type/__coturn/man.rst +++ /dev/null @@ -1,61 +0,0 @@ -cdist-type__coturn(7) -===================== - -NAME ----- -cdist-type__coturn - Install and configure a coturn TURN server - - -DESCRIPTION ------------ -This (singleton) type install and configure a coturn TURN -server. - - -REQUIRED PARAMETERS -------------------- -None. - - -OPTIONAL PARAMETERS -------------------- -static_auth_secret - Secret used to access the TURN REST API. - -realm - Defailt realm. - -BOOLEAN PARAMETERS ------------------- -use_auth_secret - Allows TURN credentials to be accounted for a specific user id. - -no_tcp_relay - Disable TCP relay endpoints. - - -EXAMPLES --------- - -.. code-block:: sh - - __coturn \ - --realm turn.domain.tld \ - --no_tcp_relay - - -SEE ALSO --------- -- `coturn Github repository `_ - -AUTHORS -------- -Timothée Floure - - -COPYING -------- -Copyright \(C) 2020 Timothée Floure. You can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. diff --git a/cdist/conf/type/__coturn/manifest b/cdist/conf/type/__coturn/manifest deleted file mode 100755 index 915f587d..00000000 --- a/cdist/conf/type/__coturn/manifest +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh -e -# -# 2020 Timothée Floure (timothee.floure@ungleich.ch) -# -# This file is part of cdist. -# -# cdist is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# cdist is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with cdist. If not, see . -# - -__package coturn - -# Optional parameters. -if [ -f "$__object/parameter/use_auth_secret" ]; then - export USE_AUTH_SECRET=1 -fi - -if [ -f "$__object/parameter/static_auth_secret" ]; then - static_auth_secret=$(cat "$__object/parameter/static_auth_secret") - export STATIC_AUTH_SECRET=$static_auth_secret -fi - -if [ -f "$__object/parameter/realm" ]; then - realm=$(cat "$__object/parameter/realm") - export REALM=$realm -fi - -if [ -f "$__object/parameter/no_tcp_relay" ]; then - no_tcp_relay=$(cat "$__object/parameter/no_tcp_relay") - export NO_TCP_RELAY=$no_tcp_relay -fi - -# Hardcoded. -coturn_config='/etc/turnserver.conf' - -# Generate and deploy configuration file. -mkdir -p "$__object/files" -"$__type/files/turnserver.conf.sh" > "$__object/files/turnserver.conf" - -__file $coturn_config \ - --source "$__object/files/turnserver.conf" \ - --state present - -# Restart coturn server. -require="__file/$coturn_config" __service coturn --action restart diff --git a/cdist/conf/type/__coturn/parameter/boolean b/cdist/conf/type/__coturn/parameter/boolean deleted file mode 100644 index 45f9e704..00000000 --- a/cdist/conf/type/__coturn/parameter/boolean +++ /dev/null @@ -1,2 +0,0 @@ -use_auth_secret -no_tcp_relay diff --git a/cdist/conf/type/__coturn/parameter/optional b/cdist/conf/type/__coturn/parameter/optional deleted file mode 100644 index 33218485..00000000 --- a/cdist/conf/type/__coturn/parameter/optional +++ /dev/null @@ -1,2 +0,0 @@ -static_auth_secret -realm diff --git a/cdist/conf/type/__cron/man.rst b/cdist/conf/type/__cron/man.rst index d0694738..e39bfb5c 100644 --- a/cdist/conf/type/__cron/man.rst +++ b/cdist/conf/type/__cron/man.rst @@ -21,6 +21,11 @@ command OPTIONAL PARAMETERS ------------------- +**NOTE**: All time-related parameters (``--minute``, ``--hour``, ``--day_of_month`` +``--month`` and ``--day_of_week``) defaults to ``*``, which means to execute it +**always**. If you set ``--hour 0`` to execute the cronjob only at midnight, it +will execute **every** minute in the first hour of the morning all days. + state Either present or absent. Defaults to present. minute diff --git a/cdist/conf/type/__matrix_synapse/parameter/default/database_host b/cdist/conf/type/__cron/nonparallel similarity index 100% rename from cdist/conf/type/__matrix_synapse/parameter/default/database_host rename to cdist/conf/type/__cron/nonparallel diff --git a/cdist/conf/type/__directory/explorer/stat b/cdist/conf/type/__directory/explorer/stat index 105d894f..f817cb02 100755 --- a/cdist/conf/type/__directory/explorer/stat +++ b/cdist/conf/type/__directory/explorer/stat @@ -30,10 +30,10 @@ fallback() { gid=$(echo "$ls_line" | awk '{ print $4 }') owner=$(awk -F: -v uid="$uid" '$3 == uid { print $1; f=1 } END { if (!f) print "UNKNOWN" }' /etc/passwd) - group=$(awk -F: -v uid="$uid" '$3 == uid { print $1; f=1 } END { if (!f) print "UNKNOWN" }' /etc/group) + group=$(awk -F: -v gid="$gid" '$3 == gid { print $1; f=1 } END { if (!f) print "UNKNOWN" }' /etc/group) mode_text=$(echo "$ls_line" | awk '{ print $1 }') - mode=$(echo "$mode_text" | awk '{ k=0; for (i=0; i<=8; i++) k += ((substr($1, i+2, 1) ~ /[rwx]/) * 2^(8-i)); printf("%0o", k) }') + mode=$(echo "$mode_text" | awk '{for(i=8;i>=0;--i){c=substr($1,10-i,1);k+=((c~/[rwxst]/)*2^i);if(!(i%3))k+=(tolower(c)~/[lst]/)*2^(9+i/3)}printf("%04o",k)}') printf 'type: %s\nowner: %d %s\ngroup: %d %s\nmode: %s %s\n' \ "$("$__type_explorer/type")" \ @@ -45,56 +45,27 @@ fallback() { # nothing to work with, nothing we could do [ -e "$destination" ] || exit 0 -if ! command -v stat >/dev/null -then +command -v stat >/dev/null 2>&1 || { fallback exit -fi +} -case $("$__explorer/os") in - "freebsd"|"netbsd"|"openbsd"|"macosx") - stat -f "type: %HT +case $("$__explorer/os") +in + freebsd|netbsd|openbsd|macosx) + stat -f 'type: %HT owner: %Du %Su group: %Dg %Sg -mode: %Lp %Sp -" "$destination" | awk '/^type/ { print tolower($0); next } { print }' +mode: %Mp%03Lp %Sp +' "$destination" | awk '/^type/ { print tolower($0); next } { print }' ;; - solaris) - ls1="$( ls -ld "$destination" )" - ls2="$( ls -ldn "$destination" )" - - if [ -f "$__object/parameter/mode" ] - then mode_should="$( cat "$__object/parameter/mode" )" - fi - - # yes, it is ugly hack, but if you know better way... - if [ -z "$( find "$destination" -perm "$mode_should" )" ] - then octets=888 - else octets="$( echo "$mode_should" | sed 's/^0//' )" - fi - - case "$( echo "$ls1" | cut -c1-1 )" in - -) echo 'type: regular file' ;; - d) echo 'type: directory' ;; - esac - - echo "owner: $( echo "$ls2" \ - | awk '{print $3}' ) $( echo "$ls1" \ - | awk '{print $3}' )" - - echo "group: $( echo "$ls2" \ - | awk '{print $4}' ) $( echo "$ls1" \ - | awk '{print $4}' )" - - echo "mode: $octets $( echo "$ls1" | awk '{print $1}' )" - ;; *) # NOTE: Do not use --printf here as it is not supported by BusyBox stat. # NOTE: BusyBox's stat might not support the "-c" option, in which case # we fall through to the shell fallback. - stat -c "type: %F + stat -c 'type: %F owner: %u %U group: %g %G -mode: %a %A" "$destination" 2>/dev/null || fallback - ;; +mode: %04a %A' "$destination" 2>/dev/null || fallback + ;; esac diff --git a/cdist/conf/type/__directory/gencode-remote b/cdist/conf/type/__directory/gencode-remote index 374db47a..d9c00b56 100755 --- a/cdist/conf/type/__directory/gencode-remote +++ b/cdist/conf/type/__directory/gencode-remote @@ -3,6 +3,7 @@ # 2011-2013 Nico Schottelius (nico-cdist at schottelius.org) # 2013 Steven Armstrong (steven-cdist armstrong.cc) # 2014 Daniel Heule (hda at sfs.biz) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -21,8 +22,8 @@ # destination="/$__object_id" -state_should="$(cat "$__object/parameter/state")" -type="$(cat "$__object/explorer/type")" +state_should=$(cat "$__object/parameter/state") +type=$(cat "$__object/explorer/type") stat_file="$__object/explorer/stat" # variable to keep track if we have to set directory attributes @@ -72,7 +73,7 @@ set_mode() { } case "$state_should" in - present) + present|exists) if [ "$type" != "directory" ]; then set_attributes=1 if [ "$type" != "none" ]; then @@ -83,6 +84,10 @@ case "$state_should" in fi echo "mkdir $mkdiropt '$destination'" echo "create" >> "$__messages_out" + elif [ "$state_should" = 'exists' ]; then + # The type is directory and --state exists. We are done and do not + # check or set the attributes. + exit 0 fi # Note: Mode - needs to happen last as a chown/chgrp can alter mode by @@ -92,9 +97,11 @@ case "$state_should" in value_should="$(cat "$__object/parameter/$attribute")" value_is="$(get_current_value "$attribute" "$value_should")" - # change 0xxx format to xxx format => same as stat returns + # format mode in four digits => same as stat returns if [ "$attribute" = mode ]; then - value_should="$(echo "$value_should" | sed 's/^0\(...\)/\1/')" + # Convert to four-digit octal number (printf interprets + # strings with leading 0s as octal!) + value_should=$(printf '%04o' "0${value_should}") fi if [ "$set_attributes" = 1 ] || [ "$value_should" != "$value_is" ]; then @@ -103,6 +110,26 @@ case "$state_should" in fi done ;; + pre-exists) + case $type in + directory) + # all good + exit 0 + ;; + none) + printf 'Directory "%s" does not exist\n' "$destination" >&2 + exit 1 + ;; + file|symlink) + printf 'File "%s" exists and is a %s, but should be a directory\n' "$destination" "$type" >&2 + exit 1 + ;; + *) + printf 'File or directory "%s" is in an unknown state\n' "$destination" >&2 + exit 1 + ;; + esac + ;; absent) if [ "$type" = "directory" ]; then echo "rm -rf '$destination'" diff --git a/cdist/conf/type/__directory/man.rst b/cdist/conf/type/__directory/man.rst index 74b00afe..7755334c 100644 --- a/cdist/conf/type/__directory/man.rst +++ b/cdist/conf/type/__directory/man.rst @@ -19,7 +19,18 @@ None. OPTIONAL PARAMETERS ------------------- state - 'present' or 'absent', defaults to 'present' + 'present', 'absent', 'exists' or 'pre-exists', defaults to 'present' where: + + present + the directory exists and the given attributes are set. + absent + the directory does not exist. + exists + the directory exists, but its attributes are not altered if it already + existed. + pre-exists + check that the directory exists and is indeed a directory, but do not + create or modify it. group Group to chgrp to. @@ -36,7 +47,7 @@ BOOLEAN PARAMETERS parents Whether to create parents as well (mkdir -p behaviour). Warning: all intermediate directory permissions default - to whatever mkdir -p does. + to whatever mkdir -p does. Usually this means root:root, 0700. diff --git a/cdist/conf/type/__dot_file/man.rst b/cdist/conf/type/__dot_file/man.rst index ae65eb95..ba7621a1 100644 --- a/cdist/conf/type/__dot_file/man.rst +++ b/cdist/conf/type/__dot_file/man.rst @@ -25,6 +25,9 @@ user OPTIONAL PARAMETERS ------------------- +dirmode + forwarded to :strong:`__directory` type as mode + mode forwarded to :strong:`__file` type diff --git a/cdist/conf/type/__dot_file/manifest b/cdist/conf/type/__dot_file/manifest index 5e4957e5..02dadf05 100755 --- a/cdist/conf/type/__dot_file/manifest +++ b/cdist/conf/type/__dot_file/manifest @@ -19,6 +19,7 @@ set -eu user="$(cat "${__object}/parameter/user")" home="$(cat "${__object}/explorer/home")" primary_group="$(cat "${__object}/explorer/primary_group")" +dirmode="$(cat "${__object}/parameter/dirmode")" # Create parent directory. Type __directory has flag 'parents', but it # will leave us with root-owned directory in user home, which is not @@ -36,6 +37,7 @@ export CDIST_ORDER_DEPENDENCY for dir ; do __directory "${home}/${dir}" \ --group "${primary_group}" \ + --mode "${dirmode}" \ --owner "${user}" done diff --git a/cdist/conf/type/__dot_file/parameter/default/dirmode b/cdist/conf/type/__dot_file/parameter/default/dirmode new file mode 100644 index 00000000..e9745d1f --- /dev/null +++ b/cdist/conf/type/__dot_file/parameter/default/dirmode @@ -0,0 +1 @@ +0700 diff --git a/cdist/conf/type/__dot_file/parameter/optional b/cdist/conf/type/__dot_file/parameter/optional index ccab9fa6..9f7f83fb 100644 --- a/cdist/conf/type/__dot_file/parameter/optional +++ b/cdist/conf/type/__dot_file/parameter/optional @@ -1,3 +1,4 @@ state mode source +dirmode diff --git a/cdist/conf/type/__download/explorer/remote_cmd b/cdist/conf/type/__download/explorer/remote_cmd new file mode 100755 index 00000000..e3e35b45 --- /dev/null +++ b/cdist/conf/type/__download/explorer/remote_cmd @@ -0,0 +1,19 @@ +#!/bin/sh -e + +if [ -f "$__object/parameter/cmd-get" ] +then + cmd="$( cat "$__object/parameter/cmd-get" )" + +elif command -v curl > /dev/null +then + cmd="curl -L -o - '%s'" + +elif command -v fetch > /dev/null +then + cmd="fetch -o - '%s'" + +else + cmd="wget -O - '%s'" +fi + +echo "$cmd" diff --git a/cdist/conf/type/__download/explorer/state b/cdist/conf/type/__download/explorer/state new file mode 100755 index 00000000..00362545 --- /dev/null +++ b/cdist/conf/type/__download/explorer/state @@ -0,0 +1,72 @@ +#!/bin/sh -e + +dst="/$__object_id" + +if [ ! -f "$dst" ] +then + echo 'absent' + exit 0 +fi + +sum_should="$( cat "$__object/parameter/sum" )" + +if [ -f "$__object/parameter/cmd-sum" ] +then + # shellcheck disable=SC2059 + sum_is="$( eval "$( printf \ + "$( cat "$__object/parameter/cmd-sum" )" \ + "$dst" )" )" +else + os="$( "$__explorer/os" )" + + if echo "$sum_should" | grep -Eq '^[0-9]+\s[0-9]+$' + then + sum_is="$( cksum "$dst" | awk '{print $1" "$2}' )" + + elif echo "$sum_should" | grep -Eiq '^md5:[a-f0-9]{32}$' + then + case "$os" in + freebsd) + sum_is="md5:$( md5 -q "$dst" )" + ;; + *) + sum_is="md5:$( md5sum "$dst" | awk '{print $1}' )" + ;; + esac + + elif echo "$sum_should" | grep -Eiq '^sha1:[a-f0-9]{40}$' + then + case "$os" in + freebsd) + sum_is="sha1:$( sha1 -q "$dst" )" + ;; + *) + sum_is="sha1:$( sha1sum "$dst" | awk '{print $1}' )" + ;; + esac + + elif echo "$sum_should" | grep -Eiq '^sha256:[a-f0-9]{64}$' + then + case "$os" in + freebsd) + sum_is="sha256:$( sha256 -q "$dst" )" + ;; + *) + sum_is="sha256:$( sha256sum "$dst" | awk '{print $1}' )" + ;; + esac + fi +fi + +if [ -z "$sum_is" ] +then + echo 'no checksum from target' >&2 + exit 1 +fi + +if [ "$sum_is" = "$sum_should" ] +then + echo 'present' +else + echo 'mismatch' +fi diff --git a/cdist/conf/type/__download/gencode-local b/cdist/conf/type/__download/gencode-local new file mode 100755 index 00000000..571d2c3c --- /dev/null +++ b/cdist/conf/type/__download/gencode-local @@ -0,0 +1,58 @@ +#!/bin/sh -e + +download="$( cat "$__object/parameter/download" )" + +state_is="$( cat "$__object/explorer/state" )" + +if [ "$download" != 'local' ] || [ "$state_is" = 'present' ] +then + exit 0 +fi + +url="$( cat "$__object/parameter/url" )" + +tmp="$( mktemp )" + +dst="/$__object_id" + +if [ -f "$__object/parameter/cmd-get" ] +then + cmd="$( cat "$__object/parameter/cmd-get" )" + +elif command -v wget > /dev/null +then + cmd="wget -O - '%s'" + +elif command -v curl > /dev/null +then + cmd="curl -L -o - '%s'" + +elif command -v fetch > /dev/null +then + cmd="fetch -o - '%s'" + +else + echo 'no usable locally installed utility for downloading' >&2 + exit 1 +fi + +printf "$cmd > %s\n" \ + "$url" \ + "$tmp" + +if echo "$__target_host" | grep -Eq '^[0-9a-fA-F:]+$' +then + target_host="[$__target_host]" +else + target_host="$__target_host" +fi + +printf '%s %s %s:%s\n' \ + "$__remote_copy" \ + "$tmp" \ + "$target_host" \ + "$dst" + +echo "rm -f '$tmp'" + +echo 'downloaded' > "$__messages_out" diff --git a/cdist/conf/type/__download/gencode-remote b/cdist/conf/type/__download/gencode-remote new file mode 100755 index 00000000..029a0801 --- /dev/null +++ b/cdist/conf/type/__download/gencode-remote @@ -0,0 +1,25 @@ +#!/bin/sh -e + +download="$( cat "$__object/parameter/download" )" + +state_is="$( cat "$__object/explorer/state" )" + +if [ "$download" = 'remote' ] && [ "$state_is" != 'present' ] +then + cmd="$( cat "$__object/explorer/remote_cmd" )" + + url="$( cat "$__object/parameter/url" )" + + dst="/$__object_id" + + printf "$cmd > %s\n" \ + "$url" \ + "$dst" + + echo 'downloaded' > "$__messages_out" +fi + +if [ -f "$__object/parameter/onchange" ] && [ "$state_is" != "present" ] +then + cat "$__object/parameter/onchange" +fi diff --git a/cdist/conf/type/__download/man.rst b/cdist/conf/type/__download/man.rst new file mode 100644 index 00000000..54503470 --- /dev/null +++ b/cdist/conf/type/__download/man.rst @@ -0,0 +1,87 @@ +cdist-type__download(7) +======================= + +NAME +---- +cdist-type__download - Download a file + + +DESCRIPTION +----------- +Destination (``$__object_id``) in target host must be persistent storage +in order to calculate checksum and decide if file must be (re-)downloaded. + +By default type will try to use ``wget``, ``curl`` or ``fetch``. +If download happens in target (see ``--download``) then type will +fallback to (and install) ``wget``. + +If download happens in local machine, then environment variables like +``{http,https,ftp}_proxy`` etc can be used on cdist execution +(``http_proxy=foo cdist config ...``). + + +REQUIRED PARAMETERS +------------------- +url + File's URL. + +sum + Checksum of file going to be downloaded. + By default output of ``cksum`` without filename is expected. + Other hash formats supported with prefixes: ``md5:``, ``sha1:`` and ``sha256:``. + + +OPTIONAL PARAMETERS +------------------- +download + If ``local`` (default), then download file to local storage and copy + it to target host. If ``remote``, then download happens in target. + +cmd-get + Command used for downloading. + Command must output to ``stdout``. + Parameter will be used for ``printf`` and must include only one + format specification ``%s`` which will become URL. + For example: ``wget -O - '%s'``. + +cmd-sum + Command used for checksum calculation. + Command output and ``--sum`` parameter must match. + Parameter will be used for ``printf`` and must include only one + format specification ``%s`` which will become destination. + For example: ``md5sum '%s' | awk '{print $1}'``. + +onchange + Execute this command after download. + + +EXAMPLES +-------- + +.. code-block:: sh + + __directory /opt/cpma + + require='__directory/opt/cpma' \ + __download /opt/cpma/cnq3.zip \ + --url https://cdn.playmorepromode.com/files/cnq3/cnq3-1.51.zip \ + --sum md5:46da3021ca9eace277115ec9106c5b46 + + require='__download/opt/cpma/cnq3.zip' \ + __unpack /opt/cpma/cnq3.zip \ + --backup-destination \ + --preserve-archive \ + --destination /opt/cpma/server + + +AUTHORS +------- +Ander Punnar + + +COPYING +------- +Copyright \(C) 2020 Ander Punnar. You can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. diff --git a/cdist/conf/type/__download/manifest b/cdist/conf/type/__download/manifest new file mode 100755 index 00000000..7ec8d86d --- /dev/null +++ b/cdist/conf/type/__download/manifest @@ -0,0 +1,6 @@ +#!/bin/sh -e + +if grep -Eq '^wget' "$__object/explorer/remote_cmd" +then + __package wget +fi diff --git a/cdist/conf/type/__download/parameter/default/download b/cdist/conf/type/__download/parameter/default/download new file mode 100644 index 00000000..40830374 --- /dev/null +++ b/cdist/conf/type/__download/parameter/default/download @@ -0,0 +1 @@ +local diff --git a/cdist/conf/type/__download/parameter/optional b/cdist/conf/type/__download/parameter/optional new file mode 100644 index 00000000..838e2fbf --- /dev/null +++ b/cdist/conf/type/__download/parameter/optional @@ -0,0 +1,4 @@ +cmd-get +cmd-sum +download +onchange diff --git a/cdist/conf/type/__download/parameter/required b/cdist/conf/type/__download/parameter/required new file mode 100644 index 00000000..6ea4c38f --- /dev/null +++ b/cdist/conf/type/__download/parameter/required @@ -0,0 +1,2 @@ +url +sum diff --git a/cdist/conf/type/__dpkg_architecture/explorer/architecture b/cdist/conf/type/__dpkg_architecture/explorer/architecture new file mode 100755 index 00000000..03e7e386 --- /dev/null +++ b/cdist/conf/type/__dpkg_architecture/explorer/architecture @@ -0,0 +1,26 @@ +#!/bin/sh -e +# __dpkg_architecture/explorer/architecture +# +# 2020 Matthias Stecher +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +# Get the main architecture of this machine + + +# print or die in the gencode-remote +dpkg --print-architecture || true diff --git a/cdist/conf/type/__dpkg_architecture/explorer/foreign-architectures b/cdist/conf/type/__dpkg_architecture/explorer/foreign-architectures new file mode 100755 index 00000000..a150d307 --- /dev/null +++ b/cdist/conf/type/__dpkg_architecture/explorer/foreign-architectures @@ -0,0 +1,26 @@ +#!/bin/sh -e +# __dpkg_architecture/explorer/foreign-architectures +# +# 2020 Matthias Stecher +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +# Print all additional architectures + + +# print or die in the gencode-remote +dpkg --print-foreign-architectures || true diff --git a/cdist/conf/type/__dpkg_architecture/gencode-remote b/cdist/conf/type/__dpkg_architecture/gencode-remote new file mode 100755 index 00000000..47fb24e7 --- /dev/null +++ b/cdist/conf/type/__dpkg_architecture/gencode-remote @@ -0,0 +1,82 @@ +#!/bin/sh -e +# __dpkg_architecture/gencode-remote +# +# 2020 Matthias Stecher +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + + +# Get parameter and explorer +state_should="$(cat "$__object/parameter/state")" +arch_wanted="$__object_id" +main_arch="$(cat "$__object/explorer/architecture")" + +# Exit here if dpkg do not work (empty explorer) +if [ -z "$main_arch" ]; then + echo "dpkg is not available or unable to detect a architecture!" >&2 + exit 1 +fi + + +# Check if requested architecture is the main one +if [ "$arch_wanted" = "$main_arch" ]; then + # higher than present; we can not remove it + state_is="present" + caution="yes" + +# Check if the architecture not already used +elif grep -qFx "$arch_wanted" "$__object/explorer/foreign-architectures"; then + state_is="present" + +# arch does not exist +else + state_is="absent" +fi + + +# Check what to do +if [ "$state_is" != "$state_should" ]; then + case "$state_should" in + present) + # print add code + printf "dpkg --add-architecture '%s'\n" "$arch_wanted" + # updating the index to make the new architecture available + echo "apt update" + + echo added >> "$__messages_out" + ;; + + absent) + if [ "$caution" ]; then + printf "can not remove the main arch '%s' of the system!\n" "$main_arch" >&2 + exit 1 + fi + + # removing all existing packages for the architecture + printf "apt purge '.*:%s'\n" "$arch_wanted" + # print remove code + printf "dpkg --remove-architecture '%s'\n" "$arch_wanted" + + echo removed >> "$__messages_out" + ;; + + *) + printf "state '%s' is unknown!\n" "$state_should" >&2 + exit 1 + ;; + esac +fi diff --git a/cdist/conf/type/__dpkg_architecture/man.rst b/cdist/conf/type/__dpkg_architecture/man.rst new file mode 100644 index 00000000..fa196229 --- /dev/null +++ b/cdist/conf/type/__dpkg_architecture/man.rst @@ -0,0 +1,103 @@ +cdist-type__dpkg_architecture(7) +================================ + +NAME +---- +cdist-type__dpkg_architecture - Handles foreign architectures on debian-like +systems managed by `dpkg` + + +DESCRIPTION +----------- +This type handles foreign architectures on systems managed by +:strong:`dpkg`\ (1). The object id is the name of the architecture accepted by +`dpkg`, which should be added or removed. + +If the architecture is not setup on the system, it adds a new architecture as a +new foreign architecture in `dpkg`. Then, it updates the apt package index to +make packages from the new architecture available. + +If the architecture should be removed, it will remove it if it is not the base +architecture on where the system was installed on. Before it, it will purge +every package based on the "to be removed" architecture via `apt` to be able to +remove the selected architecture. + + +REQUIRED PARAMETERS +------------------- +None. + + +OPTIONAL PARAMETERS +------------------- +state + ``present`` or ``absent``. Defaults to ``present``. + + +MESSAGES +-------- +added + Added the specified architecture + +removed + Removed the specified architecture + + +ABORTS +------ +Aborts in the following cases: + +If :strong:`dpkg`\ (1) is not available. It will abort with a proper error +message. + +If the architecture is the same as the base architecture the system is build +upon it (returned by ``dpkg --print-architecture``) and it should be removed. + +It will fail if it can not execute :strong:`apt`\ (8). It is assumed that it is +already installed. + + +EXAMPLES +-------- + +.. code-block:: sh + + # add i386 (32 bit) architecture + __dpkg_architecture i386 + + # remove it again :) + __dpkg_architecture i386 --state absent + + +SEE ALSO +-------- +`Multiarch on Debian systems `_ + +`How to setup multiarch on Debian `_ + +:strong:`dpkg`\ (1) +:strong:`cdist-type__package_dpkg`\ (7) +:strong:`cdist-type__package_apt`\ (7) + +Useful commands: + +.. code-block:: sh + + # base architecture installed on this system + dpkg --print-architecture + + # extra architectures added + dpkg --print-foreign-architectures + + +AUTHORS +------- +Matthias Stecher + + +COPYING +------- +Copyright \(C) 2020 Matthias Stecher. You can redistribute it +and/or modify it under the terms of the GNU General Public License as +ublished by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. diff --git a/cdist/conf/type/__matrix_synapse/parameter/default/database_password b/cdist/conf/type/__dpkg_architecture/nonparallel similarity index 100% rename from cdist/conf/type/__matrix_synapse/parameter/default/database_password rename to cdist/conf/type/__dpkg_architecture/nonparallel diff --git a/cdist/conf/type/__dpkg_architecture/parameter/default/state b/cdist/conf/type/__dpkg_architecture/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__dpkg_architecture/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__dpkg_architecture/parameter/optional b/cdist/conf/type/__dpkg_architecture/parameter/optional new file mode 100644 index 00000000..ff72b5c7 --- /dev/null +++ b/cdist/conf/type/__dpkg_architecture/parameter/optional @@ -0,0 +1 @@ +state diff --git a/cdist/conf/type/__file/explorer/stat b/cdist/conf/type/__file/explorer/stat index 91c8cc84..29b3c8a3 100755 --- a/cdist/conf/type/__file/explorer/stat +++ b/cdist/conf/type/__file/explorer/stat @@ -31,10 +31,10 @@ fallback() { gid=$(echo "$ls_line" | awk '{ print $4 }') owner=$(awk -F: -v uid="$uid" '$3 == uid { print $1; f=1 } END { if (!f) print "UNKNOWN" }' /etc/passwd) - group=$(awk -F: -v uid="$uid" '$3 == uid { print $1; f=1 } END { if (!f) print "UNKNOWN" }' /etc/group) + group=$(awk -F: -v gid="$gid" '$3 == gid { print $1; f=1 } END { if (!f) print "UNKNOWN" }' /etc/group) mode_text=$(echo "$ls_line" | awk '{ print $1 }') - mode=$(echo "$mode_text" | awk '{ k=0; for (i=0; i<=8; i++) k += ((substr($1, i+2, 1) ~ /[rwx]/) * 2^(8-i)); printf("%0o", k) }') + mode=$(echo "$mode_text" | awk '{for(i=8;i>=0;--i){c=substr($1,10-i,1);k+=((c~/[rwxst]/)*2^i);if(!(i%3))k+=(tolower(c)~/[lst]/)*2^(9+i/3)}printf("%04o",k)}') size=$(echo "$ls_line" | awk '{ print $5 }') links=$(echo "$ls_line" | awk '{ print $2 }') @@ -53,64 +53,32 @@ fallback() { [ -e "$destination" ] || exit 0 -if ! command -v stat >/dev/null -then +command -v stat >/dev/null 2>&1 || { fallback exit -fi +} case $("$__explorer/os") in freebsd|netbsd|openbsd|macosx) - stat -f "type: %HT + stat -f 'type: %HT owner: %Du %Su group: %Dg %Sg -mode: %Lp %Sp +mode: %Mp%03Lp %Sp size: %Dz links: %Dl -" "$destination" | awk '/^type/ { print tolower($0); next } { print }' +' "$destination" | awk '/^type/ { print tolower($0); next } { print }' ;; - solaris) - ls1="$( ls -ld "$destination" )" - ls2="$( ls -ldn "$destination" )" - - if [ -f "$__object/parameter/mode" ] - then mode_should="$( cat "$__object/parameter/mode" )" - fi - - # yes, it is ugly hack, but if you know better way... - if [ -z "$( find "$destination" -perm "$mode_should" )" ] - then octets=888 - else octets="$( echo "$mode_should" | sed 's/^0//' )" - fi - - case "$( echo "$ls1" | cut -c1-1 )" in - -) echo 'type: regular file' ;; - d) echo 'type: directory' ;; - esac - - echo "owner: $( echo "$ls2" \ - | awk '{print $3}' ) $( echo "$ls1" \ - | awk '{print $3}' )" - - echo "group: $( echo "$ls2" \ - | awk '{print $4}' ) $( echo "$ls1" \ - | awk '{print $4}' )" - - echo "mode: $octets $( echo "$ls1" | awk '{print $1}' )" - echo "size: $( echo "$ls1" | awk '{print $5}' )" - echo "links: $( echo "$ls1" | awk '{print $2}' )" - ;; *) # NOTE: Do not use --printf here as it is not supported by BusyBox stat. # NOTE: BusyBox's stat might not support the "-c" option, in which case # we fall through to the shell fallback. - stat -c "type: %F + stat -c 'type: %F owner: %u %U group: %g %G -mode: %a %A +mode: %04a %A size: %s -links: %h" "$destination" 2>/dev/null || fallback - ;; +links: %h' "$destination" 2>/dev/null || fallback + ;; esac diff --git a/cdist/conf/type/__file/gencode-local b/cdist/conf/type/__file/gencode-local index fb9f9a92..231b6927 100755 --- a/cdist/conf/type/__file/gencode-local +++ b/cdist/conf/type/__file/gencode-local @@ -31,12 +31,24 @@ if [ "$state_should" = "pre-exists" ]; then exit 1 fi - if [ "$type" = "file" ]; then - exit 0 # nothing to do - else - echo "File \"$destination\" does not exist" - exit 1 - fi + case $type in + file) + # nothing to do + exit 0 + ;; + none) + printf 'File "%s" does not exist\n' "$destination" >&2 + exit 1 + ;; + directory|symlink) + printf 'File "%s" exists and is a %s, but should be a regular file\n' "$destination" "$type" >&2 + exit 1 + ;; + *) + printf 'File or directory "%s" is in an unknown state\n' "$destination" >&2 + exit 1 + ;; + esac fi upload_file= diff --git a/cdist/conf/type/__file/gencode-remote b/cdist/conf/type/__file/gencode-remote index b04c471e..f7a528fd 100755 --- a/cdist/conf/type/__file/gencode-remote +++ b/cdist/conf/type/__file/gencode-remote @@ -55,35 +55,36 @@ set_owner() { } set_mode() { - echo "chmod '$1' '$destination'" - echo "chmod '$1'" >> "$__messages_out" - fire_onchange=1 + echo "chmod '$1' '$destination'" + echo "chmod '$1'" >> "$__messages_out" + fire_onchange=1 } case "$state_should" in - present|exists|pre-exists) - # Note: Mode - needs to happen last as a chown/chgrp can alter mode by - # clearing S_ISUID and S_ISGID bits (see chown(2)) - for attribute in group owner mode; do - if [ -f "$__object/parameter/$attribute" ]; then - value_should="$(cat "$__object/parameter/$attribute")" + present|exists) + # Note: Mode - needs to happen last as a chown/chgrp can alter mode by + # clearing S_ISUID and S_ISGID bits (see chown(2)) + for attribute in group owner mode; do + if [ -f "$__object/parameter/$attribute" ]; then + value_should="$(cat "$__object/parameter/$attribute")" - # change 0xxx format to xxx format => same as stat returns - if [ "$attribute" = mode ]; then - value_should="$(echo "$value_should" | sed 's/^0\(...\)/\1/')" - fi - - value_is="$(get_current_value "$attribute" "$value_should")" - if [ -f "$__object/files/set-attributes" ] || [ "$value_should" != "$value_is" ]; then - "set_$attribute" "$value_should" + # format mode in four digits => same as stat returns + if [ "$attribute" = mode ]; then + # Convert to four-digit octal number (printf interprets + # strings with leading 0s as octal!) + value_should=$(printf '%04o' "0${value_should}") + fi + + value_is="$(get_current_value "$attribute" "$value_should")" + if [ -f "$__object/files/set-attributes" ] || [ "$value_should" != "$value_is" ]; then + "set_$attribute" "$value_should" + fi fi + done + if [ -f "$__object/files/set-attributes" ]; then + # set-attributes is created if file is created or uploaded in gencode-local + fire_onchange=1 fi - done - if [ -f "$__object/files/set-attributes" ]; then - # set-attributes is created if file is created or uploaded in gencode-local - fire_onchange=1 - fi - ;; absent) @@ -94,6 +95,10 @@ case "$state_should" in fi ;; + pre-exists) + : + ;; + *) echo "Unknown state: $state_should" >&2 exit 1 @@ -101,7 +106,7 @@ case "$state_should" in esac if [ -f "$__object/parameter/onchange" ]; then - if [ -n "$fire_onchange" ]; then - cat "$__object/parameter/onchange" - fi + if [ -n "$fire_onchange" ]; then + cat "$__object/parameter/onchange" + fi fi diff --git a/cdist/conf/type/__file/man.rst b/cdist/conf/type/__file/man.rst index 7a0603bb..2f3b9e69 100644 --- a/cdist/conf/type/__file/man.rst +++ b/cdist/conf/type/__file/man.rst @@ -50,13 +50,13 @@ state create or modify it group - Group to chgrp to. + Group to chgrp to. Defaults to ``root``. mode - Unix permissions, suitable for chmod. + Unix permissions, suitable for chmod. Defaults to a very secure ``0600``. owner - User to chown to. + User to chown to. Defaults to ``root``. source If supplied, copy this file from the host running cdist to the target. diff --git a/cdist/conf/type/__filesystem/explorer/lsblk b/cdist/conf/type/__filesystem/explorer/lsblk index 9ae544ac..9be3c575 100644 --- a/cdist/conf/type/__filesystem/explorer/lsblk +++ b/cdist/conf/type/__filesystem/explorer/lsblk @@ -18,16 +18,16 @@ # along with cdist. If not, see . # -os=$("$__explorer/os") +os=$("${__explorer:?}/os") -if [ -f "$__object/parameter/device" ]; then +if [ -f "${__object:?}/parameter/device" ]; then blkdev="$(cat "$__object/parameter/device")" else - blkdev="$__object_id" + blkdev="${__object_id:?}" fi case "$os" in - centos|fedora|redhat|suse|gentoo) + alpine|centos|fedora|redhat|suse|gentoo) if [ ! -x "$(command -v lsblk)" ]; then echo "lsblk is required for __filesystem type" >&2 exit 1 diff --git a/cdist/conf/type/__group/gencode-remote b/cdist/conf/type/__group/gencode-remote index 6091c548..ff63e218 100755 --- a/cdist/conf/type/__group/gencode-remote +++ b/cdist/conf/type/__group/gencode-remote @@ -88,7 +88,7 @@ if [ "$state" = "present" ]; then fi done if [ "$os" = "freebsd" ]; then - echo pw groupadd "$@" "$name" + echo pw groupadd "$name" "$@" else echo groupadd "$@" "$name" fi diff --git a/cdist/conf/type/__hostname/gencode-remote b/cdist/conf/type/__hostname/gencode-remote index ae224611..c1a97ac8 100755 --- a/cdist/conf/type/__hostname/gencode-remote +++ b/cdist/conf/type/__hostname/gencode-remote @@ -20,26 +20,27 @@ # along with cdist. If not, see . # -os=$(cat "$__global/explorer/os") -name_running=$(cat "$__global/explorer/hostname") -has_hostnamectl=$(cat "$__object/explorer/has_hostnamectl") +os=$(cat "${__global:?}/explorer/os") +name_running=$(cat "${__global:?}/explorer/hostname") +has_hostnamectl=$(cat "${__object:?}/explorer/has_hostnamectl") -if test -s "$__object/parameter/name" +if test -s "${__object:?}/parameter/name" then - name_should=$(cat "$__object/parameter/name") + name_should=$(cat "${__object:?}/parameter/name") else - case $os + case ${os} in # RedHat-derivatives and BSDs - centos|fedora|redhat|scientific|freebsd|macosx|netbsd|openbsd) + (centos|fedora|redhat|scientific|freebsd|macosx|netbsd|openbsd) # Hostname is FQDN - name_should="${__target_host}" - ;; - *) + name_should=${__target_host:?} + ;; + (*) # Hostname is only first component of FQDN - name_should="${__target_host%%.*}" - ;; + name_should=${__target_host:?} + name_should=${name_should%%.*} + ;; esac fi @@ -47,43 +48,46 @@ fi ################################################################################ # Check if the (running) hostname is already correct # -test "$name_running" != "$name_should" || exit 0 +test "${name_running}" != "${name_should}" || exit 0 ################################################################################ # Setup hostname # -echo 'changed' >>"$__messages_out" +echo 'changed' >>"${__messages_out:?}" # Use the good old way to set the hostname. -case $os +case ${os} in - alpine|debian|devuan|ubuntu) + (alpine|debian|devuan|ubuntu) echo 'hostname -F /etc/hostname' - ;; - archlinux) + ;; + (archlinux) echo 'command -v hostnamectl >/dev/null 2>&1' \ - "&& hostnamectl set-hostname '$name_should'" \ - "|| hostname '$name_should'" - ;; - centos|fedora|redhat|scientific|freebsd|netbsd|openbsd|gentoo|void) - echo "hostname '$name_should'" - ;; - macosx) - echo "scutil --set HostName '$name_should'" - ;; - solaris) - echo "uname -S '$name_should'" - ;; - slackware|suse|opensuse-leap) + "&& hostnamectl set-hostname '${name_should}'" \ + "|| hostname '${name_should}'" + ;; + (centos|fedora|redhat|scientific|freebsd|netbsd|openbsd|gentoo|void) + echo "hostname '${name_should}'" + ;; + (openwrt) + echo "echo '${name_should}' >/proc/sys/kernel/hostname" + ;; + (macosx) + echo "scutil --set HostName '${name_should}'" + ;; + (solaris) + echo "uname -S '${name_should}'" + ;; + (slackware|suse) # We do not read from /etc/HOSTNAME, because the running # hostname is the first component only while the file contains # the FQDN. - echo "hostname '$name_should'" - ;; - *) + echo "hostname '${name_should}'" + ;; + (*) # Fall back to set the hostname using hostnamectl, if available. - if test -n "$has_hostnamectl" + if test -n "${has_hostnamectl}" then # Don't use hostnamectl as the primary means to set the hostname for # systemd systems, because it cannot be trusted to work reliably and @@ -94,7 +98,8 @@ in echo "test \"\$(hostname)\" = \"\$(cat /etc/hostname)\"" \ " || hostname -F /etc/hostname" else - printf "echo 'Unsupported OS: %s' >&2\nexit 1\n" "$os" + printf "echo 'Unsupported OS: %s' >&2\n" "${os}" + printf 'exit 1\n' fi - ;; + ;; esac diff --git a/cdist/conf/type/__hostname/manifest b/cdist/conf/type/__hostname/manifest index e1e356a0..b80aa2ef 100755 --- a/cdist/conf/type/__hostname/manifest +++ b/cdist/conf/type/__hostname/manifest @@ -20,69 +20,49 @@ # along with cdist. If not, see . # -not_supported() { - echo "Your operating system ($os) is currently not supported by this type (${__type##*/})." >&2 - echo "Please contribute an implementation for it if you can." >&2 - exit 1 -} - set_hostname_systemd() { echo "$1" | __file /etc/hostname --source - } -os=$(cat "$__global/explorer/os") -os_version=$(cat "$__global/explorer/os_version") -os_major=$(echo "$os_version" | grep -o '^[0-9][0-9]*' || true) +os=$(cat "${__global:?}/explorer/os") -max_len=$(cat "$__object/explorer/max_len") -has_hostnamectl=$(cat "$__object/explorer/has_hostnamectl") +max_len=$(cat "${__object:?}/explorer/max_len") +has_hostnamectl=$(cat "${__object:?}/explorer/has_hostnamectl") -if test -s "$__object/parameter/name" +if test -s "${__object:?}/parameter/name" then - name_should=$(cat "$__object/parameter/name") + name_should=$(cat "${__object:?}/parameter/name") else - case $os + case ${os} in # RedHat-derivatives and BSDs - centos|fedora|redhat|scientific|freebsd|netbsd|openbsd|slackware) + (centos|fedora|redhat|scientific|freebsd|netbsd|openbsd|slackware|suse) # Hostname is FQDN - name_should="${__target_host}" - ;; - suse|opensuse-leap) - # Classic SuSE stores the FQDN in /etc/HOSTNAME, while - # systemd does not. The running hostname is the first - # component in both cases. - # In versions before 15.x, the FQDN is stored in /etc/hostname. - if test -n "$has_hostnamectl" && test "$os_major" -ge 15 \ - && test "$os_major" -ne 42 - then - name_should="${__target_host%%.*}" - else - name_should="${__target_host}" - fi - ;; + name_should=${__target_host:?} + ;; *) # Hostname is only first component of FQDN on all other systems. - name_should="${__target_host%%.*}" - ;; + name_should=${__target_host:?} + name_should=${name_should%%.*} + ;; esac fi -if test -n "$max_len" && test "$(printf '%s' "$name_should" | wc -c)" -gt "$max_len" +if test -n "${max_len}" && test "$(printf '%s' "${name_should}" | wc -c)" -gt "${max_len}" then printf "Host name too long. Up to %u characters allowed.\n" "${max_len}" >&2 exit 1 fi -case $os +case ${os} in - alpine|debian|devuan|ubuntu|void) - echo "$name_should" | __file /etc/hostname --source - - ;; - archlinux) - if test -n "$has_hostnamectl" + (alpine|debian|devuan|ubuntu|void) + echo "${name_should}" | __file /etc/hostname --source - + ;; + (archlinux) + if test -n "${has_hostnamectl}" then - set_hostname_systemd "$name_should" + set_hostname_systemd "${name_should}" else echo 'Ancient ArchLinux variants without hostnamectl are not supported.' >&2 exit 1 @@ -97,8 +77,8 @@ in # --value "\"$name_should\"" fi ;; - centos|fedora|redhat|scientific) - if test -z "$has_hostnamectl" + (centos|fedora|redhat|scientific) + if test -z "${has_hostnamectl}" then # Only write to /etc/sysconfig/network on non-systemd versions. # On systemd-based versions this entry is ignored. @@ -106,59 +86,83 @@ in --file /etc/sysconfig/network \ --delimiter '=' --exact_delimiter \ --key HOSTNAME \ - --value "\"$name_should\"" + --value "\"${name_should}\"" else - set_hostname_systemd "$name_should" + set_hostname_systemd "${name_should}" fi - ;; - gentoo) + ;; + (gentoo) # Only write to /etc/conf.d/hostname on OpenRC-based installations. # On systemd use hostnamectl(1) in gencode-remote. - if test -z "$has_hostnamectl" + if test -z "${has_hostnamectl}" then __key_value '/etc/conf.d/hostname:hostname' \ --file /etc/conf.d/hostname \ --delimiter '=' --exact_delimiter \ --key 'hostname' \ - --value "\"$name_should\"" + --value "\"${name_should}\"" else set_hostname_systemd "$name_should" fi - ;; - freebsd) + ;; + (freebsd) __key_value '/etc/rc.conf:hostname' \ --file /etc/rc.conf \ --delimiter '=' --exact_delimiter \ --key 'hostname' \ - --value "\"$name_should\"" - ;; - macosx) + --value "\"${name_should}\"" + ;; + (macosx) # handled in gencode-remote - : - ;; - netbsd) + ;; + (netbsd) __key_value '/etc/rc.conf:hostname' \ --file /etc/rc.conf \ --delimiter '=' --exact_delimiter \ --key 'hostname' \ - --value "\"$name_should\"" + --value "\"${name_should}\"" # To avoid confusion, ensure that the hostname is only stored once. __file /etc/myname --state absent - ;; - openbsd) - echo "$name_should" | __file /etc/myname --source - - ;; - slackware) + ;; + (openbsd) + echo "${name_should}" | __file /etc/myname --source - + ;; + (openwrt) + __uci system.@system[0].hostname --value "${name_should}" + # --transaction hostname + ;; + (slackware) # We write the FQDN into /etc/HOSTNAME. But /etc/rc.d/rc.M will only # read the first component from this file and set it as the running # hostname on boot. - echo "$name_should" | __file /etc/HOSTNAME --source - - ;; - solaris) - echo "$name_should" | __file /etc/nodename --source - - ;; - suse|opensuse-leap) + echo "${name_should}" | __file /etc/HOSTNAME --source - + ;; + (solaris) + echo "${name_should}" | __file /etc/nodename --source - + ;; + (suse) + if test -s "${__global:?}/explorer/os_release" + then + # shellcheck source=/dev/null + os_version=$(. "${__global:?}/explorer/os_release" && echo "${VERSION}") + else + os_version=$(sed -n 's/^VERSION\ *=\ *//p' "${__global:?}/explorer/os_version") + fi + os_major=$(expr "${os_version}" : '\([0-9]\{1,\}\)') + + # Classic SuSE stores the FQDN in /etc/HOSTNAME, while + # systemd does not. The running hostname is the first + # component in both cases. + # In versions before 15.x, the FQDN is stored in /etc/hostname. + if test -n "${has_hostnamectl}" \ + && test "${os_major}" -ge 15 \ + && test "${os_major}" -ne 42 + then + # strip away everything but the first part from $name_should + name_should=${name_should%%.*} + fi + # Modern SuSE provides /etc/HOSTNAME as a symlink for # backwards-compatibility. Unfortunately it cannot be used # here as __file does not follow the symlink. @@ -167,23 +171,25 @@ in # not work correctly on openSUSE 12.x which provides # hostnamectl but not /etc/hostname. - if test -n "$has_hostnamectl" -a "$os_major" -gt 12 + if test -n "${has_hostnamectl}" -a "${os_major}" -gt 12 then - hostname_file='/etc/hostname' + hostname_file=/etc/hostname else - hostname_file='/etc/HOSTNAME' + hostname_file=/etc/HOSTNAME fi - echo "$name_should" | __file "$hostname_file" --source - - ;; - *) + echo "${name_should}" | __file "${hostname_file}" --source - + ;; + (*) # On other operating systems we fall back to systemd's # hostnamectl if available… - if test -n "$has_hostnamectl" + if test -n "${has_hostnamectl}" then - set_hostname_systemd "$name_should" + set_hostname_systemd "${name_should}" else - not_supported + echo "Your operating system (${os}) is currently not supported by this type (${__type##*/})." >&2 + echo "Please contribute an implementation for it if you can." >&2 + exit 1 fi - ;; + ;; esac diff --git a/cdist/conf/type/__hosts/man.rst b/cdist/conf/type/__hosts/man.rst index bece7967..1ac706cb 100644 --- a/cdist/conf/type/__hosts/man.rst +++ b/cdist/conf/type/__hosts/man.rst @@ -25,6 +25,10 @@ ip state is ``present``, this parameter is mandatory, if state is ``absent``, this parameter is silently ignored. +alias + An alias for the hostname. + This parameter can be specified multiple times (once per alias). + EXAMPLES -------- @@ -36,6 +40,8 @@ EXAMPLES # previously configured via __hosts. __hosts happy --state absent + __hosts srv1.example.com --ip 192.168.0.42 --alias srv1 + SEE ALSO -------- @@ -43,13 +49,14 @@ SEE ALSO AUTHORS ------- - -Dmitry Bogatov +| Dmitry Bogatov +| Dennis Camera COPYING ------- -Copyright (C) 2015,2016 Dmitry Bogatov. Free use of this software is granted -under the terms of the GNU General Public License version 3 or later -(GPLv3+). +Copyright \(C) 2015-2016 Dmitry Bogatov, 2019 Dennis Camera. +You can redistribute it and/or modify it under the terms of the GNU General +Public License as published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. diff --git a/cdist/conf/type/__hosts/manifest b/cdist/conf/type/__hosts/manifest index c536b83b..8103ebd5 100755 --- a/cdist/conf/type/__hosts/manifest +++ b/cdist/conf/type/__hosts/manifest @@ -1,29 +1,42 @@ #!/bin/sh -e -# Copyright (C) 2015 Bogatov Dmitry # -# This program is free software: you can redistribute it and/or modify +# Copyright (C) 2015 Bogatov Dmitry +# 2019 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, +# cdist is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -set -ue +# -hostname="$__object_id" -state="$(cat "$__object/parameter/state")" -marker="# __hosts/$hostname" +set -e -set -- "__hosts/$hostname" --file /etc/hosts --state "$state" +hostname=$__object_id +state=$(cat "${__object}/parameter/state") +marker="# __hosts/${hostname}" -if [ "$state" = absent ] ; then - __line "$@" --regex "$marker" +if test "${state}" != 'absent' +then + ip=$(cat "${__object}/parameter/ip") + if test -s "${__object}/parameter/alias" + then + aliases=$(while read -r a; do printf '\t%s' "$a"; done <"$__object/parameter/alias") + fi + + set -- --line "$(printf '%s\t%s%s %s' \ + "${ip}" "${hostname}" "${aliases}" "${marker}")" else - ip="$(cat "$__object/parameter/ip")" - __line "$@" --line "$ip $hostname $marker" + set -- --regex "$(echo "${marker}" | sed -e 's/\./\\./')$" fi + +__line "/etc/hosts:${hostname}" --file /etc/hosts --state "${state}" "$@" diff --git a/cdist/conf/type/__hosts/parameter/optional_multiple b/cdist/conf/type/__hosts/parameter/optional_multiple new file mode 100644 index 00000000..d077ed80 --- /dev/null +++ b/cdist/conf/type/__hosts/parameter/optional_multiple @@ -0,0 +1 @@ +alias diff --git a/cdist/conf/type/__hwclock/explorer/adjtime_mode b/cdist/conf/type/__hwclock/explorer/adjtime_mode new file mode 100755 index 00000000..2b27bedc --- /dev/null +++ b/cdist/conf/type/__hwclock/explorer/adjtime_mode @@ -0,0 +1,28 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# Prints the clock mode read from the /etc/adjtime file, if present. +# + +# not all operating systems use an adjfile +test -f /etc/adjtime || exit 0 + +# 3rd line is clock mode +# adjtime(5) https://man7.org/linux/man-pages/man5/adjtime.5.html +sed -n 3p /etc/adjtime diff --git a/cdist/conf/type/__hwclock/explorer/timedatectl_localrtc b/cdist/conf/type/__hwclock/explorer/timedatectl_localrtc new file mode 100755 index 00000000..8239122e --- /dev/null +++ b/cdist/conf/type/__hwclock/explorer/timedatectl_localrtc @@ -0,0 +1,27 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# Prints the LocalRTC property using timedatectl on systemd-based systems. +# + +command -v timedatectl >/dev/null 2>&1 || exit 0 + +# NOTE: Older versions of timedatectl do not support `timedatectl show' +timedatectl --no-pager status \ +| awk -F': ' '$1 ~ "RTC in local TZ$" { sub(/[ \t]*$/, "", $2); print $2 }' diff --git a/cdist/conf/type/__hwclock/gencode-remote b/cdist/conf/type/__hwclock/gencode-remote new file mode 100755 index 00000000..5995fb23 --- /dev/null +++ b/cdist/conf/type/__hwclock/gencode-remote @@ -0,0 +1,62 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +mode=$(cat "${__object:?}/parameter/mode") + +timedatectl_localrtc=$(cat "${__object:?}/explorer/timedatectl_localrtc") +adjtime_mode=$(cat "${__object:?}/explorer/adjtime_mode") + + +case ${mode} +in + (localtime) + adjtime_str=LOCAL + local_rtc_str=yes + ;; + (UTC|utc) + adjtime_str=UTC + local_rtc_str=no + ;; + (*) + printf 'Invalid value for --mode: %s\n' "${mode}" >&2 + printf 'Acceptable values are: localtime, utc.\n' >&2 + exit 1 +esac + + +if test -n "${timedatectl_localrtc}" +then + # systemd + timedatectl_should=${local_rtc_str} + if test "${timedatectl_localrtc}" != "${timedatectl_should}" + then + printf 'timedatectl set-local-rtc %s\n' "${timedatectl_should}" + fi +elif test -n "${adjtime_mode}" +then + # others (update /etc/adjtime if present) + if test "${adjtime_mode}" != "${adjtime_str}" + then + # Update /etc/adjtime (3rd line is clock mode) + # adjtime(5) https://man7.org/linux/man-pages/man5/adjtime.5.html + # FIXME: Should maybe add third line if adjfile only contains two lines + printf "sed -i '3c\\\\\\n%s\\n' /etc/adjtime\\n" "${adjtime_str}" + fi +fi diff --git a/cdist/conf/type/__hwclock/man.rst b/cdist/conf/type/__hwclock/man.rst new file mode 100644 index 00000000..65eb648f --- /dev/null +++ b/cdist/conf/type/__hwclock/man.rst @@ -0,0 +1,63 @@ +cdist-type__hwclock(7) +====================== + +NAME +---- +cdist-type__hwclock - Manage the hardware real time clock. + + +DESCRIPTION +----------- +This type can be used to control how the hardware clock is used by the operating +system. + + +REQUIRED PARAMETERS +------------------- +mode + What mode the hardware clock is in. + + Acceptable values: + + localtime + The hardware clock is set to local time (common for systems also running + Windows.) + UTC + The hardware clock is set to UTC (common on UNIX systems.) + + +OPTIONAL PARAMETERS +------------------- +None. + + +BOOLEAN PARAMETERS +------------------ +None. + + +EXAMPLES +-------- + +.. code-block:: sh + + # Make the operating system treat the time read from the hwclock as UTC. + __hwclock --mode UTC + + +SEE ALSO +-------- +:strong:`hwclock`\ (8) + + +AUTHORS +------- +Dennis Camera + + +COPYING +------- +Copyright \(C) 2020 Dennis Camera. You can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. diff --git a/cdist/conf/type/__hwclock/manifest b/cdist/conf/type/__hwclock/manifest new file mode 100755 index 00000000..7d9ab88f --- /dev/null +++ b/cdist/conf/type/__hwclock/manifest @@ -0,0 +1,222 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +# TODO: Consider supporting BADYEAR + +os=$(cat "${__global:?}/explorer/os") +mode=$(cat "${__object:?}/parameter/mode") + +has_systemd_timedatectl=$(test -s "${__object:?}/explorer/timedatectl_localrtc" && echo true || echo false) + + +case ${mode} +in + (localtime) + local_clock=true + ;; + (UTC|utc) + local_clock=false + ;; + (*) + printf 'Invalid value for --mode: %s\n' "${mode}" >&2 + printf 'Acceptable values are: UTC, localtime.\n' >&2 + exit 1 +esac + + +case ${os} +in + (alpine|gentoo) + if ! $has_systemd_timedatectl + then + # NOTE: Gentoo also supports systemd, in which case /etc/conf.d is + # not used. So we check for systemd presence here and only + # update /etc/conf.d if systemd is not installed. + # https://wiki.gentoo.org/wiki/System_time#Hardware_clock + + export CDIST_ORDER_DEPENDENCY=true + __file /etc/conf.d/hwclock --state present \ + --owner root --group root --mode 0644 + __key_value /etc/conf.d/hwclock:clock \ + --file /etc/conf.d/hwclock \ + --key clock \ + --delimiter '=' --exact_delimiter \ + --value "\"$($local_clock && echo local || echo UTC)\"" + unset CDIST_ORDER_DEPENDENCY + fi + ;; + (centos|fedora|redhat|scientific) + os_version=$(cat "${__global:?}/explorer/os_version") + os_major=$(expr "${os_version}" : '.* release \([0-9]*\)') + case ${os} + in + (centos|scientific) + update_sysconfig=$(test "${os_major}" -lt 6 && echo true || echo false) + ;; + (fedora) + update_sysconfig=$(test "${os_major}" -lt 10 && echo true || echo false) + ;; + (redhat|*) + case ${os_version} + in + ('Red Hat Enterprise Linux'*) + update_sysconfig=$(test "${os_major}" -lt 6 && echo true || echo false) + ;; + ('Red Hat Linux'*) + update_sysconfig=true + ;; + (*) + printf 'Could not determine Red Hat distribution.\n' >&2 + printf "Please contribute an implementation for it if you can.\n" >&2 + exit 1 + ;; + esac + ;; + esac + + if ${update_sysconfig:?} + then + export CDIST_ORDER_DEPENDENCY=true + __file /etc/sysconfig/clock --state present \ + --owner root --group root --mode 0644 + __key_value /etc/sysconfig/clock:UTC \ + --file /etc/sysconfig/clock \ + --key UTC \ + --delimiter '=' --exact_delimiter \ + --value "$($local_clock && echo false || echo true)" + unset CDIST_ORDER_DEPENDENCY + fi + ;; + (debian|devuan|ubuntu) + os_major=$(sed 's/[^0-9].*$//' "${__global:?}/explorer/os_version") + + case ${os} + in + (debian) + if test "${os_major}" -ge 7 + then + update_rcS=false + elif test "${os_major}" -ge 3 + then + update_rcS=true + else + # Debian 2.2 should be supportable using rcS. + # Debian 2.1 uses the ancient GMT key. + # Debian 1.3 does not have rcS. + printf "Your operating system (Debian %s) is currently not supported by this type (%s)\n" \ + "$(cat "${__global:?}/explorer/os_version")" "${__type##*/}" >&2 + printf "Please contribute an implementation for it if you can.\n" >&2 + exit 1 + fi + ;; + (devuan) + update_rcS=false + ;; + (ubuntu) + update_rcS=$(test "${os_major}" -lt 16 && echo true || echo false) + ;; + esac + + if ${update_rcS} + then + export CDIST_ORDER_DEPENDENCY=true + __file /etc/default/rcS --state present \ + --owner root --group root --mode 0644 + __key_value /etc/default/rcS:UTC \ + --file /etc/default/rcS \ + --key UTC \ + --delimiter '=' --exact_delimiter \ + --value "$($local_clock && echo no || echo yes)" + unset CDIST_ORDER_DEPENDENCY + fi + ;; + (freebsd) + # cf. adjkerntz(8) + __file /etc/wall_cmos_clock \ + --state "$($local_clock && echo present || echo absent)" \ + --owner root --group wheel --mode 0444 + ;; + (netbsd) + # https://wiki.netbsd.org/guide/boot/#index9h2 + __key_value /etc/rc.conf:rtclocaltime \ + --file /etc/rc.conf \ + --key rtclocaltime \ + --delimiter '=' --exact_delimiter \ + --value "$($local_clock && echo YES || echo NO)" + ;; + (slackware) + __file /etc/hardwareclock --owner root --group root --mode 0644 \ + --source - <<-EOF + # /etc/hardwareclock + # + # Tells how the hardware clock time is stored. + # This file is managed by cdist. + + $($local_clock && echo localtime || echo UTC) + EOF + ;; + (suse) + if test -s "${__global:?}/explorer/os_release" + then + # shellcheck source=/dev/null + os_version=$(. "${__global:?}/explorer/os_release" && echo "${VERSION}") + else + os_version=$(sed -n 's/^VERSION\ *=\ *//p' "${__global:?}/explorer/os_version") + fi + os_major=$(expr "${os_version}" : '\([0-9]\{1,\}\)') + + # TODO: Consider using `yast2 timezone set hwclock' instead + if expr "${os_major}" \< 12 + then + # Starting with SuSE 12 (first systemd-based version) + # /etc/sysconfig/clock does not contain the HWCLOCK line + # anymore. + # With SuSE 13, it has been reduced to TIMEZONE configuration. + __key_value /etc/sysconfig/clock:HWCLOCK \ + --file /etc/sysconfig/clock \ + --delimiter '=' --exact_delimiter \ + --key HWCLOCK \ + --value "$($local_clock && echo '"--localtime"' || echo '"-u"')" + fi + ;; + (void) + export CDIST_ORDER_DEPENDENCY=true + __file /etc/rc.conf \ + --owner root --group root --mode 0644 \ + --state present + __key_value /etc/rc.conf:HARDWARECLOCK \ + --file /etc/rc.conf \ + --delimiter '=' --exact_delimiter \ + --key HARDWARECLOCK \ + --value "\"$($local_clock && echo localtime || echo UTC)\"" + unset CDIST_ORDER_DEPENDENCY + ;; + (*) + if ! $has_systemd_timedatectl + then + printf "Your operating system (%s) is currently not supported by this type (%s)\n" "$os" "${__type##*/}" >&2 + printf "Please contribute an implementation for it if you can.\n" >&2 + exit 1 + fi + ;; +esac + +# NOTE: timedatectl set-local-rtc for systemd is in gencode-remote +# NOTE: /etc/adjtime is also updated in gencode-remote diff --git a/cdist/conf/type/__hwclock/parameter/required b/cdist/conf/type/__hwclock/parameter/required new file mode 100644 index 00000000..17ab372f --- /dev/null +++ b/cdist/conf/type/__hwclock/parameter/required @@ -0,0 +1 @@ +mode diff --git a/cdist/conf/type/__matrix_synapse/singleton b/cdist/conf/type/__hwclock/singleton similarity index 100% rename from cdist/conf/type/__matrix_synapse/singleton rename to cdist/conf/type/__hwclock/singleton diff --git a/cdist/conf/type/__pf_apply/explorer/rcvar b/cdist/conf/type/__ipset/explorer/content similarity index 65% rename from cdist/conf/type/__pf_apply/explorer/rcvar rename to cdist/conf/type/__ipset/explorer/content index 7c8d535f..87f6b517 100755 --- a/cdist/conf/type/__pf_apply/explorer/rcvar +++ b/cdist/conf/type/__ipset/explorer/content @@ -1,6 +1,6 @@ #!/bin/sh # -# 2012 Jake Guffey (jake.guffey at eprotex.com) +# 2021 Mesar Hameed (mesar.hameed at gmail.com) # # This file is part of cdist. # @@ -17,20 +17,10 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # -# -# Get the location of the pf ruleset on the target host. -# - -# Debug -#exec >&2 -#set -x - -# Check /etc/rc.conf for pf's configuration file name. Default to /etc/pf.conf - -RC="/etc/rc.conf" -PFCONF="$(grep '^pf_rules=' ${RC} | cut -d= -f2 | sed 's/"//g')" -echo "${PFCONF:-"/etc/pf.conf"}" - -# Debug -#set +x +name="$__object_id" +if ipset -t list | grep -qFx "Name: $name"; then + ipset list "$name" | sed '0,/^Members:/d' +else + echo "x_missing_x" +fi diff --git a/cdist/conf/type/__pf_ruleset/explorer/cksum b/cdist/conf/type/__ipset/explorer/state similarity index 55% rename from cdist/conf/type/__pf_ruleset/explorer/cksum rename to cdist/conf/type/__ipset/explorer/state index 9be6c901..9ece28df 100755 --- a/cdist/conf/type/__pf_ruleset/explorer/cksum +++ b/cdist/conf/type/__ipset/explorer/state @@ -1,6 +1,6 @@ #!/bin/sh # -# 2012 Jake Guffey (jake.guffey at eprotex.com) +# 2021 Mesar Hameed (mesar.hameed at gmail.com) # # This file is part of cdist. # @@ -17,25 +17,10 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # -# -# Get the 256 bit SHA2 checksum of the pf ruleset on the target host. -# -# Debug -#exec >&2 -#set -x - -# Check /etc/rc.conf for pf's configuration file name. Default to /etc/pf.conf -# See if file exists and if so, get checksum - -RC="/etc/rc.conf" -TMP="$(grep '^pf_rules=' ${RC} | cut -d= -f2 | sed 's/"//g')" -PFCONF="${TMP:-"/etc/pf.conf"}" - -if [ -f "${PFCONF}" ]; then # The pf config file exists, find its cksum. - cksum -o 1 "${PFCONF}" | cut -d= -f2 | awk '{print $1}' +name="$__object_id" +if ipset -t list "$name" >/dev/null; then + echo "present" +else + echo "absent" fi - -# Debug -#set +x - diff --git a/cdist/conf/type/__ipset/explorer/type b/cdist/conf/type/__ipset/explorer/type new file mode 100755 index 00000000..9413cdad --- /dev/null +++ b/cdist/conf/type/__ipset/explorer/type @@ -0,0 +1,26 @@ +#!/bin/sh +# +# 2021 Mesar Hameed (mesar.hameed at gmail.com) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +name="$__object_id" +if ipset -t list | grep -qFx "Name: $name"; then + ipset -t list "$name" | grep "^Type: " | awk '{print $2}' +else + echo "x_missing_x" +fi diff --git a/cdist/conf/type/__ipset/files/ipset-persistent b/cdist/conf/type/__ipset/files/ipset-persistent new file mode 100755 index 00000000..e812c30f --- /dev/null +++ b/cdist/conf/type/__ipset/files/ipset-persistent @@ -0,0 +1,48 @@ +#!/bin/sh +# +# 2021 Mesar Hameed (mesar.hameed at gmail.com) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# +### BEGIN INIT INFO +# Provides: ipset +# Required-Start: $local_fs $remote_fs +# Required-Stop: $local_fs $remote_fs +# X-Start-Before: iptables +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Create ipset lists before iptables rules require them +# Description: Applies lists found in /etc/ipset.d/*.saved +# and saves/restores previous status +### END INIT INFO + +case $1 in + start) + # Restore previous state: + /usr/local/bin/ipsets-restore + ;; + stop) + # Save current state before exiting: + /usr/local/bin/ipsets-save + ;; + restart) + "$0" stop && "$0" start + ;; + reset) + ipset flush + ;; +esac diff --git a/cdist/conf/type/__ipset/files/ipsets-restore b/cdist/conf/type/__ipset/files/ipsets-restore new file mode 100755 index 00000000..30df3a13 --- /dev/null +++ b/cdist/conf/type/__ipset/files/ipsets-restore @@ -0,0 +1,28 @@ +#!/bin/sh +# +# 2021 Mesar Hameed (mesar.hameed at gmail.com) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +mkdir -p /etc/ipset.d/ +if [ -n "$1" ]; then + ipset -! restore < "/etc/ipset.d/$1" +else +find /etc/ipset.d/ -iname "*.saved" | while read s; do + ipset -! restore <$s +done +fi diff --git a/cdist/conf/type/__ipset/files/ipsets-save b/cdist/conf/type/__ipset/files/ipsets-save new file mode 100755 index 00000000..9f5a9f3a --- /dev/null +++ b/cdist/conf/type/__ipset/files/ipsets-save @@ -0,0 +1,28 @@ +#!/bin/sh +# +# 2021 Mesar Hameed (mesar.hameed at gmail.com) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +mkdir -p /etc/ipset.d/ +if [ -n "$1" ]; then + ipset save "$1" > "/etc/ipset.d/${1}.saved" +else +ipset -t list | grep "^Name:" | awk '{print $2}' | while read s; do + ipset save $s > /etc/ipset.d/$s.saved +done +fi diff --git a/cdist/conf/type/__ipset/gencode-remote b/cdist/conf/type/__ipset/gencode-remote new file mode 100755 index 00000000..38437a6c --- /dev/null +++ b/cdist/conf/type/__ipset/gencode-remote @@ -0,0 +1,79 @@ +#!/bin/sh +# +# 2021 Mesar Hameed (mesar.hameed at gmail.com) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +e="$__object/explorer" +p="$__object/parameter" +name="$__object_id" +type_is="$(cat "$e/type")" +type_should="$(cat "$p/type")" +state_is="$(cat "$e/state")" +state_should="$(cat "$p/state")" +needToSave=0 + +case $state_should in + present) + if [ "$state_is" = "absent" ]; then + echo ipset create "$name" "$type_should" + needToSave=1 + elif [ "$state_is" = "present" ] && [ "$type_is" != "$type_should" ]; then + echo ipset destroy "$name" + echo "rm \"/etc/ipset.d/${name}.saved\" || true" + echo ipset create "$name" "$type_should" + needToSave=1 + fi + ;; + absent) + if [ "$state_is" = "present" ]; then + echo ipset destroy "$name" + echo "rm \"/etc/ipset.d/${name}.saved\" || true" + fi + ;; + *) + echo "Unknown state: $state_should" >&2 + exit 1 + ;; +esac + +if [ "$state_should" = "present" ]; then + if [ -f "$p/add" ]; then + while read -r value; do + if ! grep -qFx "$value" "$e/content"; then + echo "ipset -! add $name $value" + needToSave=1 + fi + done < "$p/add" + fi + + if [ -f "$p/del" ]; then + while read -r value; do + if grep -qFx "$value" "$e/content"; then + echo "ipset -! del $name $value" + needToSave=1 + fi + done < "$p/del" + fi +elif [ "$state_should" = "absent" ] && \( [ -f "$p/add" ] || [ -f "$p/del" ] \); then + echo "Error: ipset state absent is incompatible with --add or --del" >&2 + exit 1 +fi + +if [ $needToSave -ne 0 ]; then + echo /usr/local/bin/ipsets-save "$name" +fi diff --git a/cdist/conf/type/__ipset/man.rst b/cdist/conf/type/__ipset/man.rst new file mode 100644 index 00000000..f376470e --- /dev/null +++ b/cdist/conf/type/__ipset/man.rst @@ -0,0 +1,69 @@ +cdist-type__ipset(7) +==================== + +NAME +---- +cdist-type__ipset - Manage ipset sets + +DESCRIPTION +----------- +Making use of ipset sets in iptable rules can make your rules more expressive, maintainable and efficient. + +REQUIRED PARAMETERS +------------------- +type + One of the supported ipset set types, for a full list see: + + ``ipset help`` + +OPTIONAL PARAMETERS +------------------- +add + The entry that must exist in the given set. + + Can be used multiple times. +del + The entry that must not exist in the given set. + + Can be used multiple times. +state + Can be: + + - ``present``: ensure that the given set exists. + - ``absent``: ensure the given set doesn't exist. + +BOOLEAN PARAMETERS +------------------ +None. + +EXAMPLES +-------- + +.. code-block:: sh + + # Make sure a set with the given name/type exists: + __ipset testset1 --type hash:ip + + # Ensure allowed_ssh_clients contains private range: + __ipset allowed_ssh_hosts --type hash:net \ + --add 192.168.0.0/24 --add 10.0.0.0/8 + + # Make sure host is not on the blocked list: + __ipset blocked_hosts --type hash:ip \ + --del 1.2.3.4 + + +SEE ALSO +-------- +:strong:`cdist-type__iptables_rule`\ (7), :strong:`iptables`\ (8) + +AUTHORS +------- +Mesar Hameed + +COPYING +------- +Copyright \(C) 2021 Mesar Hameed. You can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. diff --git a/cdist/conf/type/__ipset/manifest b/cdist/conf/type/__ipset/manifest new file mode 100755 index 00000000..769a50b8 --- /dev/null +++ b/cdist/conf/type/__ipset/manifest @@ -0,0 +1,45 @@ +#!/bin/sh -e +# +# 2021 Mesar Hameed (mesar.hameed at gmail.com) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# + +os=$(cat "$__global/explorer/os") +case "$os" in + debian) + : + ;; + ubuntu) + : + ;; + *) + echo "OS $os currently not supported" >&2 + exit 1 + ;; +esac + +export CDIST_ORDER_DEPENDENCY=on + +# install packages +__package ipset + +__file /etc/init.d/ipset-persistent --mode 0755 --source "${__type}/files/ipset-persistent" +__file /usr/local/bin/ipsets-restore --mode 0755 --source "${__type}/files/ipsets-restore" +__file /usr/local/bin/ipsets-save --mode 0755 --source "${__type}/files/ipsets-save" +__systemd_unit ipset-persistent --enablement-state enabled --restart + +unset CDIST_ORDER_DEPENDENCY diff --git a/cdist/conf/type/__ipset/parameter/default/state b/cdist/conf/type/__ipset/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__ipset/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__ipset/parameter/optional b/cdist/conf/type/__ipset/parameter/optional new file mode 100644 index 00000000..ff72b5c7 --- /dev/null +++ b/cdist/conf/type/__ipset/parameter/optional @@ -0,0 +1 @@ +state diff --git a/cdist/conf/type/__ipset/parameter/optional_multiple b/cdist/conf/type/__ipset/parameter/optional_multiple new file mode 100644 index 00000000..4f890061 --- /dev/null +++ b/cdist/conf/type/__ipset/parameter/optional_multiple @@ -0,0 +1,2 @@ +add +del diff --git a/cdist/conf/type/__ipset/parameter/required b/cdist/conf/type/__ipset/parameter/required new file mode 100644 index 00000000..aa80e646 --- /dev/null +++ b/cdist/conf/type/__ipset/parameter/required @@ -0,0 +1 @@ +type diff --git a/cdist/conf/type/__iptables_apply/files/init-script b/cdist/conf/type/__iptables_apply/files/init-script index d9c79ef7..e42017ae 100644 --- a/cdist/conf/type/__iptables_apply/files/init-script +++ b/cdist/conf/type/__iptables_apply/files/init-script @@ -1,7 +1,4 @@ #!/bin/sh -# Nico Schottelius -# Zürisee, Mon Sep 2 18:38:27 CEST 2013 -# ### BEGIN INIT INFO # Provides: iptables # Required-Start: $local_fs $remote_fs @@ -14,34 +11,72 @@ # and saves/restores previous status ### END INIT INFO +# Originally written by: +# Nico Schottelius +# Zürisee, Mon Sep 2 18:38:27 CEST 2013 +# +# 2013 Nico Schottelius (nico-cdist at schottelius.org) +# 2020 Matthias Stecher (matthiasstecher at gmx.de) +# +# This file is distributed with cdist and licenced under the +# GNU GPLv3+ WITHOUT ANY WARRANTY. + + +# Read files and execute the content with the given commands +# +# Arguments: +# 1: Directory +# 2..n: Commands which should be used to execute the file content +gothrough() { + cd "$1" || return + shift + + # iterate through all rules and continue if it's not a file + for rule in *; do + [ -f "$rule" ] || continue + echo "Appling iptables rule $rule ..." + + # execute it with all commands specificed + ruleparam="$(cat "$rule")" + for cmd in "$@"; do + # Command and Rule should be split. + # shellcheck disable=SC2046 + command $cmd $ruleparam + done + done +} + +# Shortcut for iptables command to do IPv4 and v6 +# only applies to the "reset" target +iptables() { + command iptables "$@" + command ip6tables "$@" +} basedir=/etc/iptables.d -status="${basedir}/.pre-start" +status4="${basedir}/.pre-start" +status6="${basedir}/.pre-start6" case $1 in start) # Save status - iptables-save > "$status" + iptables-save > "$status4" + ip6tables-save > "$status6" # Apply our ruleset - cd "$basedir" || exit - count="$(find . ! -name . -prune | wc -l)" - - # Only do something if there are rules - if [ "$count" -ge 1 ]; then - for rule in *; do - echo "Applying iptables rule $rule ..." - # Rule should be split. - # shellcheck disable=SC2046 - iptables $(cat "$rule") - done - fi + gothrough "$basedir" iptables + #gothrough "$basedir/v4" iptables # conflicts with $basedir + gothrough "$basedir/v6" ip6tables + gothrough "$basedir/all" iptables ip6tables ;; stop) # Restore from status before, if there is something to restore - if [ -f "$status" ]; then - iptables-restore < "$status" + if [ -f "$status4" ]; then + iptables-restore < "$status4" + fi + if [ -f "$status6" ]; then + ip6tables-restore < "$status6" fi ;; restart) diff --git a/cdist/conf/type/__iptables_apply/man.rst b/cdist/conf/type/__iptables_apply/man.rst index 76e1f6bf..3bef92cc 100644 --- a/cdist/conf/type/__iptables_apply/man.rst +++ b/cdist/conf/type/__iptables_apply/man.rst @@ -10,7 +10,24 @@ DESCRIPTION ----------- This cdist type deploys an init script that triggers the configured rules and also re-applies them on -configuration. +configuration. Rules are written from __iptables_rule +into the folder ``/etc/iptables.d/``. + +It reads all rules from the base folder as rules for IPv4. +Rules in the subfolder ``v6/`` are IPv6 rules. Rules in +the subfolder ``all/`` are applied to both rule tables. All +files contain the arguments for a single ``iptables`` and/or +``ip6tables`` command. + +Rules are applied in the following order: +1. All IPv4 rules +2. All IPv6 rules +2. All rules that should be applied to both tables + +The order of the rules that will be applied are definite +from the result the shell glob returns, which should be +alphabetical. If rules must be applied in a special order, +prefix them with a number like ``02-some-rule``. REQUIRED PARAMETERS @@ -24,7 +41,7 @@ None EXAMPLES -------- -None (__iptables_apply is used by __iptables_rule) +None (__iptables_apply is used by __iptables_rule automatically) SEE ALSO @@ -35,11 +52,13 @@ SEE ALSO AUTHORS ------- Nico Schottelius +Matthias Stecher COPYING ------- -Copyright \(C) 2013 Nico Schottelius. You can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. +Copyright \(C) 2013 Nico Schottelius. +Copyright \(C) 2020 Matthias Stecher. +You can redistribute it and/or modify it under the terms of the GNU +General Public License as published by the Free Software Foundation, +either version 3 of the License, or (at your option) any later version. diff --git a/cdist/conf/type/__iptables_rule/man.rst b/cdist/conf/type/__iptables_rule/man.rst index 92d8859f..afb71e01 100644 --- a/cdist/conf/type/__iptables_rule/man.rst +++ b/cdist/conf/type/__iptables_rule/man.rst @@ -11,6 +11,10 @@ DESCRIPTION This cdist type allows you to manage iptable rules in a distribution independent manner. +See :strong:`cdist-type__iptables_apply`\ (7) for the +execution order of these rules. It will be executed +automaticly to apply all rules non-volaite. + REQUIRED PARAMETERS ------------------- @@ -25,6 +29,24 @@ state 'present' or 'absent', defaults to 'present' +BOOLEAN PARAMETERS +------------------ +All rules without any of these parameters will be treated like ``--v4`` because +of backward compatibility. + +v4 + Explicitly set it as rule for IPv4. If IPv6 is set, too, it will be + threaten like ``--all``. Will be the default if nothing else is set. + +v6 + Explicitly set it as rule for IPv6. If IPv4 is set, too, it will be + threaten like ``--all``. + +all + Set the rule for both IPv4 and IPv6. It will be saved separately from the + other rules. + + EXAMPLES -------- @@ -48,6 +70,16 @@ EXAMPLES --state absent + # IPv4-only rule for ICMPv4 + __iptables_rule icmp-v4 --v4 --rule "-A INPUT -p icmp -j ACCEPT" + # IPv6-only rule for ICMPv6 + __iptables_rule icmp-v6 --v6 --rule "-A INPUT -p icmpv6 -j ACCEPT" + + # doing something for the dual stack + __iptables_rule fwd-eth0-eth1 --v4 --v6 --rule "-A INPUT -i eth0 -o eth1 -j ACCEPT" + __iptables_rule fwd-eth1-eth0 --all --rule "-A -o eth1 -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT" + + SEE ALSO -------- :strong:`cdist-type__iptables_apply`\ (7), :strong:`iptables`\ (8) @@ -56,11 +88,13 @@ SEE ALSO AUTHORS ------- Nico Schottelius +Matthias Stecher COPYING ------- -Copyright \(C) 2013 Nico Schottelius. You can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. +Copyright \(C) 2013 Nico Schottelius. +Copyright \(C) 2020 Matthias Stecher. +You can redistribute it and/or modify it under the terms of the GNU +General Public License as published by the Free Software Foundation, +either version 3 of the License, or (at your option) any later version. diff --git a/cdist/conf/type/__iptables_rule/manifest b/cdist/conf/type/__iptables_rule/manifest index ed78787f..d4394c25 100755 --- a/cdist/conf/type/__iptables_rule/manifest +++ b/cdist/conf/type/__iptables_rule/manifest @@ -1,6 +1,7 @@ #!/bin/sh -e # # 2013 Nico Schottelius (nico-cdist at schottelius.org) +# 2020 Matthias Stecher (matthiasstecher at gmx.de) # # This file is part of cdist. # @@ -24,12 +25,36 @@ base_dir=/etc/iptables.d name="$__object_id" state="$(cat "$__object/parameter/state")" +if [ -f "$__object/parameter/v4" ]; then + only_v4="yes" + # $specific_dir is $base_dir +fi +if [ -f "$__object/parameter/v6" ]; then + only_v6="yes" + specific_dir="$base_dir/v6" +fi +# If rules should be set for both protocols +if { [ "$only_v4" = "yes" ] && [ "$only_v6" = "yes" ]; } || + [ -f "$__object/parameter/all" ]; then + + # all to a specific directory + specific_dir="$base_dir/all" +fi + +# set rule directory based on if it's the base or subdirectory +rule_dir="${specific_dir:-$base_dir}" + ################################################################################ # Basic setup # __directory "$base_dir" --state present +# sub-directory if required +if [ "$specific_dir" ]; then + require="__directory/$base_dir" __directory "$specific_dir" --state present +fi + # Have apply do the real job require="$__object_name" __iptables_apply @@ -37,6 +62,15 @@ require="$__object_name" __iptables_apply # The rule # -require="__directory/$base_dir" __file "$base_dir/${name}" \ - --source "$__object/parameter/rule" \ - --state "$state" +for dir in "$base_dir" "$base_dir/v6" "$base_dir/all"; do + # defaults to absent except the directory that should contain the file + if [ "$rule_dir" = "$dir" ]; then + curr_state="$state" + else + curr_state="absent" + fi + + require="__directory/$rule_dir" __file "$dir/$name" \ + --source "$__object/parameter/rule" \ + --state "$curr_state" +done diff --git a/cdist/conf/type/__iptables_rule/parameter/boolean b/cdist/conf/type/__iptables_rule/parameter/boolean new file mode 100644 index 00000000..76882272 --- /dev/null +++ b/cdist/conf/type/__iptables_rule/parameter/boolean @@ -0,0 +1,3 @@ +all +v4 +v6 diff --git a/cdist/conf/type/__key_value/explorer/state b/cdist/conf/type/__key_value/explorer/state index 7b2de1df..d24600af 100755 --- a/cdist/conf/type/__key_value/explorer/state +++ b/cdist/conf/type/__key_value/explorer/state @@ -40,7 +40,9 @@ else fi export key state delimiter value exact_delimiter -awk -f - "$file" <<"AWK_EOF" +awk_bin=$(PATH=$(getconf PATH 2>/dev/null) && command -v awk || echo awk) + +"${awk_bin}" -f - "$file" <<"AWK_EOF" BEGIN { state=ENVIRON["state"] key=ENVIRON["key"] diff --git a/cdist/conf/type/__key_value/files/remote_script.sh b/cdist/conf/type/__key_value/files/remote_script.sh index f7a1add5..faf080cb 100644 --- a/cdist/conf/type/__key_value/files/remote_script.sh +++ b/cdist/conf/type/__key_value/files/remote_script.sh @@ -24,7 +24,10 @@ if [ -f "$file" ]; then else touch "$file" fi -awk -f - "$file" >"$tmpfile" <<"AWK_EOF" + +awk_bin=$(PATH=$(getconf PATH 2>/dev/null) && command -v awk || echo awk) + +"${awk_bin}" -f - "$file" >"$tmpfile" <<"AWK_EOF" BEGIN { # import variables in a secure way .. state=ENVIRON["state"] diff --git a/cdist/conf/type/__key_value/gencode-remote b/cdist/conf/type/__key_value/gencode-remote index 13cc27c7..1174400e 100755 --- a/cdist/conf/type/__key_value/gencode-remote +++ b/cdist/conf/type/__key_value/gencode-remote @@ -25,7 +25,7 @@ state_should="$(cat "$__object/parameter/state")" state_is="$(cat "$__object/explorer/state")" fire_onchange='' -if [ "$state_is" = "$state_should" ]; then +if [ "$state_is" = "$state_should" ]; then exit 0 fi diff --git a/cdist/conf/type/__letsencrypt_cert/man.rst b/cdist/conf/type/__letsencrypt_cert/man.rst index c4ffc6bc..85eb88ea 100644 --- a/cdist/conf/type/__letsencrypt_cert/man.rst +++ b/cdist/conf/type/__letsencrypt_cert/man.rst @@ -59,13 +59,13 @@ MESSAGES -------- change - Certificte was changed. + Certificate was changed. create - Certificte was created. + Certificate was created. remove - Certificte was removed. + Certificate was removed. EXAMPLES -------- diff --git a/cdist/conf/type/__letsencrypt_cert/manifest b/cdist/conf/type/__letsencrypt_cert/manifest index 68ecf9d4..b4464366 100755 --- a/cdist/conf/type/__letsencrypt_cert/manifest +++ b/cdist/conf/type/__letsencrypt_cert/manifest @@ -91,6 +91,9 @@ if [ -z "${certbot_fullpath}" ]; then certbot_fullpath=/usr/local/bin/certbot ;; + ubuntu) + __package certbot + ;; *) echo "Unsupported os: $os" >&2 exit 1 diff --git a/cdist/conf/type/__line/explorer/state b/cdist/conf/type/__line/explorer/state index e8fc3630..9d480b19 100755 --- a/cdist/conf/type/__line/explorer/state +++ b/cdist/conf/type/__line/explorer/state @@ -53,8 +53,10 @@ function _find(_text, _pattern) { BEGIN { getline anchor < (ENVIRON["__object"] "/parameter/" position) getline pattern < (ENVIRON["__object"] "/parameter/" needle) + getline line < (ENVIRON["__object"] "/parameter/line") found_line = 0 + correct_line = 0 correct_pos = (position != "after" && position != "before") } { @@ -63,15 +65,18 @@ BEGIN { getline if (_find($0, pattern)) { found_line++ + if (index($0, line) == 1) { correct_line++ } correct_pos = 1 exit 0 } } else if (_find($0, pattern)) { found_line++ + if (index($0, line) == 1) { correct_line++ } } } else if (position == "before") { if (_find($0, pattern)) { found_line++ + if (index($0, line) == 1) { correct_line++ } getline if (match($0, anchor)) { correct_pos = 1 @@ -81,13 +86,18 @@ BEGIN { } else { if (_find($0, pattern)) { found_line++ + if (index($0, line) == 1) { correct_line++ } exit 0 } } } END { if (found_line && correct_pos) { - print "present" + if (correct_line) { + print "present" + } else { + print "matching" + } } else if (found_line) { print "wrongposition" } else { diff --git a/cdist/conf/type/__line/gencode-remote b/cdist/conf/type/__line/gencode-remote index 88cae68b..a89886da 100755 --- a/cdist/conf/type/__line/gencode-remote +++ b/cdist/conf/type/__line/gencode-remote @@ -38,7 +38,11 @@ if [ -z "$state_is" ]; then exit 1 fi -if [ "$state_should" = "$state_is" ]; then +if [ "$state_should" = "$state_is" ] || \ + { [ "$state_should" = "present" ] && [ "$state_is" = "matching" ] ;} || \ + { [ "$state_should" = "replace" ] && [ "$state_is" = "present" ] ;} ; then + # If state matches already, or 'present' is used and regex matches + # or 'replace' is used and the exact line is present, then there is # nothing to do exit 0 fi @@ -61,8 +65,8 @@ fi add=0 remove=0 case "$state_should" in - present) - if [ "$state_is" = "wrongposition" ]; then + present|replace) + if [ "$state_is" = "wrongposition" ] || [ "$state_is" = "matching" ]; then echo updated >> "$__messages_out" remove=1 else diff --git a/cdist/conf/type/__line/man.rst b/cdist/conf/type/__line/man.rst index f76cab64..70490f68 100644 --- a/cdist/conf/type/__line/man.rst +++ b/cdist/conf/type/__line/man.rst @@ -31,7 +31,7 @@ file line Specifies the line which should be absent or present. - Must be present, if state is 'present'. + Must be present, if state is 'present' or 'replace'. Ignored if regex is given and state is 'absent'. regex @@ -41,10 +41,13 @@ regex If state is 'absent', ensure all lines matching the regular expression are absent. + If state is 'replace', ensure all lines matching the regular expression + are exactly 'line'. + The regular expression is interpreted by awk's match function. state - 'present' or 'absent', defaults to 'present' + 'present', 'absent' or 'replace', defaults to 'present'. onchange The code to run if line is added, removed or updated. @@ -99,6 +102,12 @@ EXAMPLES --line '-session required pam_exec.so debug log=/tmp/classify.log /usr/local/libexec/classify' \ --after '^session[[:space:]]+include[[:space:]]+password-auth-ac$' + # Uncomment as needed and set a value in a configuration file. + __line /etc/example.conf \ + --line 'SomeSetting SomeValue' \ + --regex '^(#[[:space:]]*)?SomeSetting[[:space:]]' \ + --state replace + SEE ALSO -------- diff --git a/cdist/conf/type/__link/man.rst b/cdist/conf/type/__link/man.rst index fe0ce425..2e81aea9 100644 --- a/cdist/conf/type/__link/man.rst +++ b/cdist/conf/type/__link/man.rst @@ -18,7 +18,7 @@ source Specifies the link source. type - Specifies the link type: Either hard or symoblic. + Specifies the link type: Either hard or symbolic. OPTIONAL PARAMETERS diff --git a/cdist/conf/type/__locale/deprecated b/cdist/conf/type/__locale/deprecated new file mode 100644 index 00000000..5a06b28e --- /dev/null +++ b/cdist/conf/type/__locale/deprecated @@ -0,0 +1 @@ +This type is deprecated. Please use __localedef instead. diff --git a/cdist/conf/type/__acl/explorer/checks b/cdist/conf/type/__locale/explorer/state similarity index 54% rename from cdist/conf/type/__acl/explorer/checks rename to cdist/conf/type/__locale/explorer/state index 70bb0412..4494fcbc 100755 --- a/cdist/conf/type/__acl/explorer/checks +++ b/cdist/conf/type/__locale/explorer/state @@ -1,6 +1,7 @@ #!/bin/sh -e +# __locale/explorer/state # -# 2019 Ander Punnar (ander-at-kvlt-dot-ee) +# 2020 Matthias Stecher (matthiasstecher at gmx.de) # # This file is part of cdist. # @@ -17,23 +18,19 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # +# +# Check if the locale is already installed on the system. +# Outputs 'present' or 'absent' depending if the locale exists. +# -# TODO check if filesystem has ACL turned on etc -if [ -f "$__object/parameter/acl" ] -then - grep -E '^(default:)?(user|group):' "$__object/parameter/acl" \ - | while read -r acl - do - param="$( echo "$acl" | awk -F: '{print $(NF-2)}' )" - check="$( echo "$acl" | awk -F: '{print $(NF-1)}' )" +# Get user-defined locale +# locale name is echoed differently than the user propably set it (for UTF-8) +locale="$(echo "$__object_id" | sed 's/UTF-8/utf8/')" - [ "$param" = 'user' ] && db=passwd || db="$param" - - if ! getent "$db" "$check" > /dev/null - then - echo "missing $param '$check'" >&2 - exit 1 - fi - done +# Check if the given locale exists on the system +if localedef --list-archive | grep -qFx "$locale"; then + echo present +else + echo absent fi diff --git a/cdist/conf/type/__locale/gencode-remote b/cdist/conf/type/__locale/gencode-remote index 1feb9884..4639cef8 100755 --- a/cdist/conf/type/__locale/gencode-remote +++ b/cdist/conf/type/__locale/gencode-remote @@ -23,6 +23,15 @@ locale="$__object_id" +state_is=$(cat "$__object/explorer/state") +state_should=$(cat "$__object/parameter/state") + +# short circuit if there is nothing to do +if [ "$state_is" = "$state_should" ]; then + exit 0 +fi + + # Hardcoded, create a pull request with # branching on $os in case it is at another location alias=/usr/share/locale/locale.alias @@ -35,8 +44,6 @@ charmap=$(echo "$locale" | cut -d . -f 2) # W-T-F! locale_remove=$(echo "$locale" | sed 's/UTF-8/utf8/') -state=$(cat "$__object/parameter/state") - os=$(cat "$__global/explorer/os") # Nothing to be done on alpine @@ -46,7 +53,7 @@ case "$os" in ;; esac -case "$state" in +case "$state_should" in present) echo localedef -A "$alias" -f "$charmap" -i "$input" "$locale" ;; @@ -54,7 +61,7 @@ case "$state" in echo localedef --delete-from-archive "$locale_remove" ;; *) - echo "Unsupported state: $state" >&2 + echo "Unsupported state: $state_should" >&2 exit 1 ;; esac diff --git a/cdist/conf/type/__locale_system/manifest b/cdist/conf/type/__locale_system/manifest index 80f7401b..4b996ebc 100755 --- a/cdist/conf/type/__locale_system/manifest +++ b/cdist/conf/type/__locale_system/manifest @@ -3,6 +3,7 @@ # 2012-2016 Steven Armstrong (steven-cdist at armstrong.cc) # 2016 Carlos Ortigoza (carlos.ortigoza at ungleich.ch) # 2016 Nico Schottelius (nico.schottelius at ungleich.ch) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -23,17 +24,171 @@ # Configure system-wide locale by modifying i18n file. # +version_ge() { + awk -F '[^0-9.]' -v target="${1:?}" ' + function max(x, y) { return x > y ? x : y } + BEGIN { + getline + nx = split($1, x, ".") + ny = split(target, y, ".") + for (i = 1; i <= max(nx, ny); ++i) { + diff = int(x[i]) - int(y[i]) + if (diff == 0) continue + exit (diff < 0) + } + }' +} + + +key=$__object_id +onchange_cmd= # none, by default +quote_value=false + +catval() { + # shellcheck disable=SC2059 + printf "$($quote_value && echo '"%s"' || echo '%s')" "$(cat "$1")" +} + +state_should=$(cat "${__object}/parameter/state") + os=$(cat "$__global/explorer/os") -case "$os" in - debian|ubuntu) +case $os +in + debian) + if version_ge 4 <"${__global}/explorer/os_version" + then + # Debian 4 (etch) and later + locale_conf="/etc/default/locale" + else + locale_conf="/etc/environment" + fi + ;; + devuan) locale_conf="/etc/default/locale" ;; + ubuntu) + if version_ge 6.10 <"${__global}/explorer/os_version" + then + # Ubuntu 6.10 (edgy) and later + locale_conf="/etc/default/locale" + else + locale_conf="/etc/environment" + fi + ;; archlinux) locale_conf="/etc/locale.conf" ;; - redhat|centos) - locale_conf="/etc/sysconfig/i18n" + centos|redhat|scientific) + # shellcheck source=/dev/null + version_id=$(. "${__global}/explorer/os_release" && echo "${VERSION_ID:-0}") + if echo "${version_id}" | version_ge 7 + then + locale_conf="/etc/locale.conf" + else + locale_conf="/etc/sysconfig/i18n" + fi + ;; + fedora) + # shellcheck source=/dev/null + version_id=$(. "${__global}/explorer/os_release" && echo "${VERSION_ID:-0}") + if echo "${version_id}" | version_ge 18 + then + locale_conf="/etc/locale.conf" + quote_value=false + else + locale_conf="/etc/sysconfig/i18n" + fi + ;; + gentoo) + case $(cat "${__global}/explorer/init") + in + (*openrc*) + locale_conf="/etc/env.d/02locale" + onchange_cmd="env-update --no-ldconfig" + quote_value=true + ;; + (systemd) + locale_conf="/etc/locale.conf" + ;; + esac + ;; + freebsd|netbsd) + # NetBSD doesn't have a separate configuration file to set locales. + # In FreeBSD locales could be configured via /etc/login.conf but parsing + # that would be annoying, so the shell login file will have to do. + # "Non-POSIX" shells like csh will not be updated here. + + locale_conf="/etc/profile" + quote_value=true + value="$(catval "${__object}/parameter/value"); export ${key}" + ;; + solaris) + locale_conf="/etc/default/init" + locale_conf_group="sys" + + if version_ge 5.11 <"${__global}/explorer/os_version" + then + # mode on Oracle Solaris 11 is actually 0444, + # but the write bit makes sense, IMO + locale_conf_mode=0644 + + # Oracle Solaris 11.2 and later uses SMF to store environment info. + # This is a hack, but I didn't feel like modifying the whole type + # just for some Oracle nonsense. + # 11.3 apparently added nlsadm(1m), but it is missing from 11.2. + # Illumos continues to use /etc/default/init + # NOTE: Remember not to use "cool" POSIX features like -q or -e with + # Solaris grep. + release_regex='Oracle Solaris 11.[2-9][0-9]*' + case $state_should + in + (present) + svccfg_cmd="svccfg -s svc:/system/environment:init setprop environment/${key} = astring: '$(cat "${__object}/parameter/value")'" + ;; + (absent) + svccfg_cmd="svccfg -s svc:/system/environment:init delprop environment/${key}" + ;; + esac + refresh_cmd='svcadm refresh svc:/system/environment' + onchange_cmd="grep '${release_regex}' /etc/release >&- || exit 0; ${svccfg_cmd:-:} && ${refresh_cmd}" + else + locale_conf_mode=0555 + fi + ;; + slackware) + # NOTE: lang.csh (csh config) is ignored here. + locale_conf="/etc/profile.d/lang.sh" + locale_conf_mode=0755 + key="export ${__object_id}" + ;; + suse) + if test -s "${__global}/explorer/os_release" + then + # shellcheck source=/dev/null + os_version=$(. "${__global}/explorer/os_release" && echo "${VERSION}") + else + os_version=$(sed -n 's/^VERSION\ *=\ *//p' "${__global}/explorer/os_version") + fi + os_major=$(expr "${os_version}" : '\([0-9]\{1,\}\)') + + # https://documentation.suse.com/sles/15-SP2/html/SLES-all/cha-suse.html#sec-suse-l10n + if expr "${os_major}" '>=' 15 \& "${os_major}" != 42 + then + # It seems that starting with SuSE 15 the systemd /etc/locale.conf + # is the preferred way to set locales, although + # /etc/sysconfig/language is still available. + # Older documentation doesn't mention /etc/locale.conf, even though + # is it created when localectl is used. + locale_conf="/etc/locale.conf" + else + locale_conf="/etc/sysconfig/language" + quote_value=true + key="RC_${__object_id}" + fi + ;; + voidlinux) + locale_conf="/etc/locale.conf" ;; *) echo "Your operating system ($os) is currently not supported by this type (${__type##*/})." >&2 @@ -42,14 +197,16 @@ case "$os" in ;; esac -__file "$locale_conf" \ - --owner root --group root --mode 644 \ - --state exists +__file "${locale_conf}" --state exists \ + --owner "${locale_conf_owner:-0}" \ + --group "${locale_conf_group:-0}" \ + --mode "${locale_conf_mode:-0644}" -require="__file/$locale_conf" \ - __key_value "$locale_conf:$__object_id" \ - --file "$locale_conf" \ - --key "$__object_id" \ - --delimiter = \ - --state "$(cat "$__object/parameter/state")" \ - --value "$(cat "$__object/parameter/value")" +require="__file/${locale_conf}" \ +__key_value "${locale_conf}:${key#export }" \ + --file "${locale_conf}" \ + --key "${key}" \ + --delimiter '=' --exact_delimiter \ + --state "${state_should}" \ + --value "${value:-$(catval "${__object}/parameter/value")}" \ + --onchange "${onchange_cmd}" diff --git a/cdist/conf/type/__localedef/explorer/state b/cdist/conf/type/__localedef/explorer/state new file mode 100755 index 00000000..3ba57661 --- /dev/null +++ b/cdist/conf/type/__localedef/explorer/state @@ -0,0 +1,100 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# This explorer determines if the locale is defined on the target system. +# Will print nothing on error. +# +# Possible output: +# present: +# the main locale (and possibly aliases) is present +# absent: +# neither the main locale nor any aliases are present +# alias-present: +# the main locale is absent, but at least one of its aliases is present +# + +# Hardcoded, create a pull request in case it is at another location for +# some other distro. (cf. gencode-remote) +aliasfile='/usr/share/locale/locale.alias' + +command -v locale >/dev/null 2>&1 || exit 0 + +locales=$(locale -a) + +parse_locale() { + # This function will split locales into their parts. Locale strings are + # usually of the form: [language[_territory][.codeset][@modifier]] + # For simplicity, language and territory are not separated by this function. + # Old Linux systems were also using "english" or "german" as locale strings. + # Usage: parse_locale locale_str lang_var codeset_var modifier_var + eval "${2:?}"="$(expr "$1" : '\([^.@]*\)')" + eval "${3:?}"="$(expr "$1" : '[^.]*\.\([^@]*\)')" + eval "${4:?}"="$(expr "$1" : '.*@\(.*\)$')" +} + +format_locale() { + # Usage: format_locale language codeset modifier + printf '%s' "$1" + test -z "$2" || printf '.%s' "$2" + test -z "$3" || printf '@%s' "$3" + printf '\n' +} + +gnu_normalize_codeset() { + # reimplementation of glibc/locale/programs/localedef.c normalize_codeset() + echo "$*" | tr '[:upper:]' '[:lower:]' | tr -cd '[:alnum:]' +} + +locale_available() ( + echo "${locales}" | grep -qxF "$1" || { + # glibc uses "normalized" locale names in archives. + # If a locale is stored in an archive, the normalized name will be + # printed by locale, so that needs to be checked, too. + localename=$( + parse_locale "$1" _lang _codeset _modifier \ + && format_locale "${_lang:?}" "$(gnu_normalize_codeset "${_codeset?}")" \ + "${_modifier?}") + echo "${locales}" | grep -qxF "${localename}" + } +) + +if locale_available "${__object_id:?}" +then + echo present +else + # NOTE: locale.alias can be symlinked. + if test -e "${aliasfile}" + then + # Check if one of the aliases of the locale is defined + baselocale=$( + parse_locale "${__object_id:?}" _lang _codeset _modifiers \ + && format_locale "${_lang}" "${_codeset}") + while read -r _alias _localename + do + if test "${_localename}" = "${baselocale}" \ + && echo "${locales}" | grep -qxF "${_alias}" + then + echo alias-present + exit 0 + fi + done <"${aliasfile}" + fi + + echo absent +fi diff --git a/cdist/conf/type/__localedef/files/lib/glibc.sh b/cdist/conf/type/__localedef/files/lib/glibc.sh new file mode 100644 index 00000000..6ace80d4 --- /dev/null +++ b/cdist/conf/type/__localedef/files/lib/glibc.sh @@ -0,0 +1,5 @@ +# -*- mode: sh; indent-tabs-mode: t -*- + +gnu_normalize_codeset() { + echo "$*" | tr -cd '[:alnum:]' | tr '[:upper:]' '[:lower:]' +} diff --git a/cdist/conf/type/__localedef/files/lib/locale.sh b/cdist/conf/type/__localedef/files/lib/locale.sh new file mode 100644 index 00000000..b5e61374 --- /dev/null +++ b/cdist/conf/type/__localedef/files/lib/locale.sh @@ -0,0 +1,20 @@ +# -*- mode: sh; indent-tabs-mode:t -*- + +parse_locale() { + # This function will split locales into their parts. Locale strings are + # usually of the form: [language[_territory][.codeset][@modifier]] + # For simplicity, language and territory are not separated by this function. + # Old Linux systems were also using "english" or "german" as locale strings. + # Usage: parse_locale locale_str lang_var codeset_var modifier_var + eval "${2:?}"="$(expr "$1" : '\([^.@]*\)')" + eval "${3:?}"="$(expr "$1" : '[^.]*\.\([^@]*\)')" + eval "${4:?}"="$(expr "$1" : '.*@\(.*\)$')" +} + +format_locale() { + # Usage: format_locale language codeset modifier + printf '%s' "$1" + test -z "$2" || printf '.%s' "$2" + test -z "$3" || printf '@%s' "$3" + printf '\n' +} diff --git a/cdist/conf/type/__localedef/gencode-remote b/cdist/conf/type/__localedef/gencode-remote new file mode 100755 index 00000000..4538151f --- /dev/null +++ b/cdist/conf/type/__localedef/gencode-remote @@ -0,0 +1,136 @@ +#!/bin/sh -e +# +# 2013-2019 Nico Schottelius (nico-cdist at schottelius.org) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# Manage system locales using localedef(1). +# + +# shellcheck source=cdist/conf/type/__localedef/files/lib/locale.sh +. "${__type:?}/files/lib/locale.sh" +# shellcheck source=cdist/conf/type/__localedef/files/lib/glibc.sh +. "${__type:?}/files/lib/glibc.sh" + +state_is=$(cat "${__object:?}/explorer/state") +state_should=$(cat "${__object:?}/parameter/state") + +test "${state_should}" = 'present' -o "${state_should}" = 'absent' || { + printf 'Invalid state: %s\n' "${state_should}" >&2 + exit 1 +} + +# NOTE: If state explorer fails (e.g. locale(1) missing), the following check +# will always fail and let definition/removal run. +if test "${state_is}" = "${state_should}" +then + exit 0 +fi + +locale=${__object_id:?} +os=$(cat "${__global:?}/explorer/os") + +if expr "${locale}" : '.*/' >/dev/null +then + printf 'Paths as locales are not supported.\n' >&2 + printf '__object_id is: %s\n' "${locale}" >&2 + exit 1 +fi + +: "${lang=}" "${codeset=}" "${modifier=}" # declare variables for shellcheck +parse_locale "${locale}" lang codeset modifier + + +case ${os} +in + (alpine|openwrt) + printf '%s does not support locales.\n' "${os}" >&2 + exit 1 + ;; + (archlinux|debian|devuan|ubuntu|suse|centos|fedora|redhat|scientific) + # FIXME: The code below only works for glibc-based installations. + + # NOTE: Hardcoded, create a pull request in case it is at another + # location for some opther distro. + # NOTE: locale.alias can be symlinked (e.g. Debian) + aliasfile='/usr/share/locale/locale.alias' + + case ${state_should} + in + (present) + input=$(format_locale "${lang}" '' "${modifier}") + cat <<-EOF + set -- + if test -e '${aliasfile}' + then + set -- -A '${aliasfile}' + fi + + localedef -i '${input}' -f '${codeset}' "\$@" '${locale}' + EOF + ;; + (absent) + main_localename=$(format_locale "${lang}" "$(gnu_normalize_codeset "${codeset}")" "${modifier}") + + cat <<-EOF + while read -r _alias _localename + do + if test "\${_localename}" = '$(format_locale "${lang}" "${codeset}")' + then + localedef --delete-from-archive "\${_alias}" + fi + done <'${aliasfile}' + EOF + + if test "${state_is}" = present + then + printf "localedef --delete-from-archive '%s'\n" "${main_localename}" + fi + ;; + esac + ;; + (freebsd) + case ${state_should} + in + (present) + if expr "$(grep -oe '^[0-9]*' "${__global:?}/explorer/os_version")" '>=' 11 >/dev/null + then + # localedef(1) is available with FreeBSD >= 11 + printf "localedef -i '%s' -f '%s' '%s'\n" "${input}" "${codeset}" "${locale}" + else + printf 'localedef(1) was added to FreeBSD starting with version 11.\n' >&2 + printf 'Please upgrade your FreeBSD installation to use %s.\n' "${__type##*/}" >&2 + exit 1 + fi + ;; + (absent) + printf "rm -R '/usr/share/locale/%s'\n" "${locale}" + ;; + esac + ;; + (netbsd|openbsd) + # NetBSD/OpenBSD are missing localedef(1). + # We also do not delete defined locales because they can't be recreated. + echo "${os} is lacking localedef(1). Locale management unavailable." >&2 + exit 1 + ;; + (*) + echo "Your operating system (${os}) is currently not supported by this type (${__type##*/})." >&2 + echo "Please contribute an implementation for it if you can." >&2 + exit 1 + ;; +esac diff --git a/cdist/conf/type/__localedef/man.rst b/cdist/conf/type/__localedef/man.rst new file mode 100644 index 00000000..454ce9d1 --- /dev/null +++ b/cdist/conf/type/__localedef/man.rst @@ -0,0 +1,60 @@ +cdist-type__localedef(7) +======================== + +NAME +---- +cdist-type__localedef - Define and remove system locales + + +DESCRIPTION +----------- +This cdist type allows you to define locales on the system using +:strong:`localedef`\ (1) or remove them. +On systems that don't support definition of new locales, the type will raise an +error. + +**NB:** This type respects the glibc ``locale.alias`` file, +i.e. it defines alias locales or deletes aliases of a locale when it is removed. +It is not possible, however, to use alias names to define locales or only remove +certain aliases of a locale. + + +OPTIONAL PARAMETERS +------------------- +state + ``present`` or ``absent``. Defaults to ``present``. + + +EXAMPLES +-------- + +.. code-block:: sh + + # Add locale de_CH.UTF-8 + __localedef de_CH.UTF-8 + + # Same as above, but more explicit + __localedef de_CH.UTF-8 --state present + + # Remove colourful British English + __localedef en_GB.UTF-8 --state absent + + +SEE ALSO +-------- +:strong:`locale`\ (1), +:strong:`localedef`\ (1), +:strong:`cdist-type__locale_system`\ (7) + + +AUTHORS +------- +| Dennis Camera +| Nico Schottelius + + +COPYING +------- +Copyright \(C) 2013-2019 Nico Schottelius, 2020 Dennis Camera. Free use of this +software is granted under the terms of the GNU General Public License version 3 +or later (GPLv3+). diff --git a/cdist/conf/type/__localedef/manifest b/cdist/conf/type/__localedef/manifest new file mode 100755 index 00000000..3ab3ad8c --- /dev/null +++ b/cdist/conf/type/__localedef/manifest @@ -0,0 +1,30 @@ +#!/bin/sh -e +# +# 2013-2019 Nico Schottelius (nico-cdist at schottelius.org) +# 2015 David Hürlimann (david at ungleich.ch) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# Install required packages. +# + +case $(cat "${__global:?}/explorer/os") +in + (debian|devuan) + __package_apt locales --state present + ;; +esac diff --git a/cdist/conf/type/__localedef/parameter/default/state b/cdist/conf/type/__localedef/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__localedef/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__localedef/parameter/optional b/cdist/conf/type/__localedef/parameter/optional new file mode 100644 index 00000000..ff72b5c7 --- /dev/null +++ b/cdist/conf/type/__localedef/parameter/optional @@ -0,0 +1 @@ +state diff --git a/cdist/conf/type/__matrix_riot/files/config.json.sh b/cdist/conf/type/__matrix_riot/files/config.json.sh deleted file mode 100755 index d15d4862..00000000 --- a/cdist/conf/type/__matrix_riot/files/config.json.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# Upstream configuration guide/documentation: -# https://github.com/vector-im/riot-web/blob/develop/docs/config.md - -generate_embedded_pages () { - if [ $EMBED_HOMEPAGE ]; then - cat << EOF - "embeddedPages": { - "homeUrl": "home.html" - }, -EOF - fi -} - -cat << EOF -{ - "default_server_config": { - "m.homeserver": { - "base_url": "$DEFAULT_SERVER_URL", - "server_name": "$DEFAULT_SERVER_NAME" - }, - "m.identity_server": { - "base_url": "https://vector.im" - } - }, - "brand": "$BRAND", - "defaultCountryCode": "$DEFAULT_COUNTRY_CODE", - "integrations_ui_url": "https://scalar.vector.im/", - "integrations_rest_url": "https://scalar.vector.im/api", - "integrations_widgets_urls": [ - "https://scalar.vector.im/_matrix/integrations/v1", - "https://scalar.vector.im/api", - "https://scalar-staging.vector.im/_matrix/integrations/v1", - "https://scalar-staging.vector.im/api", - "https://scalar-staging.riot.im/scalar/api" - ], - "bug_report_endpoint_url": "https://riot.im/bugreports/submit", - "roomDirectory": { - "servers": [ - $ROOM_DIRECTORY_SERVERS - ] - }, - $(generate_embedded_pages) - "terms_and_conditions_links": [ - { - "url": "$PRIVACY_POLICY_URL", - "text": "Privacy Policy" - }, - { - "url": "$COOKIE_POLICY_URL", - "text": "Cookie Policy" - } - ] -} -EOF diff --git a/cdist/conf/type/__matrix_riot/gencode-remote b/cdist/conf/type/__matrix_riot/gencode-remote deleted file mode 100755 index b8935588..00000000 --- a/cdist/conf/type/__matrix_riot/gencode-remote +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh -e -# -# 2019 Timothée Floure (timothee.floure@ungleich.ch) -# -# This file is part of cdist. -# -# cdist is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# cdist is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with cdist. If not, see . -# - -VERSION=$(cat "$__object/parameter/version") -INSTALL_DIR=$(cat "$__object/parameter/install_dir") -OWNER=$(cat "$__object/parameter/owner") - -src="riot-v$VERSION" -archive="$src.tar.gz" -config='config.json' -homepage='home.html' -url="https://github.com/vector-im/riot-web/releases/download/v$VERSION/$archive" - -# tar and curl are installed by the __matrix-riot manifest. mktemp is usually -# provided by coreutils and assumed installed. -cat << EOF -set -e - -# Ensure that coreutils is installed. -if [ ! -x \$(which mktemp) ]; then - echo "mktemp is not available on the remote host." >&2 - exit 1 -fi - -# Create temporary working directory. -tmpdir=\$(mktemp -d) -cd \$tmpdir - -# Download and extract sources. -curl -L '$url' > $archive -tar xf $archive - -# Backup configuration deployed by __matrix_riot. -cp '$INSTALL_DIR/$config' '$config' - -# Backup homepage deployed by __matrix_riot -if [ -f '$INSTALL_DIR/$homepage' ]; then - cp '$INSTALL_DIR/$homepage' '$homepage' -fi - -# Deploy sources and restore configuration. -rm -r '$INSTALL_DIR' -mv '$src' '$INSTALL_DIR' -cp '$config' '$INSTALL_DIR/$config' - -# Restore homepage if available. -if [ -f '$homepage' ]; then - cp '$homepage' '$INSTALL_DIR/$homepage' -fi - -# Chown deployed files to requested owner. -chown -R '$OWNER' '$INSTALL_DIR' - -# Remove temporary working directory. -cd / -rm -r \$tmpdir -EOF diff --git a/cdist/conf/type/__matrix_riot/man.rst b/cdist/conf/type/__matrix_riot/man.rst deleted file mode 100644 index c8d80024..00000000 --- a/cdist/conf/type/__matrix_riot/man.rst +++ /dev/null @@ -1,72 +0,0 @@ -cdist-type__matrix_riot(7) -====================== - -NAME ----- -cdist-type__matrix_riot - Install and configure Riot, a web Matrix client. - - -DESCRIPTION ------------ -This type install and configure the Riot web client. - - -REQUIRED PARAMETERS -------------------- -install_dir - Root directory of Riot's static files. - -version - Release of Riot to install. - -OPTIONAL PARAMETERS -------------------- -default_server_name - Name of matrix homeserver to connect to, defaults to 'matrix.org'. - -default_server_url - URL of matrix homeserver to connect to, defaults to 'https://matrix-client.matrix.org'. - -owner - Owner of the deployed files, passed to `chown`. Defaults to 'root'. - -brand - Web UI branding, defaults to 'Riot'. - -default_country_code - ISO 3166 alpha2 country code to use when showing country selectors, such as - phone number inputs. Defaults to GB. - -privacy_policy_url - Defaults to 'https://riot.im/privacy'. - -cookie_policy_url - Defaults to 'https://matrix.org/docs/guides/riot_im_cookie_policy'. - -homepage - Path to custom Riot homepage, displayed once logged in. - -EXAMPLES --------- - -.. code-block:: sh - - __matrix_riot my-riot --install_dir /var/www/riot-web --version 1.5.6 - - -SEE ALSO --------- -- `cdist-type__matrix_synapse(7) `_ - - -AUTHORS -------- -Timothée Floure - - -COPYING -------- -Copyright \(C) 2019 Timothée Floure. You can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. diff --git a/cdist/conf/type/__matrix_riot/manifest b/cdist/conf/type/__matrix_riot/manifest deleted file mode 100755 index 703e8b6f..00000000 --- a/cdist/conf/type/__matrix_riot/manifest +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh -e -# -# 2019 Timothée Floure (timothee.floure@ungleich.ch) -# -# This file is part of cdist. -# -# cdist is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# cdist is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with cdist. If not, see . -# - -INSTALL_DIR=$(cat "$__object/parameter/install_dir") - -default_server_name=$(cat "$__object/parameter/default_server_name") -brand=$(cat "$__object/parameter/brand") -default_country_code=$(cat "$__object/parameter/default_country_code") -room_directory_servers=$(cat "$__object/parameter/room_directory_servers") -privacy_policy_url=$(cat "$__object/parameter/privacy_policy_url") -cookie_policy_url=$(cat "$__object/parameter/cookie_policy_url") - -export DEFAULT_SERVER_NAME=$default_server_name -export BRAND=$brand -export DEFAULT_COUNTRY_CODE=$default_country_code -export ROOM_DIRECTORY_SERVERS=$room_directory_servers -export PRIVACY_POLICY_URL=$privacy_policy_url -export COOKIE_POLICY_URL=$cookie_policy_url - -if [ -f "$__object/parameter/homepage" ]; then - export EMBED_HOMEPAGE=1 - homepage=$(cat "$__object/parameter/homepage") -fi - -# Owner of the uploaded files. -owner=$(cat "$__object/parameter/owner") - -# Ensure that curl and tar are installed, as they will be required by the -# gencode-remote script. -__package curl --state present -__package tar --state present - -# Generate and deploy configuration file. -mkdir -p "$__object/files" -"$__type/files/config.json.sh" > "$__object/files/config.json" - -# Install the config.json configuration file. The application's sources are -# downloaded and deployed by gencode-remote. -__directory "$INSTALL_DIR" \ - --owner "$owner" --mode 0755 --parents \ - --state present -require="__directory/$INSTALL_DIR" __file "$INSTALL_DIR/config.json" \ - --source "$__object/files/config.json" \ - --mode 0664 \ - --state present -if [ $EMBED_HOMEPAGE ]; then - require="__directory/$INSTALL_DIR" __file "$INSTALL_DIR/home.html" \ - --source "$homepage" \ - --mode 0664 \ - --state present -fi diff --git a/cdist/conf/type/__matrix_riot/parameter/default/brand b/cdist/conf/type/__matrix_riot/parameter/default/brand deleted file mode 100644 index e8095bb8..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/brand +++ /dev/null @@ -1 +0,0 @@ -Riot diff --git a/cdist/conf/type/__matrix_riot/parameter/default/cookie_policy_url b/cdist/conf/type/__matrix_riot/parameter/default/cookie_policy_url deleted file mode 100644 index 04e9c2b7..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/cookie_policy_url +++ /dev/null @@ -1 +0,0 @@ -https://matrix.org/docs/guides/riot_im_cookie_policy diff --git a/cdist/conf/type/__matrix_riot/parameter/default/default_country_code b/cdist/conf/type/__matrix_riot/parameter/default/default_country_code deleted file mode 100644 index 30ac4a3b..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/default_country_code +++ /dev/null @@ -1 +0,0 @@ -GB diff --git a/cdist/conf/type/__matrix_riot/parameter/default/default_server_name b/cdist/conf/type/__matrix_riot/parameter/default/default_server_name deleted file mode 100644 index 5528ffdd..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/default_server_name +++ /dev/null @@ -1 +0,0 @@ -matrix.org diff --git a/cdist/conf/type/__matrix_riot/parameter/default/default_server_url b/cdist/conf/type/__matrix_riot/parameter/default/default_server_url deleted file mode 100644 index 2cb92277..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/default_server_url +++ /dev/null @@ -1 +0,0 @@ -https://matrix-client.matrix.org diff --git a/cdist/conf/type/__matrix_riot/parameter/default/owner b/cdist/conf/type/__matrix_riot/parameter/default/owner deleted file mode 100644 index d8649da3..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/owner +++ /dev/null @@ -1 +0,0 @@ -root diff --git a/cdist/conf/type/__matrix_riot/parameter/default/privacy_policy_url b/cdist/conf/type/__matrix_riot/parameter/default/privacy_policy_url deleted file mode 100644 index 4cdd12c1..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/privacy_policy_url +++ /dev/null @@ -1 +0,0 @@ -https://riot.im/privacy diff --git a/cdist/conf/type/__matrix_riot/parameter/default/room_directory_servers b/cdist/conf/type/__matrix_riot/parameter/default/room_directory_servers deleted file mode 100644 index 4ea73ad5..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/default/room_directory_servers +++ /dev/null @@ -1 +0,0 @@ -"matrix.org" diff --git a/cdist/conf/type/__matrix_riot/parameter/optional b/cdist/conf/type/__matrix_riot/parameter/optional deleted file mode 100644 index c5e949fe..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/optional +++ /dev/null @@ -1,9 +0,0 @@ -default_server_url -default_server_name -brand -default_country_code -privacy_policy_url -cookie_policy_url -room_directory_servers -owner -homepage diff --git a/cdist/conf/type/__matrix_riot/parameter/required b/cdist/conf/type/__matrix_riot/parameter/required deleted file mode 100644 index a76477e9..00000000 --- a/cdist/conf/type/__matrix_riot/parameter/required +++ /dev/null @@ -1,2 +0,0 @@ -version -install_dir diff --git a/cdist/conf/type/__matrix_synapse/files/homeserver.yaml.sh b/cdist/conf/type/__matrix_synapse/files/homeserver.yaml.sh deleted file mode 100755 index 01f328d9..00000000 --- a/cdist/conf/type/__matrix_synapse/files/homeserver.yaml.sh +++ /dev/null @@ -1,1651 +0,0 @@ -#!/bin/sh - -# NOTE: this template has been generated using the -# matrix-synapse-1.5.1-1.fc31.noarch Fedora package for use with CDIST. - -generate_database () { - if [ "$DATABASE_ENGINE" = "sqlite3" ]; then - cat << EOF -database: - # The database engine name - name: "$DATABASE_ENGINE" - # Arguments to pass to the engine - args: - # Path to the database - database: "$DATABASE_NAME" -EOF - else -cat << EOF -database: - # The database engine name - name: "$DATABASE_ENGINE" - # Arguments to pass to the engine - args: - database: "$DATABASE_NAME" - host: "$DATABASE_HOST" - user: "$DATABASE_USER" - password: "$DATABASE_PASSWORD" -EOF - fi -} - -generate_password_providers () { - if [ "$ENABLE_LDAP_AUTH" = "true" ]; then - cat <