#!/bin/bash
do {
	#////////////////////////////////////
	# DietPi Lets Encrypt
	#
	#////////////////////////////////////
	# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
	#
	#////////////////////////////////////
	#
	# Info:
	# - filename /DietPi/dietpi/dietpi-letsencrypt
	# - Menu Frontend for Letsencrypt with CLI options for use on DietPi systems.
	#
	# usage:
	# - /DietPi/dietpi/dietpi-letsencrypt   = Menu
	# - /DietPi/dietpi/dietpi-letsencrypt 1 = Create/Renew/Apply cert
	#////////////////////////////////////

	#Grab Input
	setvar INPUT = '0'
	if [[ $1 =~ ^-?[0-9]+$ ]] {
		setvar INPUT = "$1"
	}

	#Import DietPi-Globals ---------------------------------------------------------------
	source /DietPi/dietpi/func/dietpi-globals
	G_CHECK_ROOT_USER
	G_CHECK_ROOTFS_RW
	export G_PROGRAM_NAME='DietPi-Letsencrypt'
	#Import DietPi-Globals ---------------------------------------------------------------

	#/////////////////////////////////////////////////////////////////////////////////////
	#Globals
	#/////////////////////////////////////////////////////////////////////////////////////
	setvar DP_LOGFILE = ""/var/log/dietpi-letsencrypt.log""
	setvar DP_MONTHLY_CRON = ""/etc/cron.monthly/dietpi-letsencrypt""
	setvar DP_LETSENCRYPT_BINARY = ""/usr/bin/certbot""
	if (( $G_DISTRO < 4 )) {
		setvar DP_LETSENCRYPT_BINARY = ""/etc/certbot_scripts/certbot-auto""
	}
	setvar DP_WEBSERVER_INDEX = '0' #0=apache2 1=lighttpd 2=nginx 3=minio

	setvar LETSENCRYPT_INSTALLED = '0'
	if test -f $DP_LETSENCRYPT_BINARY {
		setvar LETSENCRYPT_INSTALLED = '1'
	}
	setvar LETSENCRYPT_DOMAIN = ""mydomain.com""
	setvar LETSENCRYPT_EMAIL = ""myemail@email.com""
	setvar LETSENCRYPT_REDIRECT = '0'
	setvar LETSENCRYPT_AUTORENEW = '0'
	setvar LETSENCRYPT_KEYSIZE = '4096'

	proc Run_Lets_Encrypt {

		G_DIETPI-NOTIFY 3 $PROGRAM_NAME "Running cert"

		#Conditions that must be met before allowing run
		local run_conditions_met=1

		/DietPi/dietpi/dietpi-services start

		# - Obtain installed and running webserver index
		if (( $(ps aux | grep -ci -m1 '[a]pache') )) {

			setvar DP_WEBSERVER_INDEX = '0'
			G_DIETPI-NOTIFY 0 "Apache2 webserver detected"
			if (( $G_DISTRO >= 4 )) {
				setvar DP_LETSENCRYPT_BINARY = ""$DP_LETSENCRYPT_BINARY --apache""
			}

		} elif (( $(ps aux | grep -ci -m1 '[l]ighttpd') )) {

			setvar DP_WEBSERVER_INDEX = '1'
			G_DIETPI-NOTIFY 0 "Lighttpd webserver detected"

		} elif (( $(ps aux | grep -ci -m1 '[n]ginx') )) {

			setvar DP_WEBSERVER_INDEX = '2'
			G_DIETPI-NOTIFY 0 "Nginx webserver detected"
			if (( $G_DISTRO >= 4 )) {
				setvar DP_LETSENCRYPT_BINARY = ""$DP_LETSENCRYPT_BINARY --nginx""
			}

		} elif (( $(ps aux | grep -ci -m1 '[m]inio') )) {

			setvar DP_WEBSERVER_INDEX = '3'
			G_DIETPI-NOTIFY 0 "Minio S3 server detected"

		} else {

			setvar run_conditions_met = '0'

		}

		#Failed. No compatible webserver is currently running
		if (( ! $run_conditions_met )) {

			echo -e "Error: No compatible and/or active webserver was found. Aborting." >> "$DP_LOGFILE"
			if (( $INPUT == 0 )) {

				whiptail --title "Error" --msgbox "Error: No compatible and/or active webserver was found. Aborting." --backtitle $PROGRAM_NAME 8 60

			}

		#Cert up
		} else {

			#------------------------------------------------------------------------------------------------------
			#apache2
			if (( $DP_WEBSERVER_INDEX == 0 )) {

				local dp_defaultsite="/etc/apache2/sites-available/000-default.conf"

				#Add ServerName if it doesnt exist. This is required to prevent letsencrypt compaining about vhost with no domain.
				if (( ! $(cat "$dp_defaultsite" | grep -ci -m1 'ServerName') )) {

					sed -i "/ServerAdmin /a ServerName" $dp_defaultsite

					#log
					echo -e "ServerName entry not found in $dp_defaultsite. Adding it now." >> "$DP_LOGFILE"

				}

				#Apply domain name
				sed -i "/ServerName/c\        ServerName $LETSENCRYPT_DOMAIN" $dp_defaultsite

				#Restart apache2 to apply ServerName changes.
				systemctl restart apache2

				local cli_redirect="--no-redirect"
				if (( $LETSENCRYPT_REDIRECT )) {

					setvar cli_redirect = ""--redirect""

				}

				#Cert me up Apache2
				$DP_LETSENCRYPT_BINARY --duplicate --agree-tos $cli_redirect --rsa-key-size $LETSENCRYPT_KEYSIZE --email $LETSENCRYPT_EMAIL -d $LETSENCRYPT_DOMAIN

			#------------------------------------------------------------------------------------------------------
			#Lighttpd
			} elif (( $DP_WEBSERVER_INDEX == 1 )) {

				# - Cert me up
				/DietPi/dietpi/dietpi-services stop

				$DP_LETSENCRYPT_BINARY certonly --standalone --duplicate --agree-tos $cli_redirect --rsa-key-size $LETSENCRYPT_KEYSIZE --email $LETSENCRYPT_EMAIL -d $LETSENCRYPT_DOMAIN

				# - Create combined key
				cd /etc/letsencrypt/live/"$LETSENCRYPT_DOMAIN"
				cat privkey.pem cert.pem > combined.pem

				cat <<< """ > /etc/lighttpd/conf-enabled/letsencrypt.conf
'$'SERVER["socket"] == ":443" {
		ssl.engine = "enable"
		ssl.pemfile = "/etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/combined.pem"
		ssl.ca-file =  "/etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/fullchain.pem"
		#ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
		ssl.cipher-list = "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS"
		ssl.honor-cipher-order = "enable"
		ssl.use-sslv2 = "disable"
		ssl.use-sslv3 = "disable"
}
"""
> /etc/lighttpd/conf-enabled/letsencrypt.conf
\$SERVER["socket"] == ":443" {
		ssl.engine = "enable"
		ssl.pemfile = "/etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/combined.pem"
		ssl.ca-file =  "/etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/fullchain.pem"
		#ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
		ssl.cipher-list = "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS"
		ssl.honor-cipher-order = "enable"
		ssl.use-sslv2 = "disable"
		ssl.use-sslv3 = "disable"
}
_EOF_

				#Redirect
				rm /etc/lighttpd/conf-enabled/redirect.conf
				if (( $LETSENCRYPT_REDIRECT )) {

					cat <<< """ > /etc/lighttpd/conf-enabled/redirect.conf
'$'HTTP["scheme"] == "http" {
	# capture vhost name with regex conditiona -> %0 in redirect pattern
	# must be the most inner block to the redirect rule
	'$'HTTP["host"] =~ ".*" {
		url.redirect = (".*" => "https://%0'$'0")
	}
}
"""
> /etc/lighttpd/conf-enabled/redirect.conf
\$HTTP["scheme"] == "http" {
	# capture vhost name with regex conditiona -> %0 in redirect pattern
	# must be the most inner block to the redirect rule
	\$HTTP["host"] =~ ".*" {
		url.redirect = (".*" => "https://%0\$0")
	}
}
_EOF_

				}

				/etc/init.d/lighttpd force-reload


			#------------------------------------------------------------------------------------------------------
			# Nginx

			} elif (( $DP_WEBSERVER_INDEX == 2 )) {

				local nginx_defaultsite="/etc/nginx/sites-available/default"

				# Apply domain name
				sed -i "/server_name/c\        server_name $LETSENCRYPT_DOMAIN;" $nginx_defaultsite

				#Restart nginx to apply ServerName changes.
				systemctl restart nginx

				local cli_redirect="--no-redirect"

				if (( $LETSENCRYPT_REDIRECT )) {

					setvar cli_redirect = ""--redirect""

				}

				#Cert me up Nginx
				$DP_LETSENCRYPT_BINARY --duplicate --agree-tos $cli_redirect --rsa-key-size $LETSENCRYPT_KEYSIZE --email $LETSENCRYPT_EMAIL -d $LETSENCRYPT_DOMAIN


			#------------------------------------------------------------------------------------------------------
			#Minio
			} elif (( $DP_WEBSERVER_INDEX == 3 )) {
				# - Cert me up
				/DietPi/dietpi/dietpi-services stop

				$DP_LETSENCRYPT_BINARY certonly --standalone --preferred-challenges tls-sni --staple-ocsp --agree-tos $cli_redirect --rsa-key-size $LETSENCRYPT_KEYSIZE --email $LETSENCRYPT_EMAIL -d $LETSENCRYPT_DOMAIN

				# Locate them correctly (THIS didn't work as symlinks)
				cp /etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/fullchain.pem /home/minio-user/.minio/certs/public.crt
				cp /etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/privkey.pem /home/minio-user/.minio/certs/private.key

				# Own those certs!
				chown minio-user:minio-user /home/minio-user/.minio/certs/public.crt
				chown minio-user:minio-user /home/minio-user/.minio/certs/private.key

				# Add SSL to config file
				grep -v "MINIO_OPTS" /etc/default/minio > /etc/default/minio.temp1
				grep -v "port" /etc/default/minio.temp1 > /etc/default/minio.temp2
				rm /etc/default/minio.temp1
				mv /etc/default/minio.temp2 /etc/default/minio
				cat <<< """ >> /etc/default/minio
# Use if you want to run Minio on a custom port.
MINIO_OPTS="--address :443"
"""
>> /etc/default/minio
# Use if you want to run Minio on a custom port.
MINIO_OPTS="--address :443"
_EOF_

				# Allow SSL binding for non root user
				setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/minio

				# Create renewl script
				cat <<< """ > /home/minio-user/.minio/dietpi-cert-renewl.sh
# Minio only works with copied and owned certs. Upon renewal the new certs needs to be copied and re-owned
systemctl stop minio.service

# Copy to correct Location
cp /etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/fullchain.pem /home/minio-user/.minio/certs/public.crt
cp /etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/privkey.pem /home/minio-user/.minio/certs/private.key

# Re-Own those certs!
chown minio-user:minio-user /home/minio-user/.minio/certs/public.crt
chown minio-user:minio-user /home/minio-user/.minio/certs/private.key

systemctl start minio.service
"""
> /home/minio-user/.minio/dietpi-cert-renewl.sh
# Minio only works with copied and owned certs. Upon renewal the new certs needs to be copied and re-owned
systemctl stop minio.service

# Copy to correct Location
cp /etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/fullchain.pem /home/minio-user/.minio/certs/public.crt
cp /etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/privkey.pem /home/minio-user/.minio/certs/private.key

# Re-Own those certs!
chown minio-user:minio-user /home/minio-user/.minio/certs/public.crt
chown minio-user:minio-user /home/minio-user/.minio/certs/private.key

systemctl start minio.service
_EOF_

			# Change permissions on renewal script
			chmod +x /home/minio-user/.minio/dietpi-cert-renewl.sh
			}


			#------------------------------------------------------------------------------------------------------
			#ALL | Create cron job
			if (( $LETSENCRYPT_AUTORENEW && $G_DISTRO < 4 )) {

				cat <<< """ > "$DP_MONTHLY_CRON"
#!/bin/bash
{
	#////////////////////////////////////
	# DietPi-LetsEncrypt Autorenew script
	#
	#////////////////////////////////////
	#
	# Info:
	# - Location $DP_MONTHLY_CRON
	#
	#////////////////////////////////////

	#----------------------------------------------------------------
	# Main Loop
	#----------------------------------------------------------------
	/DietPi/dietpi/dietpi-letsencrypt 1 &>> $DP_LOGFILE

	# Minio specific applications
	if (( $(ps aux | grep -ci -m1 '[m]inio') )); then
		/home/minio-user/.minio/dietpi-cert-renewl.sh
	fi

	#----------------------------------------------------------------
	exit
	#----------------------------------------------------------------
}
"""
> "$DP_MONTHLY_CRON"
#!/bin/bash
{
	#////////////////////////////////////
	# DietPi-LetsEncrypt Autorenew script
	#
	#////////////////////////////////////
	#
	# Info:
	# - Location $DP_MONTHLY_CRON
	#
	#////////////////////////////////////

	#----------------------------------------------------------------
	# Main Loop
	#----------------------------------------------------------------
	/DietPi/dietpi/dietpi-letsencrypt 1 &>> $DP_LOGFILE

	# Minio specific applications
	if (( $(ps aux | grep -ci -m1 '[m]inio') )); then
		/home/minio-user/.minio/dietpi-cert-renewl.sh
	fi

	#----------------------------------------------------------------
	exit
	#----------------------------------------------------------------
}
_EOF_
				chmod +x $DP_MONTHLY_CRON

			}

			if (( $INPUT == 0 )) {

				echo -e ""
				read -p "Press any key to continue..."
				echo -e ""

			}

			#Restart services
			/DietPi/dietpi/dietpi-services restart

		}

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Settings File
	#/////////////////////////////////////////////////////////////////////////////////////
	setvar DP_SETTINGS = ""/DietPi/dietpi/.dietpi-letsencrypt""

	proc Read_Settings_File {

		local sed_index=1

		setvar LETSENCRYPT_DOMAIN = $(sed -n "$sed_index"p $DP_SETTINGS);((sed_index++))
		setvar LETSENCRYPT_EMAIL = $(sed -n "$sed_index"p $DP_SETTINGS);((sed_index++))
		setvar LETSENCRYPT_REDIRECT = $(sed -n "$sed_index"p $DP_SETTINGS);((sed_index++))
		setvar LETSENCRYPT_AUTORENEW = $(sed -n "$sed_index"p $DP_SETTINGS);((sed_index++))
		setvar LETSENCRYPT_KEYSIZE = $(sed -n "$sed_index"p $DP_SETTINGS);((sed_index++))

	}

	proc Write_Settings_File {

		cat <<< """ > "$DP_SETTINGS"
$LETSENCRYPT_DOMAIN
$LETSENCRYPT_EMAIL
$LETSENCRYPT_REDIRECT
$LETSENCRYPT_AUTORENEW
$LETSENCRYPT_KEYSIZE
"""
> "$DP_SETTINGS"
$LETSENCRYPT_DOMAIN
$LETSENCRYPT_EMAIL
$LETSENCRYPT_REDIRECT
$LETSENCRYPT_AUTORENEW
$LETSENCRYPT_KEYSIZE
_EOF_

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# MENUS
	#/////////////////////////////////////////////////////////////////////////////////////
	setvar PROGRAM_NAME = ""DietPi-LetsEncrypt""

	setvar CHOICE = '0'
	setvar OPTION = '0'
	setvar TARGETMENUID = '0'
	setvar PREVIOUS_MENU_SELECTION = """"

	proc Menu_Exit {

		whiptail --title "Exit $PROGRAM_NAME?" --yesno "Exit $PROGRAM_NAME?" --backtitle $PROGRAM_NAME --yes-button "Ok" --no-button "Back" --defaultno 9 55
		setvar CHOICE = ""$?
		if (( $CHOICE == 0 )) {
			#exit
			setvar TARGETMENUID = '-1'
		} else {
			#Return to Main Menu
			setvar TARGETMENUID = '0'
		}
	}

	#TARGETMENUID=0
	proc Menu_Main {

		local auto_renew_text="Disabled | Manual renewal every 90 days"
		if (( $LETSENCRYPT_AUTORENEW )) {
			setvar auto_renew_text = ""Enabled | Automatic cron.monthly renewals""
		}

		local redirect_text="Disabled | Allows http and https usage"
		if (( $LETSENCRYPT_REDIRECT )) {
			setvar redirect_text = ""Enabled | Forces http redirects to https""
		}

		setvar OPTION = $(whiptail --title "$PROGRAM_NAME" --menu "Please select a option." --cancel-button "Exit" --default-item "$PREVIOUS_MENU_SELECTION" --backtitle "$PROGRAM_NAME" 14 70 6 \
		"Domain" ": $LETSENCRYPT_DOMAIN" \
		"Email" ": $LETSENCRYPT_EMAIL" \
		"Redirect" ": $redirect_text" \
		"Auto Renew" ": $auto_renew_text" \
		"Key Size" ": $LETSENCRYPT_KEYSIZE" \
		"Apply" "Runs Lets Encrypt with your chosen options." 3>&1 1>&2 2>&3)

		setvar CHOICE = ""$?
		if (( $CHOICE == 0 )) {

			setvar PREVIOUS_MENU_SELECTION = "$OPTION"

			case (OPTION) {
				Domain {
					setvar LETSENCRYPT_DOMAIN = "$(Input_Box $LETSENCRYPT_DOMAIN Website-Domain)"
				}
				Email {
					setvar LETSENCRYPT_EMAIL = "$(Input_Box $LETSENCRYPT_EMAIL Email-Address)"
				}
				"Key Size" {
					if (( $LETSENCRYPT_KEYSIZE == 2048 )) {
						setvar LETSENCRYPT_KEYSIZE = '4096'
					} else {
						setvar LETSENCRYPT_KEYSIZE = '2048'
					}
				}
				"Auto Renew" {
					((LETSENCRYPT_AUTORENEW++))
					if (( $LETSENCRYPT_AUTORENEW > 1 )) {
						setvar LETSENCRYPT_AUTORENEW = '0'
					}
				}
				Redirect {
					((LETSENCRYPT_REDIRECT++))
					if (( $LETSENCRYPT_REDIRECT > 1 )) {
						setvar LETSENCRYPT_REDIRECT = '0'
					}
				}
				Apply {
					whiptail --title "Run Lets Encrypt?" --yesno "LetsEncrypt will now be run. This will:\n- Create your free SSL cert.\n- Automatically apply and enable your SSL cert\n- NB: This process can take a long time, please be patient.\n\nWould you like to continue?" --backtitle $PROGRAM_NAME --yes-button "Ok" --no-button "Back" --defaultno 13 65
					setvar CHOICE = ""$?
					if (( $CHOICE == 0 )) {
						Write_Settings_File
						Run_Lets_Encrypt
					}
				}
			}

		} else {
			#Exit
			Menu_Exit
		}

	}

	proc Input_Box {

		local input_value=$1
		local input_desc=$2

		setvar OPTION = $(whiptail --inputbox "Please enter your $input_desc" 9 50 "$input_value" --title "Input $input_desc" 3>&1 1>&2 2>&3)
		setvar CHOICE = ""$?
		if (( $CHOICE == 0 )) {
			setvar input_value = "$OPTION"
			# - Prevent null values
			if test -z $input_value {
				setvar input_value = ''NULL''
			}
		}
		echo -e $input_value

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Main Loop
	#/////////////////////////////////////////////////////////////////////////////////////
	#Load Settings file. Generate if required.
	if test ! -f $DP_SETTINGS {

		Write_Settings_File

	} else {

		Read_Settings_File

	}

	#-----------------------------------------------------------------------------------
	#Check installed
	if (( ! $LETSENCRYPT_INSTALLED )) {

		#Menu
		if (( $INPUT == 0 )) {

			G_DIETPI-NOTIFY 1 "Certbot binary not found ( $DP_LETSENCRYPT_BINARY )"
			G_DIETPI-NOTIFY 2 "Please install Certbot with DietPi-Software before running this program."
			read -p "Press any key to continue....."

		} else {

			echo -e "Error: Letsencrypt binary not installed ( $DP_LETSENCRYPT_BINARY )." >> "$DP_LOGFILE"

		}

	#-----------------------------------------------------------------------------------
	#Menu
	} elif (( $INPUT == 0 )) { {

			#Clear Screen buffer
			clear

			if (( $TARGETMENUID == 0 )) {

				Menu_Main

			}

		}

	#-----------------------------------------------------------------------------------
	#Run
	} elif (( $INPUT == 1 )) {

		Run_Lets_Encrypt

	}

	#-----------------------------------------------------------------------------------
	exit
	#-----------------------------------------------------------------------------------
}