Hunter0x7c7
2022-08-11 3cd6b479d058b8ee96e1b773c8034f0ca8865f9e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#!/usr/bin/env sh
 
#DEPLOY_DOCKER_CONTAINER_LABEL="xxxxxxx"
 
#DEPLOY_DOCKER_CONTAINER_KEY_FILE="/path/to/key.pem"
#DEPLOY_DOCKER_CONTAINER_CERT_FILE="/path/to/cert.pem"
#DEPLOY_DOCKER_CONTAINER_CA_FILE="/path/to/ca.pem"
#DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/path/to/fullchain.pem"
#DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload"
 
_DEPLOY_DOCKER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/deploy-to-docker-containers"
 
_DOCKER_HOST_DEFAULT="/var/run/docker.sock"
 
docker_deploy() {
  _cdomain="$1"
  _ckey="$2"
  _ccert="$3"
  _cca="$4"
  _cfullchain="$5"
  _debug _cdomain "$_cdomain"
  _getdeployconf DEPLOY_DOCKER_CONTAINER_LABEL
  _debug2 DEPLOY_DOCKER_CONTAINER_LABEL "$DEPLOY_DOCKER_CONTAINER_LABEL"
  if [ -z "$DEPLOY_DOCKER_CONTAINER_LABEL" ]; then
    _err "The DEPLOY_DOCKER_CONTAINER_LABEL variable is not defined, we use this label to find the container."
    _err "See: $_DEPLOY_DOCKER_WIKI"
  fi
 
  _savedeployconf DEPLOY_DOCKER_CONTAINER_LABEL "$DEPLOY_DOCKER_CONTAINER_LABEL"
 
  if [ "$DOCKER_HOST" ]; then
    _saveaccountconf DOCKER_HOST "$DOCKER_HOST"
  fi
 
  if _exists docker && docker version | grep -i docker >/dev/null; then
    _info "Using docker command"
    export _USE_DOCKER_COMMAND=1
  else
    export _USE_DOCKER_COMMAND=
  fi
 
  export _USE_UNIX_SOCKET=
  if [ -z "$_USE_DOCKER_COMMAND" ]; then
    export _USE_REST=
    if [ "$DOCKER_HOST" ]; then
      _debug "Try use docker host: $DOCKER_HOST"
      export _USE_REST=1
    else
      export _DOCKER_SOCK="$_DOCKER_HOST_DEFAULT"
      _debug "Try use $_DOCKER_SOCK"
      if [ ! -e "$_DOCKER_SOCK" ] || [ ! -w "$_DOCKER_SOCK" ]; then
        _err "$_DOCKER_SOCK is not available"
        return 1
      fi
      export _USE_UNIX_SOCKET=1
      if ! _exists "curl"; then
        _err "Please install curl first."
        _err "We need curl to work."
        return 1
      fi
      if ! _check_curl_version; then
        return 1
      fi
    fi
  fi
 
  _getdeployconf DEPLOY_DOCKER_CONTAINER_KEY_FILE
  _debug2 DEPLOY_DOCKER_CONTAINER_KEY_FILE "$DEPLOY_DOCKER_CONTAINER_KEY_FILE"
  if [ "$DEPLOY_DOCKER_CONTAINER_KEY_FILE" ]; then
    _savedeployconf DEPLOY_DOCKER_CONTAINER_KEY_FILE "$DEPLOY_DOCKER_CONTAINER_KEY_FILE"
  fi
 
  _getdeployconf DEPLOY_DOCKER_CONTAINER_CERT_FILE
  _debug2 DEPLOY_DOCKER_CONTAINER_CERT_FILE "$DEPLOY_DOCKER_CONTAINER_CERT_FILE"
  if [ "$DEPLOY_DOCKER_CONTAINER_CERT_FILE" ]; then
    _savedeployconf DEPLOY_DOCKER_CONTAINER_CERT_FILE "$DEPLOY_DOCKER_CONTAINER_CERT_FILE"
  fi
 
  _getdeployconf DEPLOY_DOCKER_CONTAINER_CA_FILE
  _debug2 DEPLOY_DOCKER_CONTAINER_CA_FILE "$DEPLOY_DOCKER_CONTAINER_CA_FILE"
  if [ "$DEPLOY_DOCKER_CONTAINER_CA_FILE" ]; then
    _savedeployconf DEPLOY_DOCKER_CONTAINER_CA_FILE "$DEPLOY_DOCKER_CONTAINER_CA_FILE"
  fi
 
  _getdeployconf DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE
  _debug2 DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE"
  if [ "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE" ]; then
    _savedeployconf DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE"
  fi
 
  _getdeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD
  _debug2 DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
  if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then
    _savedeployconf DEPLOY_DOCKER_CONTAINER_RELOAD_CMD "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" "base64"
  fi
 
  _cid="$(_get_id "$DEPLOY_DOCKER_CONTAINER_LABEL")"
  _info "Container id: $_cid"
  if [ -z "$_cid" ]; then
    _err "can not find container id"
    return 1
  fi
 
  if [ "$DEPLOY_DOCKER_CONTAINER_KEY_FILE" ]; then
    if ! _docker_cp "$_cid" "$_ckey" "$DEPLOY_DOCKER_CONTAINER_KEY_FILE"; then
      return 1
    fi
  fi
 
  if [ "$DEPLOY_DOCKER_CONTAINER_CERT_FILE" ]; then
    if ! _docker_cp "$_cid" "$_ccert" "$DEPLOY_DOCKER_CONTAINER_CERT_FILE"; then
      return 1
    fi
  fi
 
  if [ "$DEPLOY_DOCKER_CONTAINER_CA_FILE" ]; then
    if ! _docker_cp "$_cid" "$_cca" "$DEPLOY_DOCKER_CONTAINER_CA_FILE"; then
      return 1
    fi
  fi
 
  if [ "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE" ]; then
    if ! _docker_cp "$_cid" "$_cfullchain" "$DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE"; then
      return 1
    fi
  fi
 
  if [ "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD" ]; then
    _info "Reloading: $DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"
    if ! _docker_exec "$_cid" "$DEPLOY_DOCKER_CONTAINER_RELOAD_CMD"; then
      return 1
    fi
  fi
  return 0
}
 
#label
_get_id() {
  _label="$1"
  if [ "$_USE_DOCKER_COMMAND" ]; then
    docker ps -f label="$_label" --format "{{.ID}}"
  elif [ "$_USE_REST" ]; then
    _err "Not implemented yet."
    return 1
  elif [ "$_USE_UNIX_SOCKET" ]; then
    _req="{\"label\":[\"$_label\"]}"
    _debug2 _req "$_req"
    _req="$(printf "%s" "$_req" | _url_encode)"
    _debug2 _req "$_req"
    listjson="$(_curl_unix_sock "${_DOCKER_SOCK:-$_DOCKER_HOST_DEFAULT}" GET "/containers/json?filters=$_req")"
    _debug2 "listjson" "$listjson"
    echo "$listjson" | tr '{,' '\n' | grep -i '"id":' | _head_n 1 | cut -d '"' -f 4
  else
    _err "Not implemented yet."
    return 1
  fi
}
 
#id  cmd
_docker_exec() {
  _eargs="$*"
  _debug2 "_docker_exec $_eargs"
  _dcid="$1"
  shift
  if [ "$_USE_DOCKER_COMMAND" ]; then
    docker exec -i "$_dcid" sh -c "$*"
  elif [ "$_USE_REST" ]; then
    _err "Not implemented yet."
    return 1
  elif [ "$_USE_UNIX_SOCKET" ]; then
    _cmd="$*"
    #_cmd="$(printf "%s" "$_cmd" | sed 's/ /","/g')"
    _debug2 _cmd "$_cmd"
    #create exec instance:
    cjson="$(_curl_unix_sock "$_DOCKER_SOCK" POST "/containers/$_dcid/exec" "{\"Cmd\": [\"sh\", \"-c\", \"$_cmd\"]}")"
    _debug2 cjson "$cjson"
    execid="$(echo "$cjson" | cut -d '"' -f 4)"
    _debug execid "$execid"
    ejson="$(_curl_unix_sock "$_DOCKER_SOCK" POST "/exec/$execid/start" "{\"Detach\": false,\"Tty\": false}")"
    _debug2 ejson "$ejson"
    if [ "$ejson" ]; then
      _err "$ejson"
      return 1
    fi
  else
    _err "Not implemented yet."
    return 1
  fi
}
 
