]>
Commit | Line | Data |
---|---|---|
555e0de9 BH |
1 | #!/usr/bin/env sh |
2 | ||
8e8cda13 | 3 | # Here is a script to deploy cert to Synology DSM |
555e0de9 | 4 | # |
4635dacf | 5 | # It requires following environment variables: |
555e0de9 BH |
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 | |
80f1034d | 17 | # SYNO_DID - device ID to skip OTP - defaults to empty |
4635dacf NA |
18 | # SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty |
19 | # | |
20 | # Dependencies: | |
21 | # ------------- | |
22 | # - jq and curl | |
23 | # - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set) | |
555e0de9 BH |
24 | # |
25 | #returns 0 means success, otherwise error. | |
26 | ||
27 | ######## Public functions ##################### | |
28 | ||
29 | #domain keyfile certfile cafile fullchain | |
30 | synology_dsm_deploy() { | |
31 | ||
32 | _cdomain="$1" | |
33 | _ckey="$2" | |
34 | _ccert="$3" | |
35 | _cca="$4" | |
36 | ||
37 | _debug _cdomain "$_cdomain" | |
38 | ||
39 | # Get Username and Password, but don't save until we successfully authenticate | |
12593410 BH |
40 | _getdeployconf SYNO_Username |
41 | _getdeployconf SYNO_Password | |
42 | _getdeployconf SYNO_Create | |
fd64c208 | 43 | _getdeployconf SYNO_DID |
4635dacf | 44 | _getdeployconf SYNO_TOTP_SECRET |
3a7c7fe4 | 45 | if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then |
555e0de9 BH |
46 | _err "SYNO_Username & SYNO_Password must be set" |
47 | return 1 | |
48 | fi | |
49 | _debug2 SYNO_Username "$SYNO_Username" | |
50 | _secure_debug2 SYNO_Password "$SYNO_Password" | |
51 | ||
52 | # Optional scheme, hostname, and port for Synology DSM | |
12593410 BH |
53 | _getdeployconf SYNO_Scheme |
54 | _getdeployconf SYNO_Hostname | |
55 | _getdeployconf SYNO_Port | |
555e0de9 BH |
56 | |
57 | # default vaules for scheme, hostname, and port | |
58 | # defaulting to localhost and http because it's localhost... | |
59 | [ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http" | |
60 | [ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost" | |
61 | [ -n "${SYNO_Port}" ] || SYNO_Port="5000" | |
62 | ||
12593410 BH |
63 | _savedeployconf SYNO_Scheme "$SYNO_Scheme" |
64 | _savedeployconf SYNO_Hostname "$SYNO_Hostname" | |
65 | _savedeployconf SYNO_Port "$SYNO_Port" | |
66 | ||
555e0de9 BH |
67 | _debug2 SYNO_Scheme "$SYNO_Scheme" |
68 | _debug2 SYNO_Hostname "$SYNO_Hostname" | |
69 | _debug2 SYNO_Port "$SYNO_Port" | |
70 | ||
71 | # Get the certificate description, but don't save it until we verfiy it's real | |
72 | _getdeployconf SYNO_Certificate | |
694194be | 73 | _debug SYNO_Certificate "${SYNO_Certificate:-}" |
555e0de9 | 74 | |
dcb51683 | 75 | # shellcheck disable=SC1003 # We are not trying to escape a single quote |
74a4a788 BH |
76 | if printf "%s" "$SYNO_Certificate" | grep '\\'; then |
77 | _err "Do not use a backslash (\) in your certificate description" | |
78 | return 1 | |
79 | fi | |
80 | ||
555e0de9 BH |
81 | _base_url="$SYNO_Scheme://$SYNO_Hostname:$SYNO_Port" |
82 | _debug _base_url "$_base_url" | |
83 | ||
cc692854 T |
84 | _debug "Getting API version" |
85 | response=$(_get "$_base_url/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=SYNO.API.Auth") | |
86 | api_version=$(echo "$response" | grep "SYNO.API.Auth" | sed -n 's/.*"maxVersion" *: *\([0-9]*\).*/\1/p') | |
87 | _debug3 response "$response" | |
88 | _debug3 api_version "$api_version" | |
89 | ||
555e0de9 | 90 | # Login, get the token from JSON and session id from cookie |
52a168b9 | 91 | _info "Logging into $SYNO_Hostname:$SYNO_Port" |
52b81608 BH |
92 | encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" |
93 | encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" | |
cc692854 | 94 | |
4635dacf NA |
95 | otp_code="" |
96 | if [ -n "$SYNO_TOTP_SECRET" ]; then | |
97 | otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)" | |
98 | fi | |
99 | ||
2635dfef | 100 | if [ -n "$SYNO_DID" ]; then |
cc692854 T |
101 | _H1="Cookie: did=$SYNO_DID" |
102 | export _H1 | |
103 | _debug3 H1 "${_H1}" | |
104 | fi | |
105 | ||
4635dacf | 106 | response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") |
cc692854 | 107 | token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') |
52a168b9 | 108 | _debug3 response "$response" |
d15c14ab | 109 | _debug token "$token" |
52a168b9 BH |
110 | |
111 | if [ -z "$token" ]; then | |
555e0de9 BH |
112 | _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." |
113 | _err "Check your username and password." | |
4635dacf | 114 | _err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET." |
555e0de9 BH |
115 | return 1 |
116 | fi | |
cc692854 | 117 | sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') |
555e0de9 | 118 | |
cc692854 | 119 | _H1="X-SYNO-TOKEN: $token" |
52a168b9 | 120 | export _H1 |
5d3bc95a | 121 | _debug2 H1 "${_H1}" |
52a168b9 | 122 | |
555e0de9 | 123 | # Now that we know the username and password are good, save them |
52a168b9 BH |
124 | _savedeployconf SYNO_Username "$SYNO_Username" |
125 | _savedeployconf SYNO_Password "$SYNO_Password" | |
fd64c208 | 126 | _savedeployconf SYNO_DID "$SYNO_DID" |
4635dacf | 127 | _savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET" |
555e0de9 | 128 | |
52a168b9 | 129 | _info "Getting certificates in Synology DSM" |
cc692854 | 130 | response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") |
555e0de9 | 131 | _debug3 response "$response" |
74a4a788 BH |
132 | escaped_certificate="$(printf "%s" "$SYNO_Certificate" | sed 's/\([].*^$[]\)/\\\1/g;s/"/\\\\"/g')" |
133 | _debug escaped_certificate "$escaped_certificate" | |
134 | id=$(echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\"id\":\"\([^\"]*\).*/\1/p") | |
52a168b9 | 135 | _debug2 id "$id" |
555e0de9 | 136 | |
3a7c7fe4 | 137 | if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then |
de25232a | 138 | _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" |
555e0de9 BH |
139 | return 1 |
140 | fi | |
141 | ||
142 | # we've verified this certificate description is a thing, so save it | |
74a4a788 | 143 | _savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64" |
555e0de9 | 144 | |
52a168b9 | 145 | _info "Generate form POST request" |
0deea539 | 146 | nl="\0015\0012" |
79637097 | 147 | delim="--------------------------$(_utc_date | tr -d -- '-: ')" |
0deea539 | 148 | content="--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")\0012" |
149 | content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_ccert")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ccert")\0012" | |
150 | content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"inter_cert\"; filename=\"$(basename "$_cca")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cca")\0012" | |
52a168b9 BH |
151 | content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id" |
152 | content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}" | |
74a4a788 | 153 | if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then |
5ab9ca1c BH |
154 | _debug2 default "this is the default certificate" |
155 | content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true" | |
156 | else | |
157 | _debug2 default "this is NOT the default certificate" | |
158 | fi | |
52a168b9 | 159 | content="$content${nl}--$delim--${nl}" |
95769de4 BH |
160 | content="$(printf "%b_" "$content")" |
161 | content="${content%_}" # protect trailing \n | |
52a168b9 BH |
162 | |
163 | _info "Upload certificate to the Synology DSM" | |
cc692854 | 164 | response=$(_post "$content" "$_base_url/webapi/entry.cgi?api=SYNO.Core.Certificate&method=import&version=1&SynoToken=$token&_sid=$sid" "" "POST" "multipart/form-data; boundary=${delim}") |
555e0de9 | 165 | _debug3 response "$response" |
555e0de9 | 166 | |
1b475cf9 BH |
167 | if ! echo "$response" | grep '"error":' >/dev/null; then |
168 | if echo "$response" | grep '"restart_httpd":true' >/dev/null; then | |
6459ccb1 | 169 | _info "http services were restarted" |
555e0de9 | 170 | else |
6459ccb1 | 171 | _info "http services were NOT restarted" |
555e0de9 | 172 | fi |
6459ccb1 | 173 | return 0 |
555e0de9 | 174 | else |
52a168b9 | 175 | _err "Unable to update certificate, error code $response" |
555e0de9 BH |
176 | return 1 |
177 | fi | |
178 | } |