ssh.sh 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #!/usr/bin/env sh
  2. # Script to deploy certificates to remote server by SSH
  3. # Note that SSH must be able to login to remote host without a password...
  4. # SSH Keys must have been exchanged with the remote host. Validate and
  5. # test that you can login to USER@SERVER from the host running acme.sh before
  6. # using this script.
  7. #
  8. # The following variables exported from environment will be used.
  9. # If not set then values previously saved in domain.conf file are used.
  10. #
  11. # Only a username is required. All others are optional.
  12. #
  13. # The following examples are for QNAP NAS running QTS 4.2
  14. # export DEPLOY_SSH_CMD="" # defaults to ssh
  15. # export DEPLOY_SSH_USER="admin" # required
  16. # export DEPLOY_SSH_SERVER="qnap" # defaults to domain name
  17. # export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem"
  18. # export DEPLOY_SSH_CERTFILE="/etc/stunnel/stunnel.pem"
  19. # export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem"
  20. # export DEPLOY_SSH_FULLCHAIN=""
  21. # export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart"
  22. # export DEPLOY_SSH_BACKUP="" # yes or no, default to yes
  23. #
  24. ######## Public functions #####################
  25. #domain keyfile certfile cafile fullchain
  26. ssh_deploy() {
  27. _cdomain="$1"
  28. _ckey="$2"
  29. _ccert="$3"
  30. _cca="$4"
  31. _cfullchain="$5"
  32. _cmdstr=""
  33. _homedir='~'
  34. _backupprefix="$_homedir/.acme_ssh_deploy/$_cdomain-backup"
  35. _backupdir="$_backupprefix-$(_utc_date | tr ' ' '-')"
  36. if [ -f "$DOMAIN_CONF" ]; then
  37. # shellcheck disable=SC1090
  38. . "$DOMAIN_CONF"
  39. fi
  40. _debug _cdomain "$_cdomain"
  41. _debug _ckey "$_ckey"
  42. _debug _ccert "$_ccert"
  43. _debug _cca "$_cca"
  44. _debug _cfullchain "$_cfullchain"
  45. # USER is required to login by SSH to remote host.
  46. if [ -z "$DEPLOY_SSH_USER" ]; then
  47. if [ -z "$Le_Deploy_ssh_user" ]; then
  48. _err "DEPLOY_SSH_USER not defined."
  49. return 1
  50. fi
  51. else
  52. Le_Deploy_ssh_user="$DEPLOY_SSH_USER"
  53. _savedomainconf Le_Deploy_ssh_user "$Le_Deploy_ssh_user"
  54. fi
  55. # SERVER is optional. If not provided then use _cdomain
  56. if [ -n "$DEPLOY_SSH_SERVER" ]; then
  57. Le_Deploy_ssh_server="$DEPLOY_SSH_SERVER"
  58. _savedomainconf Le_Deploy_ssh_server "$Le_Deploy_ssh_server"
  59. elif [ -z "$Le_Deploy_ssh_server" ]; then
  60. Le_Deploy_ssh_server="$_cdomain"
  61. fi
  62. # CMD is optional. If not provided then use ssh
  63. if [ -n "$DEPLOY_SSH_CMD" ]; then
  64. Le_Deploy_ssh_cmd="$DEPLOY_SSH_CMD"
  65. _savedomainconf Le_Deploy_ssh_cmd "$Le_Deploy_ssh_cmd"
  66. elif [ -z "$Le_Deploy_ssh_cmd" ]; then
  67. Le_Deploy_ssh_cmd="ssh"
  68. fi
  69. # BACKUP is optional. If not provided then default to yes
  70. if [ "$DEPLOY_SSH_BACKUP" = "no" ]; then
  71. Le_Deploy_ssh_backup="no"
  72. elif [ -z "$Le_Deploy_ssh_backup" ]; then
  73. Le_Deploy_ssh_backup="yes"
  74. fi
  75. _savedomainconf Le_Deploy_ssh_backup "$Le_Deploy_ssh_backup"
  76. _info "Deploy certificates to remote server $Le_Deploy_ssh_user@$Le_Deploy_ssh_server"
  77. # KEYFILE is optional.
  78. # If provided then private key will be copied to provided filename.
  79. if [ -n "$DEPLOY_SSH_KEYFILE" ]; then
  80. Le_Deploy_ssh_keyfile="$DEPLOY_SSH_KEYFILE"
  81. _savedomainconf Le_Deploy_ssh_keyfile "$Le_Deploy_ssh_keyfile"
  82. fi
  83. if [ -n "$Le_Deploy_ssh_keyfile" ]; then
  84. if [ "$Le_Deploy_ssh_backup" = "yes" ]; then
  85. # backup file we are about to overwrite.
  86. _cmdstr="$_cmdstr cp $Le_Deploy_ssh_keyfile $_backupdir >/dev/null;"
  87. fi
  88. # copy new certificate into file.
  89. _cmdstr="$_cmdstr echo \"$(cat "$_ckey")\" > $Le_Deploy_ssh_keyfile;"
  90. _info "will copy private key to remote file $Le_Deploy_ssh_keyfile"
  91. fi
  92. # CERTFILE is optional.
  93. # If provided then certificate will be copied or appended to provided filename.
  94. if [ -n "$DEPLOY_SSH_CERTFILE" ]; then
  95. Le_Deploy_ssh_certfile="$DEPLOY_SSH_CERTFILE"
  96. _savedomainconf Le_Deploy_ssh_certfile "$Le_Deploy_ssh_certfile"
  97. fi
  98. if [ -n "$Le_Deploy_ssh_certfile" ]; then
  99. _pipe=">"
  100. if [ "$Le_Deploy_ssh_certfile" = "$Le_Deploy_ssh_keyfile" ]; then
  101. # if filename is same as previous file then append.
  102. _pipe=">>"
  103. elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
  104. # backup file we are about to overwrite.
  105. _cmdstr="$_cmdstr cp $Le_Deploy_ssh_certfile $_backupdir >/dev/null;"
  106. fi
  107. # copy new certificate into file.
  108. _cmdstr="$_cmdstr echo \"$(cat "$_ccert")\" $_pipe $Le_Deploy_ssh_certfile;"
  109. _info "will copy certificate to remote file $Le_Deploy_ssh_certfile"
  110. fi
  111. # CAFILE is optional.
  112. # If provided then CA intermediate certificate will be copied or appended to provided filename.
  113. if [ -n "$DEPLOY_SSH_CAFILE" ]; then
  114. Le_Deploy_ssh_cafile="$DEPLOY_SSH_CAFILE"
  115. _savedomainconf Le_Deploy_ssh_cafile "$Le_Deploy_ssh_cafile"
  116. fi
  117. if [ -n "$Le_Deploy_ssh_cafile" ]; then
  118. _pipe=">"
  119. if [ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_keyfile" ] \
  120. || [ "$Le_Deploy_ssh_cafile" = "$Le_Deploy_ssh_certfile" ]; then
  121. # if filename is same as previous file then append.
  122. _pipe=">>"
  123. elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
  124. # backup file we are about to overwrite.
  125. _cmdstr="$_cmdstr cp $Le_Deploy_ssh_cafile $_backupdir >/dev/null;"
  126. fi
  127. # copy new certificate into file.
  128. _cmdstr="$_cmdstr echo \"$(cat "$_cca")\" $_pipe $Le_Deploy_ssh_cafile;"
  129. _info "will copy CA file to remote file $Le_Deploy_ssh_cafile"
  130. fi
  131. # FULLCHAIN is optional.
  132. # If provided then fullchain certificate will be copied or appended to provided filename.
  133. if [ -n "$DEPLOY_SSH_FULLCHAIN" ]; then
  134. Le_Deploy_ssh_fullchain="$DEPLOY_SSH_FULLCHAIN"
  135. _savedomainconf Le_Deploy_ssh_fullchain "$Le_Deploy_ssh_fullchain"
  136. fi
  137. if [ -n "$Le_Deploy_ssh_fullchain" ]; then
  138. _pipe=">"
  139. if [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_keyfile" ] \
  140. || [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_certfile" ] \
  141. || [ "$Le_Deploy_ssh_fullchain" = "$Le_Deploy_ssh_cafile" ]; then
  142. # if filename is same as previous file then append.
  143. _pipe=">>"
  144. elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
  145. # backup file we are about to overwrite.
  146. _cmdstr="$_cmdstr cp $Le_Deploy_ssh_fullchain $_backupdir >/dev/null;"
  147. fi
  148. # copy new certificate into file.
  149. _cmdstr="$_cmdstr echo \"$(cat "$_cfullchain")\" $_pipe $Le_Deploy_ssh_fullchain;"
  150. _info "will copy fullchain to remote file $Le_Deploy_ssh_fullchain"
  151. fi
  152. # REMOTE_CMD is optional.
  153. # If provided then this command will be executed on remote host.
  154. if [ -n "$DEPLOY_SSH_REMOTE_CMD" ]; then
  155. Le_Deploy_ssh_remote_cmd="$DEPLOY_SSH_REMOTE_CMD"
  156. _savedomainconf Le_Deploy_ssh_remote_cmd "$Le_Deploy_ssh_remote_cmd"
  157. fi
  158. if [ -n "$Le_Deploy_ssh_remote_cmd" ]; then
  159. _cmdstr="$_cmdstr $Le_Deploy_ssh_remote_cmd;"
  160. _info "Will execute remote command $Le_Deploy_ssh_remote_cmd"
  161. fi
  162. if [ -z "$_cmdstr" ]; then
  163. _err "No remote commands to excute. Failed to deploy certificates to remote server"
  164. return 1
  165. elif [ "$Le_Deploy_ssh_backup" = "yes" ]; then
  166. # run cleanup on the backup directory, erase all older
  167. # than 180 days (15552000 seconds).
  168. _cmdstr="{ now=\"\$(date -u +%s)\"; for fn in $_backupprefix*; \
  169. do if [ -d \"\$fn\" ] && [ \"\$(expr \$now - \$(date -ur \$fn +%s) )\" -ge \"15552000\" ]; \
  170. then rm -rf \"\$fn\"; echo \"Backup \$fn deleted as older than 180 days\"; fi; done; }; $_cmdstr"
  171. # Alternate version of above... _cmdstr="find $_backupprefix* -type d -mtime +180 2>/dev/null | xargs rm -rf; $_cmdstr"
  172. # Create our backup directory for overwritten cert files.
  173. _cmdstr="mkdir -p $_backupdir; $_cmdstr"
  174. _info "Backup of old certificate files will be placed in remote directory $_backupdir"
  175. _info "Backup directories erased after 180 days."
  176. fi
  177. _secure_debug "Remote commands to execute: " "$_cmdstr"
  178. _info "Submitting sequence of commands to remote server by ssh"
  179. # quotations in bash cmd below intended. Squash travis spellcheck error
  180. # shellcheck disable=SC2029
  181. $Le_Deploy_ssh_cmd -T "$Le_Deploy_ssh_user@$Le_Deploy_ssh_server" sh -c "'$_cmdstr'"
  182. _ret="$?"
  183. if [ "$_ret" != "0" ]; then
  184. _err "Error code $_ret returned from $Le_Deploy_ssh_cmd"
  185. fi
  186. return $_ret
  187. }