Skip to content

Instantly share code, notes, and snippets.

@robbiet480
Last active July 23, 2018 23:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robbiet480/fee60c5eec7bcfb31970fac4f8efb6ff to your computer and use it in GitHub Desktop.
Save robbiet480/fee60c5eec7bcfb31970fac4f8efb6ff to your computer and use it in GitHub Desktop.
A script to install Lets Encrypt certificates generated by Dehydrated into FreeNAS
#!/usr/local/bin/python
"""
Import and activate a SSL/TLS certificate generated by dehydrated.sh into FreeNAS 11.1 or later
Uses the FreeNAS API to make the change, so everything's properly saved
in the config database and captured in a backup.
Requires paths to the cert (including the any intermediate CA certs) and
private key, and username, password, and FQDN of your FreeNAS system.
Your private key should only be readable by root, so this script must run
with root privileges. And, since it contains your root password,
this script itself should only be readable by root.
Add `export FREENAS_PASSWORD="<YOUR_FREENAS_ROOT_PASSWORD>"` to
dehydrated's config.
Original source: https://github.com/danb35/deploy-freenas
Modifications by https://github.com/robbiet480
"""
import os
import sys
import json
import requests
import subprocess
from datetime import datetime
now = datetime.now()
cert = "letsencrypt-{}".format(now.strftime("%Y-%m-%d"))
def deploy_cert(args):
if "FREENAS_PASSWORD" not in os.environ:
print("FREENAS_PASSWORD not set!")
sys.exit(1)
domain = args[0]
keyfile = args[1]
certfile = args[2]
fullchainfile = args[3]
chainfile = args[4]
timestamp = args[5]
s = requests.Session()
s.auth = ("root", os.environ["FREENAS_PASSWORD"])
# Load cert/key
with open(keyfile, "r") as file:
priv_key = file.read()
with open(fullchainfile, "r") as file:
full_chain = file.read()
# Update or create certificate
r = s.post(
"https://" + domain + "/api/v1.0/system/certificate/import/",
headers={"Content-Type": "application/json"},
data=json.dumps({"cert_name": cert,
"cert_certificate": full_chain,
"cert_privatekey": priv_key})
)
if r.status_code == 201:
print("Certificate import successful")
else:
print("Error importing certificate!")
print(r)
print(r.json())
sys.exit(1)
# Download certificate list
# set limit to 0 to disable paging in the event of many certificates
r = s.get("https://" + domain + "/api/v1.0/system/certificate/",
params={"limit": 0})
if r.status_code == 200:
print("Certificate list successful")
else:
print("Error listing certificates!")
print(r)
print(r.json())
sys.exit(1)
# Parse certificate list to find the id that matches our cert name
cert_list = r.json()
for index in range(100):
cert_data = cert_list[index]
if cert_data["cert_name"] == cert:
cert_id = cert_data["id"]
break
# Set our cert as active
r = s.put("https://" + domain + "/api/v1.0/system/settings/",
headers={"Content-Type": "application/json"},
data=json.dumps({"stg_guicertificate": cert_id}))
if r.status_code == 200:
print("Setting active certificate successful")
else:
print("Error setting active certificate!")
print(r)
print(r.json())
sys.exit(1)
# Reload nginx with new cert
restart_path = "/api/v1.0/system/settings/restart-httpd-all/"
r = s.post("https://{}{}".format(domain, restart_path))
if r.status_code == 200:
print("Restarted the web servers")
else:
print("Error restarting the web servers!")
print(r)
print(r.json())
sys.exit(1)
def main(argv):
ops = {"deploy_cert": deploy_cert}
if argv[0] in ops:
print(" + FreeNAS hook executing: {0}".format(argv[0]))
ops[argv[0]](argv[1:])
if __name__ == "__main__":
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment