From ca353ed406bc46f09b168eb4be25edd2c9594cd7 Mon Sep 17 00:00:00 2001 From: John Van de Meulebrouck Brendgard Date: Fri, 17 Nov 2023 13:50:02 +0100 Subject: [PATCH 1/5] Set same permissions for /root/.ssh/authorized_keys in post-tasks.d/010fix-ssh-perms as is done by Puppet with sunet::ssh_keys. --- global/post-tasks.d/010fix-ssh-perms | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/global/post-tasks.d/010fix-ssh-perms b/global/post-tasks.d/010fix-ssh-perms index 87636d7..f32a6a4 100755 --- a/global/post-tasks.d/010fix-ssh-perms +++ b/global/post-tasks.d/010fix-ssh-perms @@ -17,7 +17,7 @@ if test -f /root/.ssh/authorized_keys; then if test `stat -t /root/.ssh/authorized_keys | cut -d\ -f5` != 0; then chown root.root /root/.ssh/authorized_keys fi - if test `stat --printf=%a /root/.ssh/authorized_keys` != 600; then - chmod 600 /root/.ssh/authorized_keys + if test `stat --printf=%a /root/.ssh/authorized_keys` != 440; then + chmod 440 /root/.ssh/authorized_keys fi fi From 75e566ab61fe9d485a70f3066084705c720315b2 Mon Sep 17 00:00:00 2001 From: John Van de Meulebrouck Brendgard Date: Fri, 17 Nov 2023 14:58:51 +0100 Subject: [PATCH 2/5] Make sure that /root in overlay is owned by root as well as that /root/.ssh and its content is only owned and readable by root. This is redundant if the previous permissions were properly applied and no other changes have been made by the user or something else, but is added for good measure as a layered defense. --- global/pre-tasks.d/015set-overlay-permissions | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/global/pre-tasks.d/015set-overlay-permissions b/global/pre-tasks.d/015set-overlay-permissions index 37f9844..205180b 100755 --- a/global/pre-tasks.d/015set-overlay-permissions +++ b/global/pre-tasks.d/015set-overlay-permissions @@ -14,10 +14,17 @@ if ! test -d "$MODEL_OVERLAY"; then exit 0 fi +args="" +if [ "x$COSMOS_VERBOSE" = "xy" ]; then + args="-v" +fi + if [ -d "$MODEL_OVERLAY/root" ]; then - args="" - if [ "x$COSMOS_VERBOSE" = "xy" ]; then - args="-v" - fi + chown ${args} root:root "$MODEL_OVERLAY"/root chmod ${args} 0700 "$MODEL_OVERLAY"/root fi + +if [ -d "$MODEL_OVERLAY/root/.ssh" ]; then + chown ${args} -R root:root "$MODEL_OVERLAY"/root/.ssh + chmod ${args} 0700 "$MODEL_OVERLAY"/root/.ssh +fi From 8d4ce2d1b7132dbe00486134e60e0e13f715b8d4 Mon Sep 17 00:00:00 2001 From: John Van de Meulebrouck Brendgard Date: Fri, 17 Nov 2023 15:03:47 +0100 Subject: [PATCH 3/5] Make sure that COSMOS_BASE is only readable by root since it's possible that the directory can contain files that after applying the overlay to / only should be read or writable by root. --- global/post-tasks.d/014set-cosmos-permissions | 24 +++++++++++++++++++ global/pre-tasks.d/014set-cosmos-permissions | 24 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100755 global/post-tasks.d/014set-cosmos-permissions create mode 100755 global/pre-tasks.d/014set-cosmos-permissions diff --git a/global/post-tasks.d/014set-cosmos-permissions b/global/post-tasks.d/014set-cosmos-permissions new file mode 100755 index 0000000..08992b5 --- /dev/null +++ b/global/post-tasks.d/014set-cosmos-permissions @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Set Cosmos directory permissions so that +# the files cannot be read by anyone but root, +# since it's possible that the directory +# can contain files that after applying the +# overlay to / only should be read or writable +# by root. + +set -e +self=$(basename "$0") + +if ! test -d "$COSMOS_BASE"; then + test -z "$COSMOS_VERBOSE" || echo "$self: COSMOS_BASE was not found. Aborting change of permissions." + exit 0 +fi + +args="" +if [ "x$COSMOS_VERBOSE" = "xy" ]; then + args="-v" +fi + +chown ${args} root:root "$COSMOS_BASE" +chmod ${args} 750 "$COSMOS_BASE" diff --git a/global/pre-tasks.d/014set-cosmos-permissions b/global/pre-tasks.d/014set-cosmos-permissions new file mode 100755 index 0000000..08992b5 --- /dev/null +++ b/global/pre-tasks.d/014set-cosmos-permissions @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Set Cosmos directory permissions so that +# the files cannot be read by anyone but root, +# since it's possible that the directory +# can contain files that after applying the +# overlay to / only should be read or writable +# by root. + +set -e +self=$(basename "$0") + +if ! test -d "$COSMOS_BASE"; then + test -z "$COSMOS_VERBOSE" || echo "$self: COSMOS_BASE was not found. Aborting change of permissions." + exit 0 +fi + +args="" +if [ "x$COSMOS_VERBOSE" = "xy" ]; then + args="-v" +fi + +chown ${args} root:root "$COSMOS_BASE" +chmod ${args} 750 "$COSMOS_BASE" From 01768129f0ce4a7551cb39e46e64c034fcd5606d Mon Sep 17 00:00:00 2001 From: Patrik Lundin Date: Wed, 3 Jul 2024 13:27:52 +0200 Subject: [PATCH 4/5] fleetlock: configurable lock/unlock timeout While we already support setting a healthcheck timeout it probably makes sense to be able to control how long we wait for a fleetlock_lock() or fleetlock_unlock() call. This becomes important if only running cosmos once a night or something like that. In that case we you probably want to give a physical machine more than than 1 minute to complete a reboot etc. This can now be controlled by setting fleetlock_lock_timeout and fleetlock_unlock_timeout in /etc/run-cosmos-fleetlock-conf. Keep in mind that while it can make sense to increase the time for taking a lock, releasing a lock should always be fast (either you have it and release it, or you dont have it and it is a no-op) so setting a long unlock timeout should probably never be done. Since we also potentially wait the unlock timeout at boot (if the fleetlock server is broken etc) that is another reason to keep it short. The default 1m is probably OK for most uses. --- global/overlay/usr/local/bin/run-cosmos | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/global/overlay/usr/local/bin/run-cosmos b/global/overlay/usr/local/bin/run-cosmos index 7274b62..268fd6a 100755 --- a/global/overlay/usr/local/bin/run-cosmos +++ b/global/overlay/usr/local/bin/run-cosmos @@ -67,14 +67,19 @@ fleetlock_lock() { # called. fleetlock_enable_unlock_service || return 1 local fleetlock_group="" + local optional_args=() # shellcheck source=/dev/null . $FLEETLOCK_CONFIG || return 1 if [ -z "$fleetlock_group" ]; then echo "Unable to set fleetlock_group" return 1 fi + if [ -n "$fleetlock_lock_timeout" ]; then + optional_args+=("--timeout") + optional_args+=("$fleetlock_lock_timeout") + fi echo "Getting fleetlock lock" - $FLEETLOCK_TOOL --lock-group "$fleetlock_group" --lock || return 1 + $FLEETLOCK_TOOL --lock-group "$fleetlock_group" --lock "${optional_args[@]}" || return 1 fi return 0 } @@ -82,15 +87,20 @@ fleetlock_lock() { fleetlock_unlock() { if [ ! -f $FLEETLOCK_DISABLE_FILE ] && [ -f $FLEETLOCK_CONFIG ] && [ -x $FLEETLOCK_TOOL ]; then local fleetlock_group="" + local optional_args=() # shellcheck source=/dev/null . $FLEETLOCK_CONFIG || return 1 if [ -z "$fleetlock_group" ]; then echo "Unable to set fleetlock_group" return 1 fi + if [ -n "$fleetlock_unlock_timeout" ]; then + optional_args+=("--timeout") + optional_args+=("$fleetlock_unlock_timeout") + fi machine_is_healthy || return 1 echo "Releasing fleetlock lock" - $FLEETLOCK_TOOL --lock-group "$fleetlock_group" --unlock || return 1 + $FLEETLOCK_TOOL --lock-group "$fleetlock_group" --unlock "${optional_args[@]}" || return 1 fi return 0 } From aa88795ee09e1fb0ffd1b0ffee948e1ad4f33dd9 Mon Sep 17 00:00:00 2001 From: Patrik Lundin Date: Wed, 3 Jul 2024 14:13:22 +0200 Subject: [PATCH 5/5] sunet-fleetlock: also handle ReadTimeout Turns out this was not caught by ConnectionError. --- global/overlay/usr/local/bin/sunet-fleetlock | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/global/overlay/usr/local/bin/sunet-fleetlock b/global/overlay/usr/local/bin/sunet-fleetlock index 6f0b557..64effec 100755 --- a/global/overlay/usr/local/bin/sunet-fleetlock +++ b/global/overlay/usr/local/bin/sunet-fleetlock @@ -97,7 +97,10 @@ def do_fleetlock_request( timeout=args.request_timeout, auth=("", config[args.lock_group]["password"]), ) - except requests.exceptions.ConnectionError as e: + except ( + requests.exceptions.ConnectionError, + requests.exceptions.ReadTimeout, + ) as e: print(f"POST request failed: {e}") time.sleep(retry_sleep_delay) continue