third time's a charm
This commit is contained in:
167
harden
167
harden
@@ -98,7 +98,7 @@ function install_packages {
|
|||||||
# and store the ones that are indeed absent in another local array.
|
# and store the ones that are indeed absent in another local array.
|
||||||
# Then it will install the packages that are missing by invoking the install_packages function.
|
# Then it will install the packages that are missing by invoking the install_packages function.
|
||||||
function check_dependencies {
|
function check_dependencies {
|
||||||
local dependencies=(curl git sudo vim ssh docker docker-compose wget) # Declare dependencies as a local array
|
local dependencies=(curl git sudo vim ssh docker-ce docker.io docker docker-compose wget fail2ban) # Declare dependencies as a local array
|
||||||
#> see what to do with name differences between distros if any <#
|
#> see what to do with name differences between distros if any <#
|
||||||
local missing_dependencies=() # Declare missing_dependencies as a local array
|
local missing_dependencies=() # Declare missing_dependencies as a local array
|
||||||
for dependency in "${dependencies[@]}"; do # Loop through the dependencies array
|
for dependency in "${dependencies[@]}"; do # Loop through the dependencies array
|
||||||
@@ -182,21 +182,21 @@ function getCorrectKernelSecurityModule {
|
|||||||
local distro # Declare distro as a local variable
|
local distro # Declare distro as a local variable
|
||||||
distro="$(get_distro)" # Get the distribution name
|
distro="$(get_distro)" # Get the distribution name
|
||||||
case "$distro" in # Use case to check for the distribution name
|
case "$distro" in # Use case to check for the distribution name
|
||||||
"Ubuntu") # If the distribution is Debian
|
"Ubuntu") # If the distribution is Ubuntu
|
||||||
apt install apparmor-profiles -y # Install apparmor
|
apt install apparmor-profiles apparmor-utils apparmor-profiles-extra -y # Install apparmor
|
||||||
printf "%s" "apparmor" # Output apparmor
|
printf "%s" "apparmor" # Output apparmor
|
||||||
;;
|
;;
|
||||||
"Debian GNU/Linux") # If the distribution is Debian
|
"Debian GNU/Linux") # If the distribution is Debian
|
||||||
apt install apparmor apparmor-utils auditd
|
apt install apparmor apparmor-utils auditd python3-apparmor -y # Install apparmor
|
||||||
printf "%s" "apparmor" # Output apparmor
|
printf "%s" "apparmor" # Output apparmor
|
||||||
;;
|
;;
|
||||||
"CentOS Linux" | "Fedora" | "Red Hat Enterprise Linux Server") # If the distribution is CentOS, Fedora or RHEL
|
"CentOS Linux" | "Fedora" | "Red Hat Enterprise Linux Server") # If the distribution is CentOS, Fedora or RHEL
|
||||||
dnf install selinux -y # Install selinux
|
dnf install selinux container-selinux -y # Install selinux
|
||||||
printf "%s" "selinux" # Output selinux
|
printf "%s" "selinux" # Output selinux
|
||||||
;;
|
;;
|
||||||
|
|
||||||
"openSUSE Leap") # If the distribution is OpenSUSE
|
"openSUSE Leap") # If the distribution is OpenSUSE
|
||||||
zypper install libapparmor apparmor-profiles apparmor-utils apparmor-parser yast2-apparmor apparmor-docs -y # Install apparmor
|
zypper install -t pattern apparmor -y # Install apparmor
|
||||||
printf "%s" "apparmor" # Output apparmor
|
printf "%s" "apparmor" # Output apparmor
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -217,8 +217,7 @@ function firewallInit {
|
|||||||
sudo ufw default deny incoming # Deny incoming connections
|
sudo ufw default deny incoming # Deny incoming connections
|
||||||
sudo ufw allow 22100/tcp # Allow ssh connections on port 22100
|
sudo ufw allow 22100/tcp # Allow ssh connections on port 22100
|
||||||
sudo ufw enable # Enable the firewall
|
sudo ufw enable # Enable the firewall
|
||||||
sudo systemctl enable ufw # Enable the firewall on boot
|
sudo systemctl enable --now ufw # Enable and start the firewall on boot
|
||||||
sudo systemctl start ufw # Start the firewall
|
|
||||||
;;
|
;;
|
||||||
firewalld)
|
firewalld)
|
||||||
sudo systemctl enable --now firewalld # Enable the firewall on boot and start it
|
sudo systemctl enable --now firewalld # Enable the firewall on boot and start it
|
||||||
@@ -238,9 +237,12 @@ function kernelSecurityModuleInit {
|
|||||||
case "$kernelSecurityModule" in
|
case "$kernelSecurityModule" in
|
||||||
apparmor)
|
apparmor)
|
||||||
sudo systemctl enable --now apparmor # Enable the kernel security module on boot and start it
|
sudo systemctl enable --now apparmor # Enable the kernel security module on boot and start it
|
||||||
|
sudo aa-enforce /etc/apparmor.d/* # Enforce all apparmor profiles
|
||||||
;;
|
;;
|
||||||
selinux)
|
selinux)
|
||||||
sudo systemctl enable --now selinux # Enable the kernel security module on boot and start it
|
sudo systemctl enable --now selinux # Enable the kernel security module on boot and start it
|
||||||
|
printf "%s" "{\"selinux-enabled\":true}" | sudo tee /etc/docker/daemon.json # Enable selinux in docker
|
||||||
|
sudo setenforce 1 # Enforce selinux
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
printf "%s" "Unsupported kernel security module"
|
printf "%s" "Unsupported kernel security module"
|
||||||
@@ -262,17 +264,106 @@ function dockerInit {
|
|||||||
# No need to pull the docker image as the run command will do it automatically
|
# No need to pull the docker image as the run command will do it automatically
|
||||||
# Run the docker image in the background,
|
# Run the docker image in the background,
|
||||||
# with the restar always option and the name of the docker image
|
# with the restar always option and the name of the docker image
|
||||||
docker run -d --restart always --name "$dockerImage" "$dockerImage"
|
# The --security-opt=no-new-privileges option will prevent the docker image from gaining new privileges
|
||||||
|
# The --cap-drop all option will drop all capabilities from the docker image
|
||||||
|
# The --cap-add NET_ADMIN option will add the NET_ADMIN capability to the docker image
|
||||||
|
docker run -d --restart always --name "$dockerImage" --security-opt=no-new-privileges --cap-drop all --cap-add NET_ADMIN
|
||||||
|
"$dockerImage"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The apparmorConfig function will set up and configure apparmor with sane defaults.
|
||||||
|
function apparmorConfig {
|
||||||
|
# Create a new apparmor profile for the docker daemon
|
||||||
|
sudo aa-genprof docker
|
||||||
|
# Enable the apparmor profile for the docker daemon
|
||||||
|
sudo aa-enforce docker
|
||||||
|
# Reload the apparmor profiles
|
||||||
|
sudo systemctl reload apparmor
|
||||||
|
}
|
||||||
|
|
||||||
|
# The selinuxConfig function will set up and configure selinux with sane defaults.
|
||||||
|
function selinuxConfig {
|
||||||
|
# Set the selinux boolean to allow docker to use the network
|
||||||
|
sudo setsebool -P docker_connect_any 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# This function will create a new apparmor profile for every docker image installed on the system.
|
||||||
|
function apparmorProfiles {
|
||||||
|
# Get all the docker images installed on the system and store them in the dockerImages array
|
||||||
|
local dockerImages=("$(docker images --format "{{.Repository}}")")
|
||||||
|
# Loop through the dockerImages array
|
||||||
|
for dockerImage in "${dockerImages[@]}"; do
|
||||||
|
# Create a new apparmor profile for the docker image
|
||||||
|
sudo aa-genprof "$dockerImage"
|
||||||
|
# Enable the apparmor profile for the docker image
|
||||||
|
sudo aa-enforce "$dockerImage"
|
||||||
|
done
|
||||||
|
# Reload the apparmor profiles
|
||||||
|
sudo systemctl reload apparmor
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureFail2ban {
|
||||||
|
FAIL2BAN_LOCAL=$(cat <<'EOF'
|
||||||
|
[Definition]
|
||||||
|
logtarget = /var/log/fail2ban/fail2ban.log
|
||||||
|
allowipv6 = auto
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
printf "%s" "$FAIL2BAN_LOCAL" | sudo tee /etc/fail2ban/fail2ban.local
|
||||||
|
FAIL2BAN_SSH_JAIL_LOCAL=$(cat <<'EOF'
|
||||||
|
[sshd]
|
||||||
|
enabled = true
|
||||||
|
filter = sshd
|
||||||
|
banaction = ufw
|
||||||
|
backend = systemd
|
||||||
|
maxretry = 3
|
||||||
|
# 3 failed attempts in 600 seconds = 10 minutes
|
||||||
|
findtime = 1d
|
||||||
|
bantime = 1d
|
||||||
|
ignoreip = 127.0.0.1/8
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
printf "%s" "$FAIL2BAN_SSH_JAIL_LOCAL" | sudo tee /etc/fail2ban/jail.local/sshd.local
|
||||||
|
FAIL2BAN_FILTER=$(cat <<'EOF'
|
||||||
|
[Definition]
|
||||||
|
failregex = ^.*DROP_.*SRC=<ADDR> DST=.*$
|
||||||
|
journalmatch = _TRANSPORT=kernel
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
printf "%s" "$FAIL2BAN_FILTER" | sudo tee /etc/fail2ban/filter.d/fwdrop.local
|
||||||
|
HARDEN_FAIL2BAN_SERVICE=$(cat <<'EOF'
|
||||||
|
[Service]
|
||||||
|
PrivateDevices=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
ProtectHome=read-only
|
||||||
|
ProtectSystem=strict
|
||||||
|
ReadWritePaths=-/var/run/fail2ban
|
||||||
|
ReadWritePaths=-/var/lib/fail2ban
|
||||||
|
ReadWritePaths=-/var/log/fail2ban
|
||||||
|
ReadWritePaths=-/var/spool/postfix/maildrop
|
||||||
|
ReadWritePaths=/run/xtables.lock
|
||||||
|
CapabilityBoundingSet=CAP_AUDIT_READ CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
printf "%s" "$HARDEN_FAIL2BAN_SERVICE" | sudo tee /etc/systemd/system/fail2ban.service.d/override.conf
|
||||||
|
sudo systemctl enable --now fail2ban
|
||||||
|
printf "%s" "LogLevel VERBOSE" | sudo tee -a /etc/ssh/sshd_config
|
||||||
|
sudo systemctl restart sshd
|
||||||
|
}
|
||||||
|
|
||||||
# The main function will call the check_dependencies function and exit if it fails.
|
# The main function will call the check_dependencies function and exit if it fails.
|
||||||
# It will also output a message to the user to let them know that the script has finished.
|
# It will also output a message to the user to let them know that the script has finished.
|
||||||
function main {
|
function main {
|
||||||
check_dependencies || exit 1 # Check dependencies and exit if it fails
|
check_dependencies || exit 1 # Check dependencies and exit if it fails
|
||||||
harden_ssh || exit 1 # Harden ssh and exit if it fails
|
hardenSSH || exit 1 # Harden ssh and exit if it fails
|
||||||
firewallInit || exit 1 # Initialize the firewall and exit if it fails
|
firewallInit || exit 1 # Initialize the firewall and exit if it fails
|
||||||
kernelSecurityModuleInit || exit 1 # Initialize the kernel security module and exit if it fails
|
kernelSecurityModuleInit || exit 1 # Initialize the kernel security module and exit if it fails
|
||||||
|
configureFail2ban || exit 1 # Initialize fail2ban and exit if it fails
|
||||||
|
dockerInit || exit 1 # Initialize docker and exit if it fails
|
||||||
|
apparmorConfig # Configure apparmor
|
||||||
|
apparmorProfiles # Create apparmor profiles for all docker images
|
||||||
|
selinuxConfig # Configure selinux
|
||||||
# If number of arguments is greater than 0
|
# If number of arguments is greater than 0
|
||||||
# Call the dockerInit function with the arguments passed to the script
|
# Call the dockerInit function with the arguments passed to the script
|
||||||
# Else exit with error code 1
|
# Else exit with error code 1
|
||||||
@@ -287,64 +378,8 @@ function main {
|
|||||||
# exit 1 # Exit with error code 1
|
# exit 1 # Exit with error code 1
|
||||||
# fi
|
# fi
|
||||||
# }
|
# }
|
||||||
#
|
|
||||||
# # The getArgs function will get the arguments passed to the script and store them in an array.
|
|
||||||
# # It will also check if the arguments are valid and exit if they are not.
|
|
||||||
# function getArgs {
|
|
||||||
# local args=() # Declare args as a local array
|
|
||||||
# while [[ $# -gt 0 ]]; do # Loop through the arguments
|
|
||||||
# case "$*" in # Use case to check for the arguments
|
|
||||||
# --help | -h) # If the argument is --help or -h
|
|
||||||
# printf "%s" "Usage: $SCRIPT_NAME [OPTION]..."
|
|
||||||
# ;;
|
|
||||||
# --create-user | -cu) # If the argument is --create-user or -cu
|
|
||||||
# args+=("$1") # Add the argument to the args array
|
|
||||||
# shift # Shift the arguments
|
|
||||||
# case "$*" in
|
|
||||||
# --username=* | -u=*) # If the argument is --username=* or -u=*
|
|
||||||
# args+=("$1") # Add the argument to the args array
|
|
||||||
# shift # Shift the arguments
|
|
||||||
# ;;
|
|
||||||
# --password=* | -p=*) # If the argument is --password=* or -p=*
|
|
||||||
# args+=("$1") # Add the argument to the args array
|
|
||||||
# shift # Shift the arguments
|
|
||||||
# ;;
|
|
||||||
# *)
|
|
||||||
# printf "%s" "Invalid argument: $1"
|
|
||||||
# exit 1
|
|
||||||
# ;;
|
|
||||||
# esac
|
|
||||||
# create_user "${args[@]}" # Call the create_user function with the args array as arguments
|
|
||||||
# ;;
|
|
||||||
# --harden-ssh | -hs) # If the argument is --harden-ssh or -hs
|
|
||||||
# args+=("$1") # Add the argument to the args array
|
|
||||||
# shift # Shift the arguments
|
|
||||||
# harden_ssh "${args[@]}" # Call the harden_ssh function with the args array as arguments
|
|
||||||
# ;;
|
|
||||||
# esac
|
|
||||||
# done
|
|
||||||
# printf "%s" "${args[@]}" # Output the args array
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# # The createUser function will create a new user with the username and password passed as arguments.
|
|
||||||
# function createUser {
|
|
||||||
# # Declare username as a local variable and assign it the first argument passed to the function
|
|
||||||
# local username="$1"
|
|
||||||
# # Declare password as a local variable and assign it the second argument passed to the function
|
|
||||||
# local password="$2"
|
|
||||||
# # Check if the user already exists and exit if they do
|
|
||||||
# if id -u "$username" &> /dev/null; then
|
|
||||||
# printf "%s" "User already exists"
|
|
||||||
# exit 1
|
|
||||||
# fi
|
|
||||||
# # Create the user and add them to the sudo group
|
|
||||||
# useradd -m -G sudo "$username"
|
|
||||||
# # Set the user's password using printf to avoid the password being echoed to the terminal
|
|
||||||
# printf "%s" "$username:$password" | chpasswd
|
|
||||||
# }
|
|
||||||
|
|
||||||
# Call the main function
|
# Call the main function
|
||||||
main "$@"
|
main "$@"
|
||||||
# am_i_root
|
|
||||||
|
|
||||||
exit 0 # The right and proper way to exit a script
|
exit 0 # The right and proper way to exit a script
|
||||||
|
|||||||
Reference in New Issue
Block a user