Advertisement
SimonBlandfordOP

ispconfig_letsencrypt

Jul 4th, 2016
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 9.20 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. #The MIT License (MIT)
  4. #Copyright (c) 2016 Simon Blandford
  5.  
  6. #Letsencrypt and ISPConfig 3 integration script
  7.  
  8. #######################################################################################################################
  9. #$REMOTE_USER_CONF file contains following entries...
  10. # DEBUG="no"
  11. # ADMINEMAIL="<email for letsencrypt registration>"
  12. # REMOTE_USER_USERNAME="<ispconfig remote_user name"
  13. # REMOTE_USER_PASSWORD="<ispconfig remote user password"
  14. # ISPCONFIG_CONF="<path to>/config.inc.php"
  15. #######################################################################################################################
  16. # /etc/cron.d/ispconfig_letsencrypt entries: (change 18 2 to any random minute/hour of the day)
  17. # Must run as root to be able to access letsencrypt directories
  18. # * * * * * root /usr/local/bin/ispconfig_letsencrypt minute >/dev/null
  19. # 18 2 * * * root /usr/local/bin/ispconfig_letsencrypt day >/dev/null
  20.  
  21. #######################################################################################################################
  22. #How to use:
  23. # Insert one of three keywords in ISPConfig web domain SSL form "SSL key" and "SSK Certificate" files:
  24. # auto: Generates a new cert from letsencrypt
  25. # revoke: Revokes and delets a letsencrypt cert
  26. # refresh: Refreshes (re-establishes) ISPConfig with existing letsencrypt cert
  27.  
  28. #Do not select and SSL action, just press Save. Then wait a few minute for the magic to happen
  29.  
  30. #######################################################################################################################
  31.  
  32.  
  33. REMOTE_USER_CONF="/usr/local/etc/ispconfig_letsencrypt.conf"
  34. LETSENCRYPT="/usr/local/bin/certbot-auto"
  35. source "$REMOTE_USER_CONF"
  36.  
  37. logecho () {
  38.   echo "$1"
  39.   logger -t "$this" "$1"
  40. }
  41.  
  42. get_db_param () {
  43.   grep -E "conf\['$1'\][[:space:]]*=" "$ISPCONFIG_CONF" | cut -f 2 -d "=" | tr -d "'\"; "
  44. }
  45.  
  46. get_db_params () {
  47.   db_database=$( get_db_param "db_database" )
  48.   db_user=$( get_db_param "db_user" )
  49.   db_password=$( get_db_param "db_password" )
  50. }
  51.  
  52. get_db_field () {
  53.   local domain key
  54.   domain=$1
  55.   key=$2
  56.  
  57.   echo "<?php \$link=mysql_connect('localhost','$db_user','$db_password');
  58.        mysql_select_db('$db_database', \$link);
  59.        echo mysql_fetch_assoc(mysql_query(\"select $key from web_domain where domain = '$domain'\"))['$key'];
  60.        mysql_close(\$link);
  61.        ?>" | php  
  62. }
  63.  
  64. get_db_domains () {
  65.   local key value
  66.   key=$1
  67.   value=$2
  68.  
  69.   echo "<?php \$i=0; \$link=mysql_connect('localhost','$db_user','$db_password');
  70.        mysql_select_db('$db_database', \$link); \$result=mysql_query(\"select domain from web_domain where $key = '$value'\");
  71.        while ( \$domain=mysql_fetch_assoc(\$result)['domain']) { if (\$i++ >0) { echo \"\n\"; };
  72.        echo \$domain;};
  73.        mysql_close(\$link);
  74.        ?>" | php  
  75. }
  76.  
  77. set_ssl () {
  78.   local domain cert key enabled php_code webroot domain_id
  79.   domain=$1
  80.   cert=$2
  81.   key=$3
  82.   enabled=$4
  83.  
  84.   domain_id=$( get_db_field "$domain" "domain_id" )
  85.   if [[ ! "$domain_id" =~ ^[0-9]+$ ]]; then
  86.     echolog "Unable to find domain ID for $domain" >&2
  87.     return 1
  88.   fi
  89.  
  90.   php_code_db="<?php \$link=mysql_connect('localhost','$db_user','$db_password');
  91.                mysql_select_db('dbispconfig', \$link);
  92.                mysql_query(\"update web_domain set
  93.                ssl_request = '',
  94.                ssl_cert    = '$cert',
  95.                ssl_bundle  = '',
  96.                ssl_key     = '$key',
  97.                \`ssl\`     = '$enabled'
  98.                where domain  = '$domain'\");
  99.                mysql_close(\$link);
  100.                ?>"
  101.   php_code_api="<?php
  102.                \$username = 'ssl';
  103.                \$password = 'A9#VUrywSikF';
  104.                \$soap_location = 'https://localhost:8443/remote/index.php';
  105.                \$soap_uri = 'https://localhost:8443/remote/';
  106.                \$client = new SoapClient(null, array('location' => \$soap_location,
  107.                          'uri'      => \$soap_uri,
  108.                          'trace' => 1,
  109.                          'exceptions' => 1));
  110.                try {
  111.                  \$session_id = \$client->login(\$username, \$password);
  112.                  \$client_id = 0;
  113.                  \$domain_record = \$client->sites_web_domain_get(\$session_id, $domain_id);
  114.                  \$domain_record['ssl'] = 'y';
  115.                  \$domain_record['ssl_request'] = '';
  116.                  \$domain_record['ssl_cert'] = '$cert';
  117.                  \$domain_record['ssl_bundle'] = '';
  118.                  \$domain_record['ssl_key'] = '$key';
  119.                  \$domain_record['ssl'] = '$enabled';
  120.                  \$domain_record['ssl_action'] = 'save';
  121.                  \$client->sites_web_domain_update(\$session_id, \$client_id, $domain_id, \$domain_record);
  122.                  \$client->logout(\$session_id);
  123.                } catch (SoapFault \$e) {
  124.                  echo \$client->__getLastResponse();
  125.                  die('SOAP Error: '.\$e->getMessage());
  126.                } ?>"
  127.                
  128.   if [[ "$DEBUG" == "yes" ]]; then
  129.     echo "$php_code_db"
  130.     echo "$php_code_api"
  131.   else
  132.     #Paste in values into UI
  133.     echo "$php_code_db" | php
  134.     #Actually action values via API
  135.     echo "$php_code_api" | php
  136.   fi
  137. }
  138.  
  139.  
  140. scrub_domain () {
  141.   local domain
  142.   domain=$1
  143.  
  144.   if [[ "$DEBUG" == "yes" ]]; then
  145.     echo "$LETSENCRYPT revoke --cert-path \"/etc/letsencrypt/live/""$domain""/cert.pem\" 2>&1 | logger -t \"$this\""
  146.   else
  147.     $LETSENCRYPT revoke --cert-path "/etc/letsencrypt/live/""$domain""/cert.pem" 2>&1 | logger -t "$this"
  148.     rm -rf "/etc/letsencrypt/archive/""$domain"
  149.     rm -rf "/etc/letsencrypt/live/""$domain"
  150.     rm -f "/etc/letsencrypt/renewal/""$domain"".conf"
  151.   fi
  152. }
  153.  
  154. unset changes
  155. this=$( basename "$0" )
  156. mode=$1
  157.  
  158. if [ ! -x "$LETSENCRYPT" ]; then
  159.   logecho "Unable to find certbot-auto command: $ISPCONFIG" >&2
  160.   exit 1
  161. fi
  162.  
  163. if [ ! -f "$ISPCONFIG_CONF" ]; then
  164.   logecho "Unable to find ISPConfig config file: $ISPCONFIG" >&2
  165.   exit 1
  166. fi
  167.  
  168. get_db_params
  169.  
  170. if [[ "$mode" == "minute" ]]; then
  171.  
  172.   echo "Minute mode"
  173.  
  174.   #Find any auto SSL requests
  175.   new_requests=$( ( get_db_domains "ssl_key" "auto"; echo; get_db_domains "ssl_cert" "auto" ) | sort | uniq )
  176.  
  177.   for domain in $( echo "$new_requests" ); do
  178.     #Delete old domain if there is one
  179.     if [ -d "/etc/letsencrypt/live/""$domain" ]; then
  180.       scrub_domain "$domain"
  181.     fi
  182.  
  183.     webroot=$( get_db_field "$domain" "document_root" )
  184.     if [[ "$DEBUG" == "yes" ]]; then
  185.       echo "$LETSENCRYPT certonly -m "$ADMINEMAIL" --webroot -w \"$webroot""/web\" -d \"$domain\" 2>&1 | logger -t \"$this\""
  186.     else
  187.       if $LETSENCRYPT certonly -m "$ADMINEMAIL" --webroot -w "$webroot""/web" -d "$domain" 2>&1 | logger -t "$this"; then
  188.         logecho "Deploying new cert for $domain"
  189.         set_ssl "$domain" "$( cat "/etc/letsencrypt/live/""$domain""/cert.pem" )" "$( cat "/etc/letsencrypt/live/""$domain""/privkey.pem" )" "y"
  190.       else
  191.         logecho "Cert deployment or $domain failed"
  192.         set_ssl "$domain" "" "" "n"
  193.       fi
  194.     fi
  195.   done
  196.  
  197.   #Find any auto SSL revokes
  198.   new_revokes=$( ( get_db_domains "ssl_key" "revoke"; echo; get_db_domains "ssl_cert" "revoke" ) | sort | uniq )
  199.   for domain in $( echo "$new_revokes" ); do
  200.     logecho "Revoking cert for $domain"
  201.     if [ -d "/etc/letsencrypt/live/""$domain" ]; then
  202.       scrub_domain "$domain"
  203.     fi
  204.     set_ssl "$domain" "" "" "n"
  205.   done
  206.  
  207.   #find any auto SSL refreshes
  208.   new_refreshes=$( ( get_db_domains "ssl_key" "refresh"; echo; get_db_domains "ssl_cert" "refresh" ) | sort | uniq )
  209.   for domain in $( echo "$new_refreshes" ); do
  210.     if [ -d "/etc/letsencrypt/live/""$domain" ]; then
  211.       logecho "Refreshing cert for $domain"
  212.       set_ssl "$domain" "$( cat "/etc/letsencrypt/live/""$domain""/cert.pem" )" "$( cat "/etc/letsencrypt/live/""$domain""/privkey.pem" )" "y"
  213.     else
  214.       logecho "No cert found for $domain so clearing"
  215.       set_ssl "$domain" "" "" "n"
  216.     fi
  217.   done
  218. fi
  219.  
  220. if [[ "$mode" == "day" ]]; then
  221.   #Renew any certs and report
  222.   if [[ $DEBUG == "yes" ]]; then
  223.     echo "Renewal check suppressed"
  224.   else
  225.     renew_report=$( $LETSENCRYPT renew --noninteractive 2>&1 )
  226.     if ! echo "$renew_report" | grep -q "No renewals were attempted"; then
  227.       echo "$renew_report" | logger -t "$this"
  228.       changes=1
  229.     fi
  230.   fi
  231.   #Enact any changes
  232.   domain_list=$( ls -d /etc/letsencrypt/live/* | grep -Eo "[^\/]+$" )
  233.   for domain in $( echo "$domain_list" ); do
  234.     #Remove domains of sites that have disappeared
  235.     if [ ! -d "/var/www/""$domain""/ssl" ]; then
  236.       logecho "$domain is removed so revoking old cert"
  237.       scrub_domain "$domain"
  238.       continue
  239.     fi
  240.    
  241.     #Rewrite
  242.     if [ $changes ]; then
  243.       old_cert=$( get_db_field "$domain" "ssl_cert" )
  244.       old_key=$( get_db_field "$domain" "ssl_key" )
  245.       if ! echo "$old_cert" | cmp -s "/etc/letsencrypt/live/""$domain""/cert.pem" || ! echo "$old_key" | cmp -s "/etc/letsencrypt/live/""$domain""/privkey.pem"; then
  246.         logecho "Updating $domain with new cert"
  247.         set_ssl "$domain" "$( cat "/etc/letsencrypt/live/""$domain""/cert.pem" )" "$( cat "/etc/letsencrypt/live/""$domain""/privkey.pem" )" "y"
  248.       fi
  249.     fi
  250.   done
  251. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement