]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/env sh | |
2 | ||
3 | # ISPConfig 3.1 API | |
4 | # User must provide login data and URL to the ISPConfig installation incl. port. The remote user in ISPConfig must have access to: | |
5 | # - DNS txt Functions | |
6 | ||
7 | # Report bugs to https://github.com/sjau/acme.sh | |
8 | ||
9 | # Values to export: | |
10 | # export ISPC_User="remoteUser" | |
11 | # export ISPC_Password="remotePassword" | |
12 | # export ISPC_Api="https://ispc.domain.tld:8080/remote/json.php" | |
13 | # export ISPC_Api_Insecure=1 # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1) | |
14 | ||
15 | ######## Public functions ##################### | |
16 | ||
17 | #Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
18 | dns_ispconfig_add() { | |
19 | fulldomain="${1}" | |
20 | txtvalue="${2}" | |
21 | _debug "Calling: dns_ispconfig_add() '${fulldomain}' '${txtvalue}'" | |
22 | _ISPC_credentials && _ISPC_login && _ISPC_getZoneInfo && _ISPC_addTxt | |
23 | } | |
24 | ||
25 | #Usage: dns_myapi_rm _acme-challenge.www.domain.com | |
26 | dns_ispconfig_rm() { | |
27 | fulldomain="${1}" | |
28 | _debug "Calling: dns_ispconfig_rm() '${fulldomain}'" | |
29 | _ISPC_credentials && _ISPC_login && _ISPC_rmTxt | |
30 | } | |
31 | ||
32 | #################### Private functions below ################################## | |
33 | ||
34 | _ISPC_credentials() { | |
35 | ISPC_User="${ISPC_User:-$(_readaccountconf_mutable ISPC_User)}" | |
36 | ISPC_Password="${ISPC_Password:-$(_readaccountconf_mutable ISPC_Password)}" | |
37 | ISPC_Api="${ISPC_Api:-$(_readaccountconf_mutable ISPC_Api)}" | |
38 | ISPC_Api_Insecure="${ISPC_Api_Insecure:-$(_readaccountconf_mutable ISPC_Api_Insecure)}" | |
39 | if [ -z "${ISPC_User}" ] || [ -z "${ISPC_Password}" ] || [ -z "${ISPC_Api}" ] || [ -z "${ISPC_Api_Insecure}" ]; then | |
40 | ISPC_User="" | |
41 | ISPC_Password="" | |
42 | ISPC_Api="" | |
43 | ISPC_Api_Insecure="" | |
44 | _err "You haven't specified the ISPConfig Login data, URL and whether you want check the ISPC SSL cert. Please try again." | |
45 | return 1 | |
46 | else | |
47 | _saveaccountconf_mutable ISPC_User "${ISPC_User}" | |
48 | _saveaccountconf_mutable ISPC_Password "${ISPC_Password}" | |
49 | _saveaccountconf_mutable ISPC_Api "${ISPC_Api}" | |
50 | _saveaccountconf_mutable ISPC_Api_Insecure "${ISPC_Api_Insecure}" | |
51 | # Set whether curl should use secure or insecure mode | |
52 | export HTTPS_INSECURE="${ISPC_Api_Insecure}" | |
53 | fi | |
54 | } | |
55 | ||
56 | _ISPC_login() { | |
57 | _info "Getting Session ID" | |
58 | curData="{\"username\":\"${ISPC_User}\",\"password\":\"${ISPC_Password}\",\"client_login\":false}" | |
59 | curResult="$(_post "${curData}" "${ISPC_Api}?login")" | |
60 | _debug "Calling _ISPC_login: '${curData}' '${ISPC_Api}?login'" | |
61 | _debug "Result of _ISPC_login: '$curResult'" | |
62 | if _contains "${curResult}" '"code":"ok"'; then | |
63 | sessionID=$(echo "${curResult}" | _egrep_o "response.*" | cut -d ':' -f 2 | cut -d '"' -f 2) | |
64 | _info "Retrieved Session ID." | |
65 | _debug "Session ID: '${sessionID}'" | |
66 | else | |
67 | _err "Couldn't retrieve the Session ID." | |
68 | return 1 | |
69 | fi | |
70 | } | |
71 | ||
72 | _ISPC_getZoneInfo() { | |
73 | _info "Getting Zoneinfo" | |
74 | zoneEnd=false | |
75 | curZone="${fulldomain}" | |
76 | while [ "${zoneEnd}" = false ]; do | |
77 | # we can strip the first part of the fulldomain, since it's just the _acme-challenge string | |
78 | curZone="${curZone#*.}" | |
79 | # suffix . needed for zone -> domain.tld. | |
80 | curData="{\"session_id\":\"${sessionID}\",\"primary_id\":{\"origin\":\"${curZone}.\"}}" | |
81 | curResult="$(_post "${curData}" "${ISPC_Api}?dns_zone_get")" | |
82 | _debug "Calling _ISPC_getZoneInfo: '${curData}' '${ISPC_Api}?dns_zone_get'" | |
83 | _debug "Result of _ISPC_getZoneInfo: '$curResult'" | |
84 | if _contains "${curResult}" '"id":"'; then | |
85 | zoneFound=true | |
86 | zoneEnd=true | |
87 | _info "Retrieved zone data." | |
88 | _debug "Zone data: '${curResult}'" | |
89 | fi | |
90 | if [ "${curZone#*.}" != "$curZone" ]; then | |
91 | _debug2 "$curZone still contains a '.' - so we can check next higher level" | |
92 | else | |
93 | zoneEnd=true | |
94 | _err "Couldn't retrieve zone data." | |
95 | return 1 | |
96 | fi | |
97 | done | |
98 | if [ "${zoneFound}" ]; then | |
99 | server_id=$(echo "${curResult}" | _egrep_o "server_id.*" | cut -d ':' -f 2 | cut -d '"' -f 2) | |
100 | _debug "Server ID: '${server_id}'" | |
101 | case "${server_id}" in | |
102 | '' | *[!0-9]*) | |
103 | _err "Server ID is not numeric." | |
104 | return 1 | |
105 | ;; | |
106 | *) _info "Retrieved Server ID" ;; | |
107 | esac | |
108 | zone=$(echo "${curResult}" | _egrep_o "\"id.*" | cut -d ':' -f 2 | cut -d '"' -f 2) | |
109 | _debug "Zone: '${zone}'" | |
110 | case "${zone}" in | |
111 | '' | *[!0-9]*) | |
112 | _err "Zone ID is not numeric." | |
113 | return 1 | |
114 | ;; | |
115 | *) _info "Retrieved Zone ID" ;; | |
116 | esac | |
117 | sys_userid=$(echo "${curResult}" | _egrep_o "sys_userid.*" | cut -d ':' -f 2 | cut -d '"' -f 2) | |
118 | _debug "SYS User ID: '${sys_userid}'" | |
119 | case "${sys_userid}" in | |
120 | '' | *[!0-9]*) | |
121 | _err "SYS User ID is not numeric." | |
122 | return 1 | |
123 | ;; | |
124 | *) _info "Retrieved SYS User ID." ;; | |
125 | esac | |
126 | zoneFound="" | |
127 | zoneEnd="" | |
128 | fi | |
129 | # Need to get client_id as it is different from sys_userid | |
130 | curData="{\"session_id\":\"${sessionID}\",\"sys_userid\":\"${sys_userid}\"}" | |
131 | curResult="$(_post "${curData}" "${ISPC_Api}?client_get_id")" | |
132 | _debug "Calling _ISPC_ClientGetID: '${curData}' '${ISPC_Api}?client_get_id'" | |
133 | _debug "Result of _ISPC_ClientGetID: '$curResult'" | |
134 | client_id=$(echo "${curResult}" | _egrep_o "response.*" | cut -d ':' -f 2 | cut -d '"' -f 2 | tr -d '{}') | |
135 | _debug "Client ID: '${client_id}'" | |
136 | case "${client_id}" in | |
137 | '' | *[!0-9]*) | |
138 | _err "Client ID is not numeric." | |
139 | return 1 | |
140 | ;; | |
141 | *) _info "Retrieved Client ID." ;; | |
142 | esac | |
143 | } | |
144 | ||
145 | _ISPC_addTxt() { | |
146 | curSerial="$(date +%s)" | |
147 | curStamp="$(date +'%F %T')" | |
148 | params="\"server_id\":\"${server_id}\",\"zone\":\"${zone}\",\"name\":\"${fulldomain}.\",\"type\":\"txt\",\"data\":\"${txtvalue}\",\"aux\":\"0\",\"ttl\":\"3600\",\"active\":\"y\",\"stamp\":\"${curStamp}\",\"serial\":\"${curSerial}\"" | |
149 | curData="{\"session_id\":\"${sessionID}\",\"client_id\":\"${client_id}\",\"params\":{${params}},\"update_serial\":true}" | |
150 | curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_add")" | |
151 | _debug "Calling _ISPC_addTxt: '${curData}' '${ISPC_Api}?dns_txt_add'" | |
152 | _debug "Result of _ISPC_addTxt: '$curResult'" | |
153 | record_id=$(echo "${curResult}" | _egrep_o "\"response.*" | cut -d ':' -f 2 | cut -d '"' -f 2) | |
154 | _debug "Record ID: '${record_id}'" | |
155 | case "${record_id}" in | |
156 | '' | *[!0-9]*) | |
157 | _err "Couldn't add ACME Challenge TXT record to zone." | |
158 | return 1 | |
159 | ;; | |
160 | *) _info "Added ACME Challenge TXT record to zone." ;; | |
161 | esac | |
162 | } | |
163 | ||
164 | _ISPC_rmTxt() { | |
165 | # Need to get the record ID. | |
166 | curData="{\"session_id\":\"${sessionID}\",\"primary_id\":{\"name\":\"${fulldomain}.\",\"type\":\"TXT\"}}" | |
167 | curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_get")" | |
168 | _debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_get'" | |
169 | _debug "Result of _ISPC_rmTxt: '$curResult'" | |
170 | if _contains "${curResult}" '"code":"ok"'; then | |
171 | record_id=$(echo "${curResult}" | _egrep_o "\"id.*" | cut -d ':' -f 2 | cut -d '"' -f 2) | |
172 | _debug "Record ID: '${record_id}'" | |
173 | case "${record_id}" in | |
174 | '' | *[!0-9]*) | |
175 | _err "Record ID is not numeric." | |
176 | return 1 | |
177 | ;; | |
178 | *) | |
179 | unset IFS | |
180 | _info "Retrieved Record ID." | |
181 | curData="{\"session_id\":\"${sessionID}\",\"primary_id\":\"${record_id}\",\"update_serial\":true}" | |
182 | curResult="$(_post "${curData}" "${ISPC_Api}?dns_txt_delete")" | |
183 | _debug "Calling _ISPC_rmTxt: '${curData}' '${ISPC_Api}?dns_txt_delete'" | |
184 | _debug "Result of _ISPC_rmTxt: '$curResult'" | |
185 | if _contains "${curResult}" '"code":"ok"'; then | |
186 | _info "Removed ACME Challenge TXT record from zone." | |
187 | else | |
188 | _err "Couldn't remove ACME Challenge TXT record from zone." | |
189 | return 1 | |
190 | fi | |
191 | ;; | |
192 | esac | |
193 | fi | |
194 | } |