#id from  to
_docker_cp() {
  _dcid="$1"
  _from="$2"
  _to="$3"
  _info "Copying file from $_from to $_to"
  _dir="$(dirname "$_to")"
  _debug2 _dir "$_dir"
  if ! _docker_exec "$_dcid" mkdir -p "$_dir"; then
    _err "Can not create dir: $_dir"
    return 1
  fi
  if [ "$_USE_DOCKER_COMMAND" ]; then
    if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
      _docker_exec "$_dcid" tee "$_to" <"$_from"
    else
      _docker_exec "$_dcid" tee "$_to" <"$_from" >/dev/null
    fi
    if [ "$?" = "0" ]; then
      _info "Success"
      return 0
    else
      _info "Error"
      return 1
    fi
  elif [ "$_USE_REST" ]; then
    _err "Not implemented yet."
    return 1
  elif [ "$_USE_UNIX_SOCKET" ]; then
    _frompath="$_from"
    if _startswith "$_frompath" '/'; then
      _frompath="$(echo "$_from" | cut -b 2-)" #remove the first '/' char
    fi
    _debug2 "_frompath" "$_frompath"
    _toname="$(basename "$_to")"
    _debug2 "_toname" "$_toname"
    _debug2 "_from" "$_from"
    if ! tar --transform="s,$(printf "%s" "$_frompath" | tr '*' .),$_toname," -cz "$_from" 2>/dev/null | _curl_unix_sock "$_DOCKER_SOCK" PUT "/containers/$_dcid/archive?noOverwriteDirNonDir=1&path=$(printf "%s" "$_dir" | _url_encode)" '@-' "Content-Type: application/octet-stream"; then
      _err "copy error"
      return 1
    fi
    return 0
  else
    _err "Not implemented yet."
    return 1
  fi
 
}
 
#sock method  endpoint data content-type
_curl_unix_sock() {
  _socket="$1"
  _method="$2"
  _endpoint="$3"
  _data="$4"
  _ctype="$5"
  if [ -z "$_ctype" ]; then
    _ctype="Content-Type: application/json"
  fi
  _debug _data "$_data"
  _debug2 "url" "http://localhost$_endpoint"
  if [ "$_CURL_NO_HOST" ]; then
    _cux_url="http:$_endpoint"
  else
    _cux_url="http://localhost$_endpoint"
  fi
 
  if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
    curl -vvv --silent --unix-socket "$_socket" -X "$_method" --data-binary "$_data" --header "$_ctype" "$_cux_url"
  else
    curl --silent --unix-socket "$_socket" -X "$_method" --data-binary "$_data" --header "$_ctype" "$_cux_url"
  fi
 
}
 
_check_curl_version() {
  _cversion="$(curl -V | grep '^curl ' | cut -d ' ' -f 2)"
  _debug2 "_cversion" "$_cversion"
 
  _major="$(_getfield "$_cversion" 1 '.')"
  _debug2 "_major" "$_major"
 
  _minor="$(_getfield "$_cversion" 2 '.')"
  _debug2 "_minor" "$_minor"
 
  if [ "$_major$_minor" -lt "740" ]; then
    _err "curl v$_cversion doesn't support unit socket"
    _err "Please upgrade to curl 7.40 or later."
    return 1
  fi
  if [ "$_major$_minor" -lt "750" ]; then
    _debug "Use short host name"
    export _CURL_NO_HOST=1
  else
    export _CURL_NO_HOST=
  fi
  return 0
}