Skip to content

Commit

Permalink
test[entry.bats]: Added basic tests and improved script
Browse files Browse the repository at this point in the history
  • Loading branch information
sidey79 committed Dec 23, 2024
1 parent 3fbae7b commit 3cce7ae
Show file tree
Hide file tree
Showing 2 changed files with 350 additions and 85 deletions.
257 changes: 172 additions & 85 deletions src/entry.sh
Original file line number Diff line number Diff line change
@@ -1,94 +1,181 @@
#!/bin/bash

export ALEXAFHEM_DIR="/alexa-fhem"
export ALEXAFHEM_UID="${ALEXAFHEM_UID:-6062}"
export ALEXAFHEM_GID="${ALEXAFHEM_GID:-6062}"

[ ! -f /image_info.EMPTY ] && touch /image_info.EMPTY

chmod --quiet go-w ${ALEXAFHEM_DIR}

# creating user environment
echo "Preparing user environment ..."
[ ! -s /etc/passwd.orig ] && cp -f /etc/passwd /etc/passwd.orig
[ ! -s /etc/shadow.orig ] && cp -f /etc/shadow /etc/shadow.orig
[ ! -s /etc/group.orig ] && cp -f /etc/group /etc/group.orig
cp -f /etc/passwd.orig /etc/passwd
cp -f /etc/shadow.orig /etc/shadow
cp -f /etc/group.orig /etc/group
groupadd --force --gid ${ALEXAFHEM_GID} alexa-fhem 2>&1>/dev/null
useradd --home ${ALEXAFHEM_DIR} --shell /bin/bash --uid ${ALEXAFHEM_UID} --no-create-home --no-user-group --non-unique alexa-fhem 2>&1>/dev/null
usermod --append --gid ${ALEXAFHEM_GID} --groups ${ALEXAFHEM_GID} alexa-fhem 2>&1>/dev/null
chown --recursive --quiet --no-dereference ${ALEXAFHEM_UID}:${ALEXAFHEM_GID} ${ALEXAFHEM_DIR}/ 2>&1>/dev/null

# SSH key: Ed25519
mkdir -p ${ALEXAFHEM_DIR}/.ssh
if [ ! -s ${ALEXAFHEM_DIR}/.ssh/id_ed25519 ]; then
echo -e " - Generating SSH Ed25519 client certificate for user 'alexa-fhem' ..."
rm -f ${ALEXAFHEM_DIR}/.ssh/id_ed25519*
ssh-keygen -t ed25519 -f ${ALEXAFHEM_DIR}/.ssh/id_ed25519 -q -N "" -o -a 100
sed -i "s/root@.*/alexa-fhem@alexa-fhem-docker/" ${ALEXAFHEM_DIR}/.ssh/id_ed25519.pub
fi
chmod 600 ${ALEXAFHEM_DIR}/.ssh/id_ed25519
chmod 644 ${ALEXAFHEM_DIR}/.ssh/id_ed25519.pub

# SSH key: RSA
if [ ! -s ${ALEXAFHEM_DIR}/.ssh/id_rsa ]; then
echo -e " - Generating SSH RSA client certificate for user 'alexa-fhem' ..."
rm -f ${ALEXAFHEM_DIR}/.ssh/id_rsa*
ssh-keygen -t rsa -b 4096 -f ${ALEXAFHEM_DIR}/.ssh/id_rsa -q -N "" -o -a 100
sed -i "s/root@.*/alexa-fhem@alexa-fhem-docker/" ${ALEXAFHEM_DIR}/.ssh/id_rsa.pub
fi
chmod 600 ${ALEXAFHEM_DIR}/.ssh/id_rsa
chmod 644 ${ALEXAFHEM_DIR}/.ssh/id_rsa.pub

# SSH client hardening
if [ ! -f ${ALEXAFHEM_DIR}/.ssh/config ]; then
echo "IdentityFile ~/.ssh/id_ed25519
#--- Global behaviour settings ---------------------------------------------------------------------------------------

set -u # Make use of unbound variables an error
set -o pipefail # Distribute an error exit status through the whole pipe

#--- Constants -------------------------------------------------------------------------------------------------------
declare -r DEBUG=true

#--- Environment variables, configurable from outside ----------------------------------------------------------------

declare -r ALEXAFHEM_DIR="${ALEXAFHEM_DIR:-/alexa-fhem}"
declare -ri ALEXAFHEM_UID="${ALEXAFHEM_UID:-6062}"
declare -ri ALEXAFHEM_GID="${ALEXAFHEM_GID:-6062}"



