Skip to content

Instantly share code, notes, and snippets.

@shr00mie
Last active June 13, 2024 22:32
Show Gist options
  • Save shr00mie/dfe3be7b70df6459645612de1e610cac to your computer and use it in GitHub Desktop.
Save shr00mie/dfe3be7b70df6459645612de1e610cac to your computer and use it in GitHub Desktop.
Let's Encrypt SSL for ESXi
#!/bin/bash
#
## -----------------------------=[ WARNING ]=-------------------------------- ##
#
# This script is now woefully out of date due to which accounts ESXi allows to
# ssh into the box as well as sticky folders/file flags.
# I've since ported the whole thing to python with a lot of bells and whistles
# and if i get around to making it public, i'll put a link here.
#
## -------------------------------=[ Info ]=--------------------------------- ##
#
# Generate letsencrypt cert on local server and scp to esxi target.
# Designed and tested on Ubuntu 16.04LTS.
# Assumes you have upnp control over local network. Tested with Ubiquiti USG.
#
# Dependencies:
# miniupnpc (sudo apt install miniupnpc)
# certbot (sudo apt install certbot)
#
## -=[ Author ]=------------------------------------------------------------- ##
#
# shr00mie
# 9.21.2018
# v0.5
#
## -=[ Use Case ]=----------------------------------------------------------- ##
#
# Allows for the generation of certificates on a separate host which can then
# be securely copied to target esxi host.
#
## -=[ Breakdown ]=---------------------------------------------------------- ##
#
# 1. Prompt for esxi target FQDN, reminder email, and esxi admin username
# 2. Check if ssh keys exist for target.
# - If keys exist, continue.
# - If keys don't exist:
# - Silently generate 4096 RSA key, no passphrase, user@target as comment.
# - Add key to ssh-agent
# - Create target folder/file structure for scp automation
# - Restart SSH service on target.
# 3. Enable port forwarding.
# 4. Generate 4096 bit letsencrypt cert
# 5. Backup existing cert with datetime suffix
# 6. Copy cert to target
# 7. Restart target services
# 8. Remove port forwarding
#
## -=[ To-Do ]=-------------------------------------------------------------- ##
#
# change: PermitRootLogin yes -> PermitRootLogin no
# add: ChallengeResponseAuthentication no
# add: PasswordAuthentication no
#
## -=[ Functions ]=---------------------------------------------------------- ##
# Usage: status "Status Text"
function status() {
GREEN='\033[00;32m'
RESTORE='\033[0m'
echo -e "\n...${GREEN}$1${RESTORE}...\n"
}
# Usage: input "Prompt Text" "Variable Name"
function input() {
GREEN='\033[00;32m'
RESTORE='\033[0m'
echo -en "\n...${GREEN}$1${RESTORE}: "
read $2
echo -e ""
}
function pressanykey(){
GREEN='\033[00;32m'
RESTORE='\033[0m'
echo -en "\n...${GREEN}$1. Press any key to continue.${RESTORE}..."
read -r -p "" -n 1
}
## ---------------------------=[ Script Start ]=----------------------------- ##
# Importing Variables
status "Importing Variables"
# Read ESXiHost
input "Enter the FQDN for the certificate/host in host.domain.tld format" "ESXiHost"
# Read Email
input "Enter the email for confirmation & renewal notifications" "Email"
# Read ESXiUser
input "Enter ESXi target admin username" "ESXiUser"
# Prompt user to confirm/enable SSH on ESXi target
pressanykey "Confirm/Enable SSH access on $ESXiHost."
# Check for existing ssh keys for esxi host
status "Checking for existing ssh keys for $ESXiHost"
if [[ -e ~/.ssh/$ESXiHost'_rsa' ]]
then
status "Keys for $ESXiHost exist. Continuing"
else
status "Keys for $ESXiHost not found. Generating 4096 bit keys"
# Generate 4096 bit key for user@target
ssh-keygen -b 4096 -t rsa -f ~/.ssh/$ESXiHost'_rsa' -q -N "" -C "$ESXiUser@$HOSTNAME LetsEncrypt"
status "Adding new key to ssh-agent"
# Add key to agent
eval `ssh-agent` && ssh-add ~/.ssh/$ESXiHost'_rsa'
status "Configuring $ESXiHost for ssh access"
# Store key as variable
pubkey=`cat ~/.ssh/$ESXiHost'_rsa.pub'`
# Create directory for authorized user, copy key to target, set permissions,
# and restart ssh service on target.
ssh $ESXiUser@$ESXiHost "mkdir -p /etc/ssh/keys-$ESXiUser &&
echo $pubkey > /etc/ssh/keys-$ESXiUser/authorized_keys &&
chmod 700 -R /etc/ssh/keys-$ESXiUser &&
chmod 600 /etc/ssh/keys-$ESXiUser/authorized_keys &&
chown -R $ESXiUser /etc/ssh/keys-$ESXiUser &&
/etc/init.d/SSH restart"
fi
# Enable UPnP http(s) port forward for requesting device
status "Enabling http(s) port forwarding to client for letsencrypt verification"
upnpc -e "letsencrypt http" -r 80 tcp
upnpc -e "letsencrypt https" -r 443 tcp
# Acquire letsencrypt cert
status "Requesting 4096 bit certificate for $ESXiHost"
sudo certbot certonly --standalone --preferred-challenges tls-sni --agree-tos -m $Email -d $ESXiHost --rsa-key-size 4096
# Backup existing SSL components on ESXi target
status "Backing up existing certificates on $ESXiHost"
time=$(date +%Y.%m.%d_%H:%M:%S)
ssh $ESXiUser@$ESXiHost "cp /etc/vmware/ssl/castore.pem /etc/vmware/ssl/castore.pem.back.$time"
ssh $ESXiUser@$ESXiHost "cp /etc/vmware/ssl/rui.crt /etc/vmware/ssl/rui.crt.back.$time"
ssh $ESXiUser@$ESXiHost "cp /etc/vmware/ssl/rui.key /etc/vmware/ssl/rui.key.back.$time"
# Copy letsencrypt cert to ESXi target
status "Coping letsencrypt cert to $ESXiHost"
sudo scp /etc/letsencrypt/live/$ESXiHost/fullchain.pem $ESXiUser@$ESXiHost:/etc/vmware/ssl/castore.pem
sudo scp /etc/letsencrypt/live/$ESXiHost/cert.pem $ESXiUser@$ESXiHost:/etc/vmware/ssl/rui.crt
sudo scp /etc/letsencrypt/live/$ESXiHost/privkey.pem $ESXiUser@$ESXiHost:/etc/vmware/ssl/rui.key
# Restart services on ESXi target
status "Restarting services on $ESXiHost"
ssh $ESXiUser@$ESXiHost "services.sh restart"
# Disable UPnP http(s) port forward
status "Removing http(s) port forwarding"
upnpc -d 80 tcp
upnpc -d 443 tcp
# Prompt user to confirm/disable SSH on ESXi target
pressanykey "Remember to disable SSH service on $ESXiHost"
@PalmaSolutions
Copy link

Having to enable SSH access to an ESXi host which is publicly accessible is probably not that good of an idea. It'd be nice having a solution where we would not have to enable the SSH protocol. Especially because as of right now you would have to leave it enabled in order to update the certificates. Is there a way to do do this?

@shr00mie isn't forcing anyone to use this script on production, he just left a note. It's not a bad idea or a bad solution to have SSH open, only those who do not understand what's the purpose of SSH think so. ESXi has a firewall, you can keep SSH open and limit the access to specific IP's only. That doesn't make it public! Or you can change the port and keep it restricted, there are solutions to use SSH and be secure, if you understand what's the purpose of SSH and are not after one click solutions that you consider to be secure.

@shr00mie
Copy link
Author

shr00mie commented Jan 15, 2019

it's gives me the below error
letsencrypt_esxi.sh: line 50: syntax error: unexpected "("
any help?

@OmarElSergany

what os/environment are you running this from?

how are you saving/running/executing?

you could try dropping the ()s as they're not necessarily required given the use case.

@Conan179
Copy link

Kann man das Script auch auf DNS challenge umstellen?
Mein ESXi server ist nicht bei mir im Heimnetz sondern ist ein Rootserver bei einem großen Deutscher Server Vermieter.

@shr00mie
Copy link
Author

shr00mie commented May 7, 2019

for what it's worth, vmware changed which folders can be made sticky. i'll update the above script sometime this week to update as the way it is now will not persist through restarts.

@himslm01
Copy link

himslm01 commented Jul 28, 2019

ssh $ESXiUser@$ESXiHost "services.sh restart"

This line crashed the whole ESXi system, taking out all the VMs running on it. There was no console activity, I had to forcibly turn off and on the server.

@theazlan89
Copy link

Hello,

I'm not really familiar with scripting, may I know how to add this script? is it need to copy and paste into the CLI EXSI?

@shr00mie
Copy link
Author

shr00mie commented Nov 21, 2020

@theazlan89 this thing is super old. i've since ported the whole thing to python. what are you looking to do exactly? Just automate the upload and refresh of SSL cert on ESXi host?

right now i'm working with a traefik reverse proxy up front that keeps the letsencrypt cert up to date. every month i got a big ole python module that checks to see if the cert has been updated, and if it has, it grabs it, converts it to the required formats for stuff like ubiquiti and esxi, and then updates everything.

@theazlan89
Copy link

@theazlan89 this thing is super old. i've since ported the whole thing to python. what are you looking to do exactly? Just automate the upload and refresh of SSL cert on ESXi host?

right now i'm working with a traefik reverse proxy up front that keeps the letsencrypt cert up to date. every month i got a big ole python module that checks to see if the cert has been updated, and if it has, it grabs it, converts it to the required formats for stuff like ubiquiti and esxi, and then updates everything.

Yes sir, correct, im looking for to automate renewal on ESXI.

@codefriar
Copy link

@shr00mie - where can we find the python version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment