From bc2948a8a552e3bda3ab9ae8e8e199e831d81af2 Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Fri, 11 Dec 2020 19:37:53 +0100 Subject: [PATCH 1/7] ++scan stuff --- cdist/scan/scan.py | 15 +++++++++++++++ docs/dev/logs/2020-10-29.org | 10 +++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cdist/scan/scan.py b/cdist/scan/scan.py index fcbf1899..00858581 100644 --- a/cdist/scan/scan.py +++ b/cdist/scan/scan.py @@ -56,6 +56,8 @@ from scapy.all import * # Datetime overwrites scapy.all.datetime - needs to be imported AFTER import datetime +import cdist.config + log = logging.getLogger("scan") class Trigger(object): @@ -120,6 +122,19 @@ class Scanner(object): with open(fname, "w") as fd: fd.write(f"{now}\n") + def config(self): + """ + Configure a host + + - Assume we are only called if necessary + - However we need to ensure to not run in parallel + - Maybe keep dict storing per host processes + - Save the result + - Save the output -> probably aligned to config mode + + """ + + def start(self): self.process = Process(target=self.scan) self.process.start() diff --git a/docs/dev/logs/2020-10-29.org b/docs/dev/logs/2020-10-29.org index 4461be8c..03d6b3f4 100644 --- a/docs/dev/logs/2020-10-29.org +++ b/docs/dev/logs/2020-10-29.org @@ -54,4 +54,12 @@ VERBOSE: scan: Host fe80::f29f:c2ff:fe7c:275e is alive VERBOSE: scan: Host fe80::ba69:f4ff:fec5:8db7 is alive VERBOSE: scan: Host fe80::42b0:34ff:fe6f:f863 is alive VERBOSE: scan: Host fe80::21b:fcff:feee:f4bc is alive -... +** Better usage -> saving the env + sudo -E cdist scan -b -I wlan0 -vv +** TODO Implement actual configuration step + - Also serves as a nice PoC + - Might need to escape literal IPv6 addresses for scp +** TODO Define how to map link local address to something useful + - via reverse DNS? + - via link local in manifest? +** TODO define ignorehosts? From 766198912d558e4630b258bba62e78587b3f0efe Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Tue, 5 Jan 2021 15:50:21 +0100 Subject: [PATCH 2/7] [type/__sshd_config] Produce error if invalid config file is generated Previously, cdist would silently swallow the error (no invalid config file was generated). Reason: `set -e` does not exit if a command in a sub-command group fails, it merely returns with a non-zero exit status. e.g. the following snippet does not abort the script if sshd -t returns with a non-zero exit status: set -e cmp -s old new || { # check config file and update it sshd -t -f new \ && cat new >old } or compressed: set -e false || { false && true; } echo $? # prints 1 --- cdist/conf/type/__sshd_config/gencode-remote | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cdist/conf/type/__sshd_config/gencode-remote b/cdist/conf/type/__sshd_config/gencode-remote index 0b44dfa7..275db4aa 100755 --- a/cdist/conf/type/__sshd_config/gencode-remote +++ b/cdist/conf/type/__sshd_config/gencode-remote @@ -91,7 +91,8 @@ awk $(drop_awk_comments "${__type:?}/files/update_sshd_config.awk") \\ cmp -s $(quote "${sshd_config_file}") $(quote "${sshd_config_file}.tmp") || { sshd -t -f $(quote "${sshd_config_file}.tmp") \\ - && cat $(quote "${sshd_config_file}.tmp") >$(quote "${sshd_config_file}") + && cat $(quote "${sshd_config_file}.tmp") >$(quote "${sshd_config_file}") \\ + || exit # stop if sshd_config file check fails } rm -f $(quote "${sshd_config_file}.tmp") EOF From 8753b7eedf022a052ddc0b27fbc58ebf8fd638e1 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Tue, 5 Jan 2021 15:57:39 +0100 Subject: [PATCH 3/7] [type/__sshd_config] Make AuthenticationMethods and AuthorizedKeysFile singleton options They were incorrectly treated as non-singleton options before. cf. https://github.com/openssh/openssh-portable/blob/V_8_4/servconf.c#L2273 and https://github.com/openssh/openssh-portable/blob/V_8_4/servconf.c#L1899 resp. --- cdist/conf/type/__sshd_config/files/update_sshd_config.awk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdist/conf/type/__sshd_config/files/update_sshd_config.awk b/cdist/conf/type/__sshd_config/files/update_sshd_config.awk index d0bc2b4b..f7f30e87 100644 --- a/cdist/conf/type/__sshd_config/files/update_sshd_config.awk +++ b/cdist/conf/type/__sshd_config/files/update_sshd_config.awk @@ -89,7 +89,7 @@ function strdelim(s) { return strdelim_internal(s, 1) } function strdelimw(s) { return strdelim_internal(s, 0) } function singleton_option(opt) { - return tolower(opt) !~ /^(acceptenv|allowgroups|allowusers|authenticationmethods|authorizedkeysfile|denygroups|denyusers|hostcertificate|hostkey|listenaddress|logverbose|permitlisten|permitopen|port|setenv|subsystem)$/ + return tolower(opt) !~ /^(acceptenv|allowgroups|allowusers|denygroups|denyusers|hostcertificate|hostkey|listenaddress|logverbose|permitlisten|permitopen|port|setenv|subsystem)$/ } function print_update() { From bd8ab8f26fdc242f2eb77e58049d640f96d51a69 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Tue, 5 Jan 2021 17:00:55 +0100 Subject: [PATCH 4/7] [type/__sshd_config] Document "bug" in state explorer --- cdist/conf/type/__sshd_config/man.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cdist/conf/type/__sshd_config/man.rst b/cdist/conf/type/__sshd_config/man.rst index 8b0069ac..c8e6b8ad 100644 --- a/cdist/conf/type/__sshd_config/man.rst +++ b/cdist/conf/type/__sshd_config/man.rst @@ -79,6 +79,10 @@ BUGS - ``Include`` directives are ignored. - Config options are not added/removed to/from the config file if their value is the default value. +- | The explorer will incorrectly report ``absent`` if OpenSSH internally + transforms one value to another (e.g. ``permitrootlogin prohibit-password`` + is transformed to ``permitrootlogin without-password``). + | Workaround: Use the value that OpenSSH uses internally. AUTHORS From 6e9b13d94962e1bfb365efa849ebefc32854364b Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Mon, 18 Jan 2021 06:22:32 +0100 Subject: [PATCH 5/7] ++changelog --- docs/changelog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog b/docs/changelog index 35953a88..b2b35616 100644 --- a/docs/changelog +++ b/docs/changelog @@ -1,6 +1,10 @@ Changelog --------- +next: + * Core: preos: Fix passing cdist debug parameter (Darko Poljak) + * Type __sshd_config: Produce error if invalid config is generated, fix processing of AuthenticationMethods and AuthorizedKeysFile, document explorer bug (Dennis Camera) + 6.9.4: 2020-12-21 * Type __package_pkgng_freebsd: Fix bootstrapping pkg (Dennis Camera) * Core: Deal with deprecated imp in unit tests (Evil Ham) From 92a50da4873ff4bfa85dde3b85e272704cda02c7 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Mon, 18 Jan 2021 06:28:09 +0100 Subject: [PATCH 6/7] Fix pycodestyle issues --- cdist/scan/scan.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cdist/scan/scan.py b/cdist/scan/scan.py index 5ca8fae2..b1d0e9e1 100644 --- a/cdist/scan/scan.py +++ b/cdist/scan/scan.py @@ -139,7 +139,6 @@ class Scanner(object): """ - def start(self): self.process = Process(target=self.scan) self.process.start() From 92432c5d9a625a07a3fa3230788662099cf7e1cb Mon Sep 17 00:00:00 2001 From: Alexander Sieg Date: Wed, 20 Jan 2021 20:18:38 +0100 Subject: [PATCH 7/7] cconn a transparent connection wrapper cconn used the inventory system to dynamically connect to FreeBSD jail via the host system and/or using sudo to get root access This is more of a prove of concept then a finish idea. --- other/examples/remote/cconn/cconn | 199 ++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100755 other/examples/remote/cconn/cconn diff --git a/other/examples/remote/cconn/cconn b/other/examples/remote/cconn/cconn new file mode 100755 index 00000000..bc712a0d --- /dev/null +++ b/other/examples/remote/cconn/cconn @@ -0,0 +1,199 @@ +#!/bin/sh -ex + +# Copyright (c) 2021 Alexander Sieg + +# cconn is a transparent wrapper that allows seamless usage of sudo/rsync and +# FreeBSD jails, this makes it possible to configure a FreeBSD by just using +# the host system sshd. +# Configuration is done by throw the cdist invertory system. +# +# +# Installation: +# +# Simply set this script as remote_exec and remote_copy implementation in your +# cdist.cfg. You MUST always pass either copy or exec as the first parameter +# to this script +# +# remote_exec = path/to/cconn exec +# remote_copy = path/to/cconn copy +# +# As cconn uses the cdist inventory system for host specific configuration, it +# ether need to be executed from the directory the contains the inventory +# directory or be setting the INVENTORY environment variable to path were the +# inventory entries are kept. +# +# Usage: +# +# To setup a host to use some form of connection "bending" (e.g. sudo) you need +# to add a single __cconn_options tag to the host inventory file. Options are always a +# key value pair separated by a '='. All options are passed in a single tag and +# a separated by a space. +# +# __cconn_options options: +# +# NOTE: jail_host and iocage_jail can not be used at the same time and will +# lead to a error +# +# jail_host: +# hostname on which the FreeBSD jail resides on. +# +# iocage_host: +# Same as jail_host, but for jails managed by iocage(8) +# +# jail_name: +# By default cconn will use the __target_host as the FreeBSD jail name, set +# this option to override this name +# +# sudo_user: +# Username used to connect to the __target_host, all commands are then +# prefixed with sudo and copy operations are done with rsync +# +# For this work you need to be able to execute all command without password entry. +# sudoers(5) +# %wheel ALL=(ALL) NOPASSWD: ALL +# +#Examples: +# +# inventory/jail.example.com: +# some_other_tag +# __cconn_options jail_host=example.com sudo_user=ada +# + + +#TODO: add sudo_pass and sudo_passfile option to support use without NOPASSWD +#TODO: support SSH connection multiplexing. This requieres a patch to cdist, as +# we need path to the tmp dir. + +log() { + # Uncomment this for debugging + echo "$@" | logger -t "cdist-cconn-$COMMAND" + : +} + +COMMAND="$1"; shift + +if [ -z "$INVENTORY" ]; then + INVENTORY="inventory" +fi + +# shellcheck disable=SC2154 +options="$(sed -n 's/^__cconn_options\(.*\)$/\1/p' "$INVENTORY/$__target_host" | cut -d' ' -f2-)" +tmpcmd=$* +for option in $options; do + # shellcheck disable=SC2046 + set -- $(echo "$option" | tr '=' ' ') + key="$1" + value="$2" + case "$1" in + "jail_host") + JAIL_HOST="$value" + ;; + "iocage_host") + IOCAGE_HOST="$value" + ;; + "jail_name") + JAIL_NAME="$value" + ;; + "sudo_user") + SUDO_USER="$value" + ;; + *) + log "unknown option $key=$value found" + ;; + esac +done +# shellcheck disable=SC2086 +set -- $tmpcmd + +if [ -n "$IOCAGE_HOST" ] && [ -n "$JAIL_HOST" ]; then + echo "WARING: jail_host and iocage_host can't be used at the same time" + log "WARING: jail_host and iocage_host can't be used at the same time" + exit 1 +fi + +TARGET_HOST="$__target_host" +SSH_USER="root" + +if [ -n "$IOCAGE_HOST" ]; then + JAIL_HOST="$IOCAGE_HOST" + + if [ -z "$JAIL_NAME" ]; then + JAIL_NAME="ioc-$(echo "$__target_host" | tr '.' '_')" + else + JAIL_NAME="ioc-$(echo "$JAIL_NAME" | tr '.' '_')" + fi +else + if [ -z "$JAIL_NAME" ]; then + JAIL_NAME="$TARGET_HOST" + fi +fi + +if [ -n "$JAIL_HOST" ]; then + log "INSIDE_JAIL: TRUE" + TARGET_HOST="$JAIL_HOST" + WRAPPER="jexec $JAIL_NAME" +fi + +if [ -n "$SUDO_USER" ]; then + log "SUDO_USER: $SUDO_USER" + WRAPPER="sudo -- $WRAPPER" + SSH_USER="$SUDO_USER" +fi + +log "TARGET_HOST: $TARGET_HOST" +log "@:" "$@" +if [ -n "$JAIL_HOST" ]; then + log "IOCAGE_HOST: $IOCAGE_HOST" + log "JAIL_HOST: $JAIL_HOST" + log "JAIL_NAME: $JAIL_NAME" + log "WRAPPER: $WRAPPER" +fi + +case "$COMMAND" in + "exec") + shift; # remove the jail host name from $@ + ssh -o User="$SSH_USER" -q "$TARGET_HOST" "$WRAPPER $*" + ;; + "copy") + if [ -n "$JAIL_HOST" ]; then + # jls(8) dosen't need root to print this information + jail_root=$(ssh -q "$TARGET_HOST" -- jls -j "$JAIL_NAME" path) + log "JAIL_ROOT: $jail_root" + fi + + if [ -n "$JAIL_HOST" ]; then + set -- "$(echo "$@" | sed "s|$__target_host:|$JAIL_HOST:$jail_root|g")" + fi + + if [ -n "$SUDO_USER" ]; then + # For rsync to do the right thing, the source has to end with "/" if it is + # a directory. The below preprocessor loop takes care of that. + + # second last argument is the source + source_index=$(($#-1)) + index=0 + for arg in "$@"; do + if [ $index -eq 0 ]; then + # reset $@ + set -- + fi + index=$((index+=1)) + if [ $index -eq $source_index ] && [ -d "$arg" ]; then + arg="${arg%/}/" + fi + set -- "$@" "$arg" + done + + rsync --copy-links -e "ssh -o User=$SSH_USER" --rsync-path='sudo rsync' "$@" + else + #shellcheck disable=SC2068 + scp -o "User=$SSH_USER" -q $@ + fi + ;; + *) + echo "unkown command - $COMMAND" + exit 1 + ;; +esac + +log "----"