You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
5.2 KiB

  1. #!/usr/bin/env sh
  2. # Here is a script to deploy cert to Synology DSM
  3. #
  4. # it requires the jq and curl are in the $PATH and the following
  5. # environment variables must be set:
  6. #
  7. # SYNO_Username - Synology Username to login (must be an administrator)
  8. # SYNO_Password - Synology Password to login
  9. # SYNO_Certificate - Certificate description to target for replacement
  10. #
  11. # The following environmental variables may be set if you don't like their
  12. # default values:
  13. #
  14. # SYNO_Scheme - defaults to http
  15. # SYNO_Hostname - defaults to localhost
  16. # SYNO_Port - defaults to 5000
  17. #
  18. #returns 0 means success, otherwise error.
  19. ######## Public functions #####################
  20. #domain keyfile certfile cafile fullchain
  21. synology_dsm_deploy() {
  22. _cdomain="$1"
  23. _ckey="$2"
  24. _ccert="$3"
  25. _cca="$4"
  26. _debug _cdomain "$_cdomain"
  27. # Get Username and Password, but don't save until we successfully authenticate
  28. SYNO_Username="${SYNO_Username:-$(_readdomainconf SYNO_Username)}"
  29. SYNO_Password="${SYNO_Password:-$(_readdomainconf SYNO_Password)}"
  30. if [ -z "$SYNO_Username" ] || [ -z "$SYNO_Password" ]; then
  31. SYNO_Username=""
  32. SYNO_Password=""
  33. _err "SYNO_Username & SYNO_Password must be set"
  34. return 1
  35. fi
  36. _debug2 SYNO_Username "$SYNO_Username"
  37. _secure_debug2 SYNO_Password "$SYNO_Password"
  38. # Optional scheme, hostname, and port for Synology DSM
  39. SYNO_Scheme="${SYNO_Scheme:-$(_readdomainconf SYNO_Scheme)}"
  40. SYNO_Hostname="${SYNO_Hostname:-$(_readdomainconf SYNO_Hostname)}"
  41. SYNO_Port="${SYNO_Port:-$(_readdomainconf SYNO_Port)}"
  42. _savedomainconf SYNO_Scheme "$SYNO_Scheme"
  43. _savedomainconf SYNO_Hostname "$SYNO_Hostname"
  44. _savedomainconf SYNO_Port "$SYNO_Port"
  45. # default vaules for scheme, hostname, and port
  46. # defaulting to localhost and http because it's localhost...
  47. [ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http"
  48. [ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost"
  49. [ -n "${SYNO_Port}" ] || SYNO_Port="5000"
  50. _debug2 SYNO_Scheme "$SYNO_Scheme"
  51. _debug2 SYNO_Hostname "$SYNO_Hostname"
  52. _debug2 SYNO_Port "$SYNO_Port"
  53. # Get the certificate description, but don't save it until we verfiy it's real
  54. _getdeployconf SYNO_Certificate
  55. # shellcheck disable=SC2154
  56. if [ -z "${SYNO_Certificate}" ]; then
  57. _err "SYNO_Certificate needs to be defined (with the Certificate description name)"
  58. return 1
  59. fi
  60. _debug SYNO_Certificate "$SYNO_Certificate"
  61. # We can't use _get or _post because they lack support for cookies
  62. # use jq because I'm too lazy to figure out what is required to parse json
  63. # by hand. Also it seems to be in place for Synology DSM (6.2.1 at least)
  64. for x in curl jq; do
  65. if ! _exists "$x"; then
  66. _err "Please install $x first."
  67. _err "We need $x to work."
  68. return 1
  69. fi
  70. done
  71. _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port"
  72. _debug _base_url "$_base_url"
  73. _cookie_jar="$(_mktemp)"
  74. _debug _cookie_jar "$_cookie_jar"
  75. # Login, get the token from JSON and session id from cookie
  76. _debug "Logging into $SYNO_Hostname:$SYNO_Port"
  77. token=$(curl -sk -c "$_cookie_jar" "$_base_url/webman/login.cgi?username=$SYNO_Username&passwd=$SYNO_Password&enable_syno_token=yes" | jq -r .SynoToken)
  78. if [ "$token" = "null" ]; then
  79. _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme."
  80. _err "Check your username and password."
  81. rm "$_cookie_jar"
  82. return 1
  83. fi
  84. # Now that we know the username and password are good, save them
  85. _savedomainconf SYNO_Username "$SYNO_Username"
  86. _savedomainconf SYNO_Password "$SYNO_Password"
  87. _secure_debug2 token "$token"
  88. # Use token and session id to get the list of certificates
  89. response=$(curl -sk -b "$_cookie_jar" "$_base_url/webapi/entry.cgi" -H "X-SYNO-TOKEN: $token" -d api=SYNO.Core.Certificate.CRT -d method=list -d version=1)
  90. _debug3 response "$response"
  91. # select the first certificate matching our description
  92. cert=$(echo "$response" | jq -r ".data.certificates | map(select(.desc == \"$SYNO_Certificate\"))[0]")
  93. _debug3 cert "$cert"
  94. if [ "$cert" = "null" ]; then
  95. _err "Unable to find certificate: $SYNO_Certificate"
  96. rm "$_cookie_jar"
  97. return 1
  98. fi
  99. # we've verified this certificate description is a thing, so save it
  100. _savedeployconf SYNO_Certificate "$SYNO_Certificate"
  101. id=$(echo "$cert" | jq -r ".id")
  102. default=$(echo "$cert" | jq -r ".is_default")
  103. _debug2 id "$id"
  104. _debug2 default "$default"
  105. # This is the heavy lifting, make the API call to update a certificate in place
  106. response=$(curl -sk -b "$_cookie_jar" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token" -F "key=@$_ckey" -F "cert=@$_ccert" -F "inter_cert=@$_cca" -F "id=$id" -F "desc=$SYNO_Certificate" -F "as_default=$default")
  107. _debug3 response "$response"
  108. success=$(echo "$response" | jq -r ".success")
  109. _debug2 success "$success"
  110. rm "$_cookie_jar"
  111. if [ "$success" = "true" ]; then
  112. restarted=$(echo "$response" | jq -r ".data.restart_httpd")
  113. if [ "$restarted" = "true" ]; then
  114. _info "http services were restarted"
  115. else
  116. _info "http services were NOT restarted"
  117. fi
  118. return 0
  119. else
  120. code=$(echo "$response" | jq -r ".error.code")
  121. _err "Unable to update certificate, error code $code"
  122. return 1
  123. fi
  124. }