From 04e3daedf1e389bb2a3d1afdcf243ba863b21c16 Mon Sep 17 00:00:00 2001 From: Pratik Date: Fri, 7 Dec 2018 03:06:32 +0530 Subject: [PATCH] Added Console logs --- init-linux-harden.sh | 414 ++++++++++++++++++++++++++++++------------- 1 file changed, 295 insertions(+), 119 deletions(-) diff --git a/init-linux-harden.sh b/init-linux-harden.sh index 9c23bad..03645c0 100644 --- a/init-linux-harden.sh +++ b/init-linux-harden.sh @@ -1,10 +1,11 @@ #!/etc/bin/env bash - -# Add the user to "sudo" -# Display the private-key on the screen and ask the user 2times to copy it -# Install sudo curl screen -# Restart systemctl restart ssh +# Accept user name as a script argument + # If no username provided + # generate a random username - all lowercase +# Something important fails + # Revert everything back to how it was +# Redirect every output to a logfile # Ask the user to NOT logout yet # Ask him to report back if he can login using the new user -with the ssh-private key # If not @@ -16,21 +17,142 @@ # User SSH-Private Key # User SSH-Public key # Display the root-user's new password on screen -# Something important fails - # Revert everything back to how it was -# Accept user name as a script argument - # If no username provided - # generate a random username - all lowercase # What to do if making .bkp file fails? +############################################################## +# Basic checks before starting +############################################################## + +# No root - no good +[ "$(id -u)" != "0" ] && { + echo "Error: You must be root to run this script, please login as root and execute the script again." + exit 1 +} + +# Check supported OSes +if [[ $(sed 's/\..*//' /etc/debian_version) -eq 8 ]]; then + DEB_VER_STR="jessie" +elif [[ $(sed 's/\..*//' /etc/debian_version) -eq 9 ]]; then + DEB_VER_STR="stretch" +else + printf "This version of Debian is NOT supported.\\n" + exit 1 +fi + + +############################################################## +# Display what the script does +############################################################## + +# What to do if something fails + # Catastophic failure + # Ignorable failure +# Where to find the log file + +############################################################## +# Gather info +############################################################## + +# Change root user's password +# Choose a user name +clear +echo "Do you want to change root password ? (y/n)" +echo "(You might want to do this if you received it as an email from your host.)" + while [[ $RESET_ROOT_PWD != "y" && $RESET_ROOT_PWD != "n" ]]; do + read -rp "Select an option [1-2]: " RESET_ROOT_PWD +done + +# Ask for a user name +echo "" +echo "A new non-root user will be created for you." +read -rp "Please provide a user name - " NORM_USER_NAME + +# If the user exists - ask for a different username +while [[ ! "$NORM_USER_NAME" ]] && [[ $(getent passwd "$NORM_USER_NAME" | wc -l) -gt 0 ]]; do + echo "User name either already exists or you provided an invalid username." + read -rp "Please provide a user name - " NORM_USER_NAME +done + + +############################################################## +# Log +############################################################## + +CSI='\033[' +CEND="${CSI}0m" +CRED="${CSI}1;31m" +CGREEN="${CSI}1;32m" +CVERTICAL="|" +CHORIZONTAL="_" +SCRIPT_NAME=server_harden +SCRIPT_VERSION=0.2 +LOGFILE=/tmp/"$SCRIPT_NAME"_v"$SCRIPT_VERSION".log + + +function horizontal_fill() { + local char=$1 + declare -i rep=$2 + for ((x = 0; x < "$rep"; x++)); do + printf %s "$char" + done +} + +function line_fill() { + horizontal_fill "$1" "$2" + printf "\\n" +} + +function recap (){ + local purpose=$1 + local value=$2 + + if [[ $value ]]; then + value="[${CGREEN}${value}${CEND}]" + else + value="${CRED}-FAILED-${CEND}" + fi + + horizontal_fill "$CVERTICAL" 1 + printf "%20s:%5s%-33s" "$purpose" " " "$(echo -e "$value")" + line_fill "$CVERTICAL" 1 +} + +function finally(){ + #local what_failed=$1 + + line_fill "$CHORIZONTAL" 60 + recap "New root Password" "$PASS_ROOT" + recap "User Name" "$NORM_USER_NAME" + recap "User's Password" "$USER_PASS" + recap "User's SSH Private Key Location" "$KEY_PASS" + recap "User's SSH Public Key Location" "$KEY_PASS" + recap "User's SSH Key Passphrase" "$KEY_PASS" + line_fill "$CHORIZONTAL" 60 +} + +function log() { + local EVENT=$1 + local RESULT=$2 + + if [ "$RESULT" = "SUCCESSFUL" ] + then + printf "%30s %7s [${CGREEN}${RESULT}${CEND}]\\n" "$EVENT" " " + echo "$(date '+%Y-%m-%d %H:%M:%S')" - "$EVENT" - "$RESULT" >> "$LOGFILE" + elif [ "$RESULT" = "FAILED" ] + then + printf "%30s %7s [${CRED}${RESULT}${CEND}]\\n" "$EVENT" " " + printf "\\n\\nPlease look at %s\\n\\n" "$LOGFILE" + echo "$(date '+%Y-%m-%d %H:%M:%S')" - "$EVENT" - "$RESULT" >> "$LOGFILE" + else + printf "%30s %7s [${CRED}..${CEND}]\\r" "$EVENT" " " + echo "$(date '+%Y-%m-%d %H:%M:%S')" - "$EVENT" - "begin..." >> "$LOGFILE" + fi +} + + declare SESSION_TYPE="" - -############################################################## -# Change root's password -############################################################## - # Check if the user connected through SSH -if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then +if [[ -n "$SSH_CLIENT" ]] || [[ -n "$SSH_TTY" ]]; then SESSION_TYPE=remote/ssh else case $(ps -o comm= -p $PPID) in @@ -39,82 +161,34 @@ else esac fi -if [ $SESSION_TYPE == "remote/ssh" ]; then - printf "You are currently connected to an SSH session.\n" +if [[ $SESSION_TYPE == "remote/ssh" ]]; then + printf "You are currently connected to an SSH session.\\n" else - printf "You are currently connected using password authentication.\n" -fi - -{ - # Generate a 15 character random password - PASS_ROOT="$(< /dev/urandom tr -cd "[:alnum:]" | head -c 15)" || exit 1 - - # Change root's password - echo -e "${PASS_ROOT}\n${PASS_ROOT}" | passwd > /dev/null -} - -if [[ $? -eq 0 ]]; then - printf "Successully changed root password.\n" -else - printf "Could not reset root password.\n" - exit 1 + printf "You are currently connected using password authentication.\\n" fi ############################################################## -# Change default source-list +# Change root's password ############################################################## -if [[ $(sed 's/\..*//' /etc/debian_version) -eq 8 ]]; then - DEB_VER_STR="jessie" -elif [[ $(sed 's/\..*//' /etc/debian_version) -eq 9 ]]; then - DEB_VER_STR="stretch" -else - printf "This version of Debian is NOT supported.\n" - exit 1 -fi -mv /etc/apt/sources.list /etc/apt/sources.list.bak -sed -i "1,$(wc -l < /etc/apt/sources.list.bak) s/^/#/" /etc/apt/sources.list.bak +if [[ $RESET_ROOT_PWD == 'y' ]]; then + { + log "Changing root password" + + # Generate a 15 character random password + PASS_ROOT="$(< /dev/urandom tr -cd "[:alnum:]" | head -c 15)" || exit 1 -# Find any additional sources listed by the provider and comment them out -if [[ $(ls -fL /etc/apt/source*/*.list | wc -l ) -gt 0 ]]; then - for file in /etc/apt/source*/*.list; - do - mv "$file" "$file".bak - sed -i "1,$(wc -l < "$file") s/^/#/" "$file" >&2 /dev/null - done -fi + # Change root's password + echo -e "${PASS_ROOT}\\n${PASS_ROOT}" | passwd > /dev/null + } -# Default sources list for debian -cat < /etc/apt/sources.list || exit 1 -deb https://deb.debian.org/debian ${DEB_VER_STR} main -deb-src https://deb.debian.org/debian ${DEB_VER_STR} main - -## Major bug fix updates produced after the final release of the -## distribution. -deb http://security.debian.org ${DEB_VER_STR}/updates main -deb-src http://security.debian.org ${DEB_VER_STR}/updates main - -deb https://deb.debian.org/debian ${DEB_VER_STR}-updates main -deb-src https://deb.debian.org/debian ${DEB_VER_STR}-updates main - -deb https://deb.debian.org/debian ${DEB_VER_STR}-backports main -deb-src https://deb.debian.org/debian ${DEB_VER_STR}-backports main -TAG - -# Comment out cloud-init generated templates for sources -if [[ $(ls -fL /etc/cloud/templates*/*.tmpl | wc -l ) -gt 0 ]]; then - for file in /etc/cloud/templates*/*.tmpl; - do - mv "$file" "$file".bak - sed -i "1,$(wc -l < "$file") s/^/#/" "$file" >&2 /dev/null - done -fi - -if [[ $? -eq 0 ]]; then - printf "Successfully updated the source list.\n" -else - printf "Updating source list failed.\n" + if [[ $? -eq 0 ]]; then + log "Changing root password" "SUCCESSFUL" + else + # Low priority - since we are disabling root login anyways + log "Changing root password" "FAILED" + fi fi @@ -122,51 +196,83 @@ fi # Create a normal user ############################################################## { - clear - # Ask for a user name - read -rp "Please provide a user name - " NORM_USER_NAME - - # If the user exists - ask for a different username - while [ $(getent passwd "$NORM_USER_NAME" | wc -l) -gt 0 ]; do - echo "${NORM_USER_NAME} already exists." - read -rp "Please provide another user name - " NORM_USER_NAME - done + log "Creating new user" # Generate a 15 character random password USER_PASS="$(< /dev/urandom tr -cd "[:alnum:]" | head -c 15)" || exit 1 # Create the user and assign the above password - echo -e "${USER_PASS}\n${USER_PASS}" | adduser "$NORM_USER_NAME" -q --gecos "First Last,RoomNumber,WorkPhone,HomePhone" 2> /dev/null + echo -e "${USER_PASS}\\n${USER_PASS}" | adduser "$NORM_USER_NAME" -q --gecos "First Last,RoomNumber,WorkPhone,HomePhone" 2> /dev/null # Give root privilages to the above user usermod -aG sudo "$NORM_USER_NAME" || exit 1 } if [[ $? -eq 0 ]]; then - printf "Successfully created new user %s.\n" "$NORM_USER_NAME" + log "Creating new user" "SUCCESSFUL" else - printf "Creating new user failed.\n" + log "Creating new user" "FAILED" + finally "CNU" exit 1; fi ############################################################## -# Create SSH Key for the new user created +# Create SSH Key for the new user ############################################################## - { - SSH_DIR=/home/"$NORM_USER_NAME"/.ssh - mkdir "$SSH_DIR" || exit 1 + log "Creating SSH Key for new user" - # Generate a 15 character random password for key - KEY_PASS="$(< /dev/urandom tr -cd "[:alnum:]" | head -c 15)" || exit 1 + shopt -s nullglob + KEY_FILES=("$SSH_DIR"/"$NORM_USER_NAME".pem*) - # Create a OpenSSH-compliant ed25519-type key - ssh-keygen -a 1000 -o -t ed25519 -N "$KEY_PASS" -C "$NORM_USER_NAME" -f "$SSH_DIR"/"$NORM_USER_NAME".pem -q || exit 1 + # Create key file only if it does NOT exist + if [[ ! ${KEY_FILES[0]} ]]; then + SSH_DIR=/home/"$NORM_USER_NAME"/.ssh + mkdir "$SSH_DIR" || exit 1 + + # Generate a 15 character random password for key + KEY_PASS="$(< /dev/urandom tr -cd "[:alnum:]" | head -c 15)" || exit 1 + + # Create a OpenSSH-compliant ed25519-type key + ssh-keygen -a 1000 -o -t ed25519 -N "$KEY_PASS" -C "$NORM_USER_NAME" -f "$SSH_DIR"/"$NORM_USER_NAME".pem -q || exit 1 + + KEY_FILES=("$SSH_DIR"/"$NORM_USER_NAME".pem*) + fi +} +if [[ $? -eq 0 ]]; then + log "Creating SSH Key for new user" "SUCCESSFUL" +else + log "Creating SSH Key for new user" "FAILED" + finally "CSK" + exit 1; +fi + + +############################################################## +# Add generated key to authorized_keys file +############################################################## +{ + log "Adding SSH Key to 'authorized_keys' file" # Insert the public key into "authoried_keys" file - cat "$SSH_DIR"/"$NORM_USER_NAME".pem.pub >> "$SSH_DIR"/authorized_keys || exit 1 + cat "${KEY_FILES[1]}" >> "$SSH_DIR"/authorized_keys || exit 1 +} +if [[ $? -eq 0 ]]; then + log "Adding SSH Key to 'authorized_keys' file" "SUCCESSFUL" +else + log "Adding SSH Key to 'authorized_keys' file" "FAILED" + finally "ATAF" + exit 1; +fi + +############################################################## +# Secure authorized_keys file +############################################################## +{ + log "Securing 'authorized_keys' file" + # Set appropriate permissions for ".ssh" dir and "authorized_key" file chown -R "$NORM_USER_NAME" "$SSH_DIR" && \ chgrp -R "$NORM_USER_NAME" "$SSH_DIR" && \ @@ -175,10 +281,9 @@ fi chattr +i "$SSH_DIR"/authorized_keys } if [[ $? -eq 0 ]]; then - printf "Successfully created SSH keys.\n%s" "${SSH_DIR}/${NORM_USER_NAME}".pem + log "Securing 'authorized_keys' file" "SUCCESSFUL" else - printf "Creating SSH key failed.\n" - exit 1; + log "Securing 'authorized_keys' file" "FAILED" fi @@ -186,9 +291,6 @@ fi # Enable SSH-only login ############################################################## -# Backup the sshd_config file -cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak || exit 1 - function config_search_regex(){ local search_key=$1 declare -i isCommented=$2 @@ -213,7 +315,6 @@ function config_search_regex(){ fi } - function set_config_key(){ local file_location=$1 local key=$2 @@ -266,19 +367,94 @@ function set_config_key(){ fi } -# Remove root login -set_config_key "/etc/ssh/sshd_config" "PermitRootLogin" "no" +{ + log "Enabling SSH-only login" -# Disable password login -set_config_key "/etc/ssh/sshd_config" "PasswordAuthentication" "no" + # Backup the sshd_config file + cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak || exit 1 -# Set SSH Authorization-Keys path -set_config_key "/etc/ssh/sshd_config" "AuthorizedKeysFile" '%h\/\.ssh\/authorized_keys' + # Remove root login + set_config_key "/etc/ssh/sshd_config" "PermitRootLogin" "no" + + # Disable password login + set_config_key "/etc/ssh/sshd_config" "PasswordAuthentication" "no" + + # Set SSH Authorization-Keys path + set_config_key "/etc/ssh/sshd_config" "AuthorizedKeysFile" '%h\/\.ssh\/authorized_keys' + + systemctl restart sshd +} +if [[ $? -eq 0 ]]; then + log "Enabling SSH-only login" "SUCCESSFUL" +else + log "Enabling SSH-only login" "FAILED" + finally "ESOL" + exit 1; +fi ############################################################## -# Enable SSH-only login +# Change default source-list ############################################################## -systemctl restart sshd +# Low priority - But what to do if it fails??? +log "Changing urls in sources.list to defaults" +mv /etc/apt/sources.list /etc/apt/sources.list.bak +sed -i "1,$(wc -l < /etc/apt/sources.list.bak) s/^/#/" /etc/apt/sources.list.bak + +# Default sources list for debian +cat < /etc/apt/sources.list || exit 1 +deb https://deb.debian.org/debian ${DEB_VER_STR} main +deb-src https://deb.debian.org/debian ${DEB_VER_STR} main + +## Major bug fix updates produced after the final release of the +## distribution. +deb http://security.debian.org ${DEB_VER_STR}/updates main +deb-src http://security.debian.org ${DEB_VER_STR}/updates main + +deb https://deb.debian.org/debian ${DEB_VER_STR}-updates main +deb-src https://deb.debian.org/debian ${DEB_VER_STR}-updates main + +deb https://deb.debian.org/debian ${DEB_VER_STR}-backports main +deb-src https://deb.debian.org/debian ${DEB_VER_STR}-backports main +TAG + +# Find any additional sources listed by the provider and comment them out +SOURCE_FILES=(/etc/apt/source*/*.list) +if [[ ${#SOURCE_FILES[@]} -gt 0 ]]; then + for file in "${SOURCE_FILES[@]}"; + do + mv "$file" "$file".bak + sed -i "1,$(wc -l < "$file") s/^/#/" "$file" >&2 /dev/null + done +fi + +# Comment out cloud-init generated templates for sources +CLOUD_INIT_FILES=(/etc/cloud/templates*/*.tmpl) +if [[ ${#CLOUD_INIT_FILES[@]} -gt 0 ]]; then + for file in "${CLOUD_INIT_FILES[@]}"; + do + mv "$file" "$file".bak + sed -i "1,$(wc -l < "$file") s/^/#/" "$file" >&2 /dev/null + done +fi + +if [[ $? -eq 0 ]]; then + log "Changing urls in sources.list to defaults" "FAILED" +else + log "Changing urls in sources.list to defaults" "FAILED" +fi + + +############################################################## +# Install required softwares +############################################################## +apt-get update && apt-get upgrade -y && apt-get install -y sudo curl screen + + +############################################################## +# Recap +############################################################## + +finally \ No newline at end of file