From 519d38c01e078f09ebbf2c65359af44088f44d17 Mon Sep 17 00:00:00 2001
From: Lukas Werner <lks.werner@fau.de>
Date: Tue, 3 Aug 2021 08:55:25 +0200
Subject: [PATCH] Added cleanup script and authentication everywhere

---
 runner_config/config.toml      |  1 +
 runner_scripts/root/cleanup.sh | 52 ++++++++++++++++++++++++++++++++++
 runner_scripts/root/config.sh  | 39 +++++++++++++++++++++++--
 runner_scripts/root/run.sh     | 10 +++++--
 4 files changed, 97 insertions(+), 5 deletions(-)
 create mode 100755 runner_scripts/root/cleanup.sh
 mode change 100644 => 100755 runner_scripts/root/run.sh

diff --git a/runner_config/config.toml b/runner_config/config.toml
index f063615..0fb6e1b 100644
--- a/runner_config/config.toml
+++ b/runner_config/config.toml
@@ -12,3 +12,4 @@ check_interval = 0
   [runners.custom]
     config_exec = "path/to/config.sh"
     run_exec = "path/to/run.sh"
+    cleanup_exec = "path/to/cleanup.sh"
diff --git a/runner_scripts/root/cleanup.sh b/runner_scripts/root/cleanup.sh
new file mode 100755
index 0000000..32d568a
--- /dev/null
+++ b/runner_scripts/root/cleanup.sh
@@ -0,0 +1,52 @@
+#!/bin/bash -l
+set -euf -o pipefail
+shopt -s inherit_errexit
+    
+hash awk
+hash chown
+hash diff
+hash getent
+hash id
+hash runuser
+hash sed
+hash ssh-keygen
+
+function error {
+    : "${RV:=${2:-$BUILD_FAILURE_EXIT_CODE}}"
+    echo "$1" >&2
+    return "$RV"
+}
+
+## User authentication
+
+: "${CUSTOM_ENV_AUTH_USER:?"AUTH_USER CI/CD variable has not been set."}"
+: "${CUSTOM_ENV_AUTH_KEY:?"AUTH_KEY CI/CD variable has not been set."}"
+
+AUTH_USER=$CUSTOM_ENV_AUTH_USER
+
+## Check if the user exists and the validity of its ID
+id -u "$AUTH_USER" >/dev/null 2>&1 || error "User $AUTH_USER does not exist"
+(( $(id -u "$AUTH_USER") >= 1000 )) || error "User $AUTH_USER ID within system reserved range."
+
+## Use a key pair to authenticate the user (private key has to be set as a GitLab CI/CD variable)
+AUTH_KEY=$CUSTOM_ENV_AUTH_KEY
+AUTH_PUB=/etc/gitlab-runner/authorized_keys
+
+(
+while read -r PUB
+do
+    diff <(ssh-keygen -y -e -f /dev/stdin <<< "$AUTH_KEY") <(ssh-keygen -y -e -f /dev/stdin <<< "$PUB") && exit 0
+done < "$AUTH_PUB"
+exit 1
+) || error "Authentication failed."
+
+### Env cleanup
+
+AUTH_USER_WORK=$(runuser "$AUTH_USER" --login --command "echo \$WORK")
+
+: "${AUTH_USER_WORK:?"Could not determine $AUTH_USER's \$WORK directory."}"
+
+BASE_DIR=$AUTH_USER_WORK/gitlab-runner/builds/${CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID:?}/${CUSTOM_ENV_CI_PROJECT_NAMESPACE:?}/${CUSTOM_ENV_CI_PROJECT_NAME:?}
+
+runuser "$AUTH_USER" --command "rm -rf $BASE_DIR"
+runuser "$AUTH_USER" --command "rm -rf $BASE_DIR.tmp"
diff --git a/runner_scripts/root/config.sh b/runner_scripts/root/config.sh
index 12e5678..ca07625 100755
--- a/runner_scripts/root/config.sh
+++ b/runner_scripts/root/config.sh
@@ -2,10 +2,45 @@
 set -euf -o pipefail
 shopt -s inherit_errexit
 
+hash id
+hash diff
+hash ssh-keygen
+hash runuser
+
+function error {
+    : "${RV:=${2:-$BUILD_FAILURE_EXIT_CODE}}"
+    echo "$1" >&2
+    return "$RV"
+}
+
+## User authentication
+
 : "${CUSTOM_ENV_AUTH_USER:?"AUTH_USER CI/CD variable has not been set."}"
-: "${CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID:?"CI_CONCURRENT_PROJECT_ID CI/CD variable has not been set."}"
+: "${CUSTOM_ENV_AUTH_KEY:?"AUTH_KEY CI/CD variable has not been set."}"
+
+AUTH_USER=$CUSTOM_ENV_AUTH_USER
+
+## Check if the user exists and the validity of its ID
+id -u "$AUTH_USER" >/dev/null 2>&1 || error "User $AUTH_USER does not exist"
+(( $(id -u "$AUTH_USER") >= 1000 )) || error "User $AUTH_USER ID within system reserved range."
+
+## Use a key pair to authenticate the user (private key has to be set as a GitLab CI/CD variable)
+AUTH_KEY=$CUSTOM_ENV_AUTH_KEY
+AUTH_PUB=/etc/gitlab-runner/authorized_keys
+
+(
+while read -r PUB
+do
+    diff --color=never <(ssh-keygen -y -e -f /dev/stdin <<< "$AUTH_KEY") <(ssh-keygen -y -e -f /dev/stdin <<< "$PUB") > /dev/null && exit 0
+done < "$AUTH_PUB"
+exit 1
+) || error "Authentication failed."
+
+### Env setup
+
+AUTH_USER_WORK=$(runuser "$AUTH_USER" --login --command "echo \$WORK")
 
-AUTH_USER_WORK=$(runuser --login "$CUSTOM_ENV_AUTH_USER" --command "echo \$WORK")
+: "${AUTH_USER_WORK:?"Could not determine $AUTH_USER's \$WORK directory."}"
 
 cat << EOS
 {
diff --git a/runner_scripts/root/run.sh b/runner_scripts/root/run.sh
old mode 100644
new mode 100755
index b42f2ee..c2e899f
--- a/runner_scripts/root/run.sh
+++ b/runner_scripts/root/run.sh
@@ -25,9 +25,6 @@ function error {
 : "${CUSTOM_ENV_AUTH_KEY:?"AUTH_KEY CI/CD variable has not been set."}"
 
 AUTH_USER=$CUSTOM_ENV_AUTH_USER
-AUTH_USER_HOME=$(getent passwd "$AUTH_USER" | awk -F ":" '{print $6}')
-AUTH_USER_SHELL=$(getent passwd "$AUTH_USER" | awk -F ":" '{print $7}')
-AUTH_USER_WORK=$(runuser "$AUTH_USER" --login --command "echo \$WORK")
 
 ## Check if the user exists and the validity of its ID
 id -u "$AUTH_USER" >/dev/null 2>&1 || error "User $AUTH_USER does not exist"
@@ -46,6 +43,13 @@ exit 1
 ) || error "Authentication failed."
 
 ### Env setup
+
+AUTH_USER_HOME=$(getent passwd "$AUTH_USER" | awk -F ":" '{print $6}')
+AUTH_USER_SHELL=$(getent passwd "$AUTH_USER" | awk -F ":" '{print $7}')
+AUTH_USER_WORK=$(runuser "$AUTH_USER" --login --command "echo \$WORK")
+
+: "${AUTH_USER_WORK:?"Could not determine $AUTH_USER's \$WORK directory."}"
+
 chown -R "$AUTH_USER" "$TMPDIR"
 
 BASE_DIR=$AUTH_USER_WORK/gitlab-runner/builds/${CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID:?}/${CUSTOM_ENV_CI_PROJECT_NAMESPACE:?}/${CUSTOM_ENV_CI_PROJECT_NAME:?}
-- 
GitLab