prepare_user_environment() {
[ ! -f /image_info.EMPTY ] && touch /image_info.EMPTY
chmod --quiet go-w "${ALEXAFHEM_DIR}"
echo "Preparing user environment ..."
[ ! -s /etc/passwd.orig ] && cp -f /etc/passwd /etc/passwd.orig
[ ! -s /etc/shadow.orig ] && cp -f /etc/shadow /etc/shadow.orig
[ ! -s /etc/group.orig ] && cp -f /etc/group /etc/group.orig
cp -f /etc/passwd.orig /etc/passwd
cp -f /etc/shadow.orig /etc/shadow
cp -f /etc/group.orig /etc/group
groupadd --force --gid ${ALEXAFHEM_GID} alexa-fhem 2>&1>/dev/null
useradd --home "${ALEXAFHEM_DIR}" --shell /bin/bash --uid ${ALEXAFHEM_UID} --no-create-home --no-user-group --non-unique alexa-fhem 2>&1>/dev/null
usermod --append --gid ${ALEXAFHEM_GID} --groups ${ALEXAFHEM_GID} alexa-fhem 2>&1>/dev/null
chown --recursive --quiet --no-dereference ${ALEXAFHEM_UID}:${ALEXAFHEM_GID} "${ALEXAFHEM_DIR}"/ 2>&1>/dev/null
}

generate_ssh_keys() {
mkdir -p ${ALEXAFHEM_DIR}/.ssh
if [ ! -s ${ALEXAFHEM_DIR}/.ssh/id_ed25519 ]; then
echo -e " - Generating SSH Ed25519 client certificate for user 'alexa-fhem' ..."
rm -f ${ALEXAFHEM_DIR}/.ssh/id_ed25519*
ssh-keygen -t ed25519 -f ${ALEXAFHEM_DIR}/.ssh/id_ed25519 -q -N "" -o -a 100
sed -i "s/root@.*/alexa-fhem@alexa-fhem-docker/" ${ALEXAFHEM_DIR}/.ssh/id_ed25519.pub
fi
chmod 600 ${ALEXAFHEM_DIR}/.ssh/id_ed25519
chmod 644 ${ALEXAFHEM_DIR}/.ssh/id_ed25519.pub

if [ ! -s ${ALEXAFHEM_DIR}/.ssh/id_rsa ]; then
echo -e " - Generating SSH RSA client certificate for user 'alexa-fhem' ..."
rm -f ${ALEXAFHEM_DIR}/.ssh/id_rsa*
ssh-keygen -t rsa -b 4096 -f ${ALEXAFHEM_DIR}/.ssh/id_rsa -q -N "" -o -a 100
sed -i "s/root@.*/alexa-fhem@alexa-fhem-docker/" ${ALEXAFHEM_DIR}/.ssh/id_rsa.pub
fi
chmod 600 ${ALEXAFHEM_DIR}/.ssh/id_rsa
chmod 644 ${ALEXAFHEM_DIR}/.ssh/id_rsa.pub
}

harden_ssh_client() {
if [ ! -f ${ALEXAFHEM_DIR}/.ssh/config ]; then
echo "IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_rsa
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
HostKeyAlgorithms ssh-ed25519,ssh-rsa
KexAlgorithms curve25519-sha256,[email protected],diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
MACs [email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,[email protected]
" > ${ALEXAFHEM_DIR}/.ssh/config
fi

# SSH key pinning
touch ${ALEXAFHEM_DIR}/.ssh/known_hosts
cat ${ALEXAFHEM_DIR}/.ssh/known_hosts /ssh_known_hosts.txt | grep -v ^# | sort -u -k2,3 > ${ALEXAFHEM_DIR}/.ssh/known_hosts.tmp
mv -f ${ALEXAFHEM_DIR}/.ssh/known_hosts.tmp ${ALEXAFHEM_DIR}/.ssh/known_hosts
chown -R alexa-fhem.alexa-fhem ${ALEXAFHEM_DIR}/.ssh/

if [[ ! -L /alexa-fhem/.alexa/config.json && -f /alexa-fhem/.alexa/config.json && ! -e /alexa-fhem/config.json ]]; then
echo " - Moving configuration from /alexa-fhem/.alexa/config.json to /alexa-fhem/config.json ..."
mv -f /alexa-fhem/.alexa/config.json /alexa-fhem/config.json
fi

if [[ -e /alexa-fhem/alexa-fhem.json && ! -e /alexa-fhem/config.json ]]; then
echo " - Moving configuration from /alexa-fhem/alexa-fhem.json to /alexa-fhem/config.json ..."
mv -f /alexa-fhem/alexa-fhem.json /alexa-fhem/config.json
" > "${ALEXAFHEM_DIR}"/.ssh/config
fi
}

pin_ssh_keys() {
touch ${ALEXAFHEM_DIR}/.ssh/known_hosts
cat ${ALEXAFHEM_DIR}/.ssh/known_hosts /ssh_known_hosts.txt | grep -v ^# | sort -u -k2,3 > ${ALEXAFHEM_DIR}/.ssh/known_hosts.tmp
mv -f ${ALEXAFHEM_DIR}/.ssh/known_hosts.tmp ${ALEXAFHEM_DIR}/.ssh/known_hosts
chown -R ${ALEXAFHEM_UID}:${ALEXAFHEM_GID} ${ALEXAFHEM_DIR}/.ssh/
}


move_configurations() {
if [[ ! -L "${ALEXAFHEM_DIR}"/.alexa/config.json && -f "${ALEXAFHEM_DIR}"/.alexa/config.json && ! -e "${ALEXAFHEM_DIR}"/config.json ]]; then
echo " - Moving configuration from ${ALEXAFHEM_DIR}/.alexa/config.json to ${ALEXAFHEM_DIR}/config.json ..."
mv -f "${ALEXAFHEM_DIR}"/.alexa/config.json "${ALEXAFHEM_DIR}"/config.json
fi

if [[ -e "${ALEXAFHEM_DIR}"/alexa-fhem.json && ! -e "${ALEXAFHEM_DIR}"/config.json ]]; then
echo " - Moving configuration from ${ALEXAFHEM_DIR}/alexa-fhem.json to ${ALEXAFHEM_DIR}/config.json ..."
mv -f "${ALEXAFHEM_DIR}"/alexa-fhem.json "${ALEXAFHEM_DIR}"/config.json
fi

if [ ! -e "${ALEXAFHEM_DIR}"/config.json ]; then
echo " - Creating default config in ${ALEXAFHEM_DIR}/config.json ..."
cp /alexa-fhem.src/alexa-fhem-docker.config.json "${ALEXAFHEM_DIR}"/config.json
fi

if [[ ! -L "${ALEXAFHEM_DIR}"/config.json && -f "${ALEXAFHEM_DIR}"/config.json ]]; then
echo " - Creating symlink to ${ALEXAFHEM_DIR}/config.json in ${ALEXAFHEM_DIR}/.alexa/config.json ..."
mkdir -p "${ALEXAFHEM_DIR}"/.alexa/
ln -sf "${ALEXAFHEM_DIR}"/config.json "${ALEXAFHEM_DIR}"/.alexa/config.json
fi
ln -sf "${ALEXAFHEM_DIR}"/config.json "${ALEXAFHEM_DIR}"/alexa-fhem.json
}



# Funktion, um Debug-Ausgaben zu machen
debug_log() {
if [ "$DEBUG" = true ]; then
echo "Debug: $1" >&2
fi
}

# Funktion, um den Pfad in einen `jq`-kompatiblen Suchstring umzuwandeln
convert_path_to_jq() {
local path="$1"
IFS='.' read -r -a parts <<< "$path"
local jq_path=""
for part in "${parts[@]}"; do
if [[ "$part" =~ ^[0-9]+$ ]]; then
jq_path+="[$part]"
else
jq_path+=".$part"
fi
done
echo "$jq_path"
}


# Funktion, um die JSON-Datei zu aktualisieren

update_config() {
local config_file=$1

debug_log "update_config called with config_file=${config_file}"

# JSON Datei in eine Variable laden
json=$(cat "$config_file")

debug_log "initial JSON=${json}"

# Iteriere über alle Umgebungsvariablen
while IFS= read -r var; do
path=$(echo "$var" | awk -F= '{print $1}' | tr '_' '.')
value=$(echo "$var" | awk -F= '{print substr($0, index($0,$2))}')

debug_log "processing variable CONFIG_${path} with value=${value}"

# Erzeuge den `jq`-Suchstring und setze den Wert in Anführungszeichen
jq_path=$(convert_path_to_jq "$path")
jq_search_string="$jq_path |= \"$value\""

debug_log "jq search string: $jq_search_string"

# JSON Struktur basierend auf Umgebungsvariablen aktualisieren
json=$(echo "$json" | jq "$jq_search_string")

done < <(env | grep '^CONFIG_' | sed 's/^CONFIG_//')

debug_log "JSON after update=${json}"

# JSON Datei speichern
if echo "$json" | jq empty > /dev/null 2>&1; then
echo "$json" | jq . > "$config_file"
debug_log "final JSON written to ${config_file}"
else
debug_log "Final JSON is invalid, not written to ${config_file}"
fi
}

if [ "$#" -eq 1 ] && [ "$1" = "start" ]; then
prepare_user_environment
generate_ssh_keys
harden_ssh_client
pin_ssh_keys
move_configurations

echo -e '\n\n'
if [ -s /pre-start.sh ]; then
echo "Running pre-start script ..."
/pre-start.sh
fi
echo 'Starting alexa-fhem ...'
su - alexa-fhem -c "cd "${ALEXAFHEM_DIR}"; /usr/local/bin/alexa-fhem --dockerDetached"
fi

if [ ! -e /alexa-fhem/config.json ]; then
echo " - Creating default config in /alexa-fhem/config.json ..."
cp /alexa-fhem.src/alexa-fhem-docker.config.json /alexa-fhem/config.json
fi

if [[ ! -L /alexa-fhem/config.json && -f /alexa-fhem/config.json ]]; then
echo " - Creating symlink to config.json in /alexa-fhem/.alexa/config.json ..."
mkdir -p /alexa-fhem/.alexa/
ln -sf ../config.json /alexa-fhem/.alexa/config.json
fi
ln -sf config.json alexa-fhem.json

# Start main process
echo -e '\n\n'

if [ -s /pre-start.sh ]; then
echo "Running pre-start script ..."
/pre-start.sh
fi

echo 'Starting alexa-fhem ...'
su - alexa-fhem -c "cd "${ALEXAFHEM_DIR}"; /usr/local/bin/alexa-fhem --dockerDetached"
Loading

0 comments on commit 3cce7ae

Please sign in to comment.