Instantly share code, notes, and snippets.

Embed
What would you like to do?
Let's Encrypt SSL for ESXi
#!/bin/bash
#
## -------------------------------=[ 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.4
#
## -=[ 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"
@AniiXx

This comment has been minimized.

AniiXx commented Apr 7, 2018

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?

@xrobau

This comment has been minimized.

xrobau commented Apr 20, 2018

https://wiki.9r.com.au/display/9R/LetsEncrypt+Certificates+for+vCenter+and+PSC automatically renews and updates your certificates, so you can shut down SSH after you've installed it.

@BitingChaos

This comment has been minimized.

BitingChaos commented Jul 19, 2018

Thank you! I had already started setting up a similar script when I started to Google around to see what others were doing. I have Let's Encrypt already configured to get certificates for other web servers, so my script looks similar to yours from just line 57 to 74.

Guest (VM):

  • Ubuntu 18.04 w/ working Let's Encrypt install.
  • A "copy-to-esxi1.sh" script that uses SSH/SCP to backup the remote ESXi keys, copy the local Let's Encrypt keys to the remote ESXi server, then restarts management services on the remote ESXi server.
  • The crontab is set up to run "copy-to-esxi1.sh" once a month, over night.

Host:

  • ESXi 6.5 w/ SSH enabled
  • I have Guest/VM's id_rsa.pub file copied to the ESXi server as /etc/ssh/keys-root/authorized_keys to enable password-less authentication for SSH/SCP.
@shr00mie

This comment has been minimized.

Owner

shr00mie commented Sep 21, 2018

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?

...your esxi host should never be publicly accessible. so you should probably work on that first.

this script is designed for homelab applications. enterprise users have vcenter solutions for this kinda crap. and ssh should be off at all times BUT FOR when you need to update the cert, and subsequently disabled. esxi client also keeps nagging if you have it enabled, so that's sort of on you if you leave it enabled...which again, shouldn't be that big of a deal considering you shouldn't have direct public access to your esxi host.

@shr00mie

This comment has been minimized.

Owner

shr00mie commented Sep 21, 2018

Thank you! I had already started setting up a similar script when I started to Google around to see what others were doing. I have Let's Encrypt already configured to get certificates for other web servers, so my script looks similar to yours from just line 57 to 74.

Guest (VM):

  • Ubuntu 18.04 w/ working Let's Encrypt install.
  • A "copy-to-esxi1.sh" script that uses SSH/SCP to backup the remote ESXi keys, copy the local Let's Encrypt keys to the remote ESXi server, then restarts management services on the remote ESXi server.
  • The crontab is set up to run "copy-to-esxi1.sh" once a month, over night.

Host:

  • ESXi 6.5 w/ SSH enabled
  • I have Guest/VM's id_rsa.pub file copied to the ESXi server as /etc/ssh/keys-root/authorized_keys to enable password-less authentication for SSH/SCP.

that's awesome. i don't have notifications enabled on my gists, so i had no idea anyone was seeing/using these. every so often, if i come up with something that i think is useful, i throw it up here in case it helps anyone else. figured people would add/improve as necessary. so far just saw a couple forks. someone on reddit asked about this use case, so i figured it was time to give the script a good once over and push an update.

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