I expected something different.

This commit is contained in:
2023-09-06 02:21:51 +03:00
parent 478009848e
commit 7c2892c5b4
2 changed files with 175 additions and 3 deletions

173
harden
View File

@@ -383,10 +383,13 @@ EOF
# which will be installed and run on port 9443 by default to make it easier to manage docker
# url to follow after the installation is complete: https://vps_ip:9443
# the https:// part is important as portainer will not work without it
# For portainer, we will be using the --runtime=runc option to run it with runc because
# For portainer (and watchtower), we will be using the --runtime=runc option to run it with runc because
# it doesn't work with runsc as it is not exposing the docker socket to the container
# but containers downloaded from it will still use runsc
sudo -E runuser - secdep -c 'docker run --runtime=runc -d -p 8000:8000 -p 9443:9443 --name=portainer --restart=always -v /run/user/$UID/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce'
# Watchtower is a docker image that will automatically update all the other docker images
# that are installed and running so we don't have to do it manually
sudo -E runuser - secdep -c 'docker run --runtime=runc -d --name watchtower --restart=always -v /run/user/$UID/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup --interval 3600'
# Check if the dockerImages array is empty and return 0 if it is
[[ "${#dockerImages[@]}" -eq 0 ]] && return 0
# Loop through the dockerImages array
@@ -486,6 +489,168 @@ EOF
sudo at now + 1 minute <<< "bash /root/delete_users.sh"
}
function dynamicDockerPortsCronjob {
sudo mkdir -p /root/bin
cat << 'TOHERE' | sudo tee /root/bin/dynamic_docker_ports_cronjob.sh
#!/usr/bin/env bash
# Get the current ports used by docker
CURRENT_DOCKER_PORTS_CMD="docker ps --format '{{.Ports}}' | rev | cut -d'/' -f2 | sed 's@^[^0-9]*\([0-9]\+\).*@\1@' | rev | sort -u | tr '\n' ' ')"
CURRENT_DOCKER_PORTS="$(sudo machinectl shell secdep@ /bin/bash -c "$CURRENT_DOCKER_PORTS_CMD")"
# Get the current ports allowed by the firewall
CURRENT_FIREWALL_PORTS_FIREWALLD_CMD="sudo firewall-cmd --list-ports | tr '\n' ' '"
CURRENT_FIREWALL_PORTS_UFW_CMD="sudo ufw status numbered | awk '{print \$3}' | sed '/^[[:space:]]*$/d' | \grep -Eow '[[:digit:]]+' | sort -u | tr '\n' ' '"
# Determine if ufw or firewalld is currently used
whereis ufw | grep -q /ufw && currentFirewall="ufw" || currentFirewall="firewalld"
# Find which ports are not allowed by the firewall but are used by docker
case "$currentFirewall" in
ufw)
NEW_PORTS="$(comm -23 <(printf "%s" "$CURRENT_DOCKER_PORTS") <(printf "%s" "$CURRENT_FIREWALL_PORTS_UFW_CMD"))"
;;
firewalld)
NEW_PORTS="$(comm -23 <(printf "%s" "$CURRENT_DOCKER_PORTS") <(printf "%s" "$CURRENT_FIREWALL_PORTS_FIREWALLD_CMD"))"
;;
*)
printf "%s" "Unsupported firewall"
exit 1
;;
esac
# Loop through the ports in the NEW_PORTS variable if it is not empty
if [[ -n "$NEW_PORTS" ]]; then
for port in $NEW_PORTS; do
# Allow the port in the firewall
case "$currentFirewall" in
ufw)
sudo ufw allow "$port"/tcp
;;
firewalld)
sudo firewall-cmd --permanent --add-port="$port"/tcp
;;
*)
printf "%s" "Unsupported firewall"
exit 1
;;
esac
done
fi
# Find which ports are not used by docker but are allowed by the firewall
case "$currentFirewall" in
ufw)
OLD_PORTS="$(comm -23 <(printf "%s" "$CURRENT_FIREWALL_PORTS_UFW_CMD") <(printf "%s" "$CURRENT_DOCKER_PORTS"))"
;;
firewalld)
OLD_PORTS="$(comm -23 <(printf "%s" "$CURRENT_FIREWALL_PORTS_FIREWALLD_CMD") <(printf "%s" "$CURRENT_DOCKER_PORTS"))"
;;
*)
printf "%s" "Unsupported firewall"
exit 1
;;
esac
# Loop through the ports in the OLD_PORTS variable if it is not empty
if [[ -n "$OLD_PORTS" ]]; then
for port in $OLD_PORTS; do
# Deny the port in the firewall
case "$currentFirewall" in
ufw)
sudo ufw deny "$port"/tcp
;;
firewalld)
sudo firewall-cmd --permanent --remove-port="$port"/tcp
;;
*)
printf "%s" "Unsupported firewall"
exit 1
;;
esac
done
fi
TOHERE
cat << TOHERE | sudo tee -a /var/spool/cron/crontabs/root
# Every 30 minutes check if there are any new ports used by docker and allow them in the firewall
*/30 * * * * /root/bin/dynamic_docker_ports_cronjob.sh
TOHERE
sudo chmod +x /root/bin/dynamic_docker_ports_cronjob.sh
sudo systemctl restart cron
}
function automaticUpdatesCronjob {
sudo mkdir -p /root/bin
cat << 'TOHERE' | sudo tee /root/bin/automatic_updates_cronjob.sh
#!/usr/bin/env bash
function get_distro {
if [[ -e /etc/os-release ]] && [[ -r /etc/os-release ]]; then # Check if file exists and is readable
. /etc/os-release # Source the file
printf "%s" "$NAME" # Output the distribution's name
else # If the file does not exist or is not readable
printf "%s" "File os-release not found or not readable" # Output error message
exit 1 # Exit with error code 1
fi
}
# The get_package_manager function will take the output of the get_distro function and determine
# which is the package manager used for the most popular server distros and exit if it is not found.
function get_package_manager {
local distro # Declare distro as a local variable
distro="$(get_distro)" # Get the distribution name
case "$distro" in # Use case to check for the distribution name
"Ubuntu" | "Debian GNU/Linux") # If the distribution is Ubuntu or Debian
printf "%s" "apt" # Output apt
;;
"CentOS Linux" | "Fedora" | "Red Hat Enterprise Linux Server") # If the distribution is CentOS, Fedora or RHEL
printf "%s" "dnf" # Output dnf
;;
"openSUSE Leap") # If the distribution is OpenSUSE
printf "%s" "zypper" # Output zypper
;;
*)
# If the distribution is none of the above, output unsupported distribution
# and exit with error code 1
printf "%s" "Unsupported distribution"
exit 1 # Exit with error code 1
;;
esac
}
# The update_system function will take the output of the get_package_manager function and update the system
# It will also check if the package manager is known and exit if it is not.
function install_packages {
local package_manager # Declare package_manager as a local variable
package_manager="$(get_package_manager)" # Get the package manager
case "$package_manager" in # Use case to check for the package manager
"apt") # If the package manager is apt
printf "%s" 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
export DEBIAN_PRIORITY=critical
# Running sudo with -E will preserve the environment variables set in the script
sudo -E apt update -y && sudo apt upgrade -y # Update the package list and upgrade the packages
sudo -E apt install -y
;;
"dnf") # If the package manager is dnf
sudo dnf upgrade -y # Update the package list
sudo dnf install -y
;;
"zypper") # If the package manager is zypper
sudo zypper update -y # Update the package list
sudo zypper install -y
;;
*)
# If the package manager is not one of the above, output unsupported package manager
# and exit with error code 1
printf "%s" "Unsupported package manager"
exit 1 # Exit with error code 1
;;
esac
}
update_system
TOHERE
cat << TOHERE | sudo tee -a /var/spool/cron/crontabs/root
# Every day at 4:00 AM update the system
0 4 * * * /root/bin/automatic_updates_cronjob.sh
TOHERE
sudo chmod +x /root/bin/automatic_updates_cronjob.sh
sudo systemctl restart cron
}
# The main function will call the declared functions in order and exit if any of them fails.
# It will also pass any arguments passed to the script to the dockerInit function.
# Then it will output a message to the user and reboot the system in 2 minutes.
@@ -504,9 +669,13 @@ function main {
# Call the dockerInit function with the arguments passed to the script
dockerInit "$@" || exit 1 # Initialize docker and exit if it fails
printf "%s" "Docker Rootless, docker-compose and gVisor installed and configured"
printf "%s" "Portainer along with any specified docker images from the command line or a docker-compose.yml file installed"
printf "%s" "Portainer and Watchtower along with any specified docker images from the command line or a docker-compose.yml file installed"
enableServices || exit 1 # Enable the services that need to be restarted and the firewall
printf "%s" "Services restarted and firewall enabled"
dynamicDockerPortsCronjob || exit 1 # Allow the ports used by docker in the firewall
printf "%s" "CronJob to allow the ports used by docker in the firewall installed"
automaticUpdatesCronjob || exit 1 # Install a cronjob to update the system periodically
printf "%s" "CronJob to update the system installed"
deleteRemainingUsers || exit 1 # Delete possible remaining users
printf "%s" "Any unnecessary users deleted"
printf "%s" "$SCRIPT_NAME script finished" # Output message to the user