]>
Commit | Line | Data |
---|---|---|
14c27554 T |
1 | #!/usr/bin/env sh |
2 | # -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*- | |
3 | # vim: et ts=2 sw=2 | |
4 | # | |
5 | # DirectAdmin 1.41.0 API | |
6 | # The DirectAdmin interface has it's own Let's encrypt functionality, but this | |
7 | # script can be used to generate certificates for names which are not hosted on | |
8 | # DirectAdmin | |
9 | # | |
10 | # User must provide login data and URL to DirectAdmin incl. port. | |
11 | # You can create login key, by using the Login Keys function | |
ac9f6e3a | 12 | # ( https://da.example.com:8443/CMD_LOGIN_KEYS ), which only has access to |
14c27554 T |
13 | # - CMD_API_DNS_CONTROL |
14 | # - CMD_API_SHOW_DOMAINS | |
15 | # | |
16 | # See also https://www.directadmin.com/api.php and | |
17 | # https://www.directadmin.com/features.php?id=1298 | |
18 | # | |
19 | # Report bugs to https://github.com/TigerP/acme.sh/issues | |
20 | # | |
21 | # Values to export: | |
22 | # export DA_Api="https://remoteUser:remotePassword@da.example.com:8443" | |
23 | # export DA_Api_Insecure=1 | |
24 | # | |
25 | # Set DA_Api_Insecure to 1 for insecure and 0 for secure -> difference is | |
26 | # whether ssl cert is checked for validity (0) or whether it is just accepted | |
27 | # (1) | |
28 | # | |
29 | ######## Public functions ##################### | |
30 | ||
31 | # Usage: dns_myapi_add _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
32 | # Used to add txt record | |
33 | dns_da_add() { | |
34 | fulldomain="${1}" | |
35 | txtvalue="${2}" | |
36 | _debug "Calling: dns_da_add() '${fulldomain}' '${txtvalue}'" | |
37 | _DA_credentials && _DA_getDomainInfo && _DA_addTxt | |
38 | } | |
39 | ||
40 | # Usage: dns_da_rm _acme-challenge.www.example.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
41 | # Used to remove the txt record after validation | |
42 | dns_da_rm() { | |
43 | fulldomain="${1}" | |
44 | txtvalue="${2}" | |
45 | _debug "Calling: dns_da_rm() '${fulldomain}' '${txtvalue}'" | |
46 | _DA_credentials && _DA_getDomainInfo && _DA_rmTxt | |
47 | } | |
48 | ||
49 | #################### Private functions below ################################## | |
50 | # Usage: _DA_credentials | |
51 | # It will check if the needed settings are available | |
52 | _DA_credentials() { | |
53 | DA_Api="${DA_Api:-$(_readaccountconf_mutable DA_Api)}" | |
54 | DA_Api_Insecure="${DA_Api_Insecure:-$(_readaccountconf_mutable DA_Api_Insecure)}" | |
55 | if [ -z "${DA_Api}" ] || [ -z "${DA_Api_Insecure}" ]; then | |
56 | DA_Api="" | |
57 | DA_Api_Insecure="" | |
58 | _err "You haven't specified the DirectAdmin Login data, URL and whether you want check the DirectAdmin SSL cert. Please try again." | |
59 | return 1 | |
60 | else | |
61 | _saveaccountconf_mutable DA_Api "${DA_Api}" | |
62 | _saveaccountconf_mutable DA_Api_Insecure "${DA_Api_Insecure}" | |
63 | # Set whether curl should use secure or insecure mode | |
64 | export HTTPS_INSECURE="${DA_Api_Insecure}" | |
65 | fi | |
66 | } | |
67 | ||
68 | # Usage: _get_root _acme-challenge.www.example.com | |
69 | # Split the full domain to a domain and subdomain | |
70 | #returns | |
71 | # _sub_domain=_acme-challenge.www | |
72 | # _domain=example.com | |
73 | _get_root() { | |
74 | domain=$1 | |
75 | i=2 | |
76 | p=1 | |
77 | # Get a list of all the domains | |
78 | # response will contain "list[]=example.com&list[]=example.org" | |
399d6592 | 79 | _da_api CMD_API_SHOW_DOMAINS "" "${domain}" |
14c27554 T |
80 | while true; do |
81 | h=$(printf "%s" "$domain" | cut -d . -f $i-100) | |
82 | _debug h "$h" | |
83 | if [ -z "$h" ]; then | |
84 | # not valid | |
85 | _debug "The given domain $h is not valid" | |
86 | return 1 | |
87 | fi | |
88 | if _contains "$response" "$h" >/dev/null; then | |
89 | _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | |
90 | _domain=$h | |
91 | return 0 | |
92 | fi | |
93 | p=$i | |
94 | i=$(_math "$i" + 1) | |
95 | done | |
96 | _debug "Stop on 100" | |
97 | return 1 | |
98 | } | |
99 | ||
100 | # Usage: _da_api CMD_API_* data example.com | |
101 | # Use the DirectAdmin API and check the result | |
102 | # returns | |
103 | # response="error=0&text=Result text&details=" | |
104 | _da_api() { | |
105 | cmd=$1 | |
106 | data=$2 | |
107 | domain=$3 | |
108 | _debug "$domain; $data" | |
109 | response="$(_post "$data" "$DA_Api/$cmd" "" "POST")" | |
110 | ||
111 | if [ "$?" != "0" ]; then | |
112 | _err "error $cmd" | |
113 | return 1 | |
114 | fi | |
115 | _debug response "$response" | |
116 | ||
117 | case "${cmd}" in | |
19c43451 | 118 | CMD_API_DNS_CONTROL) |
119 | # Parse the result in general | |
120 | # error=0&text=Records Deleted&details= | |
121 | # error=1&text=Cannot View Dns Record&details=No domain provided | |
122 | err_field="$(_getfield "$response" 1 '&')" | |
123 | txt_field="$(_getfield "$response" 2 '&')" | |
124 | details_field="$(_getfield "$response" 3 '&')" | |
125 | error="$(_getfield "$err_field" 2 '=')" | |
126 | text="$(_getfield "$txt_field" 2 '=')" | |
127 | details="$(_getfield "$details_field" 2 '=')" | |
128 | _debug "error: ${error}, text: ${text}, details: ${details}" | |
129 | if [ "$error" != "0" ]; then | |
130 | _err "error $response" | |
131 | return 1 | |
132 | fi | |
133 | ;; | |
134 | CMD_API_SHOW_DOMAINS) ;; | |
14c27554 T |
135 | esac |
136 | return 0 | |
137 | } | |
138 | ||
139 | # Usage: _DA_getDomainInfo | |
140 | # Get the root zone if possible | |
141 | _DA_getDomainInfo() { | |
142 | _debug "First detect the root zone" | |
143 | if ! _get_root "$fulldomain"; then | |
144 | _err "invalid domain" | |
145 | return 1 | |
146 | else | |
147 | _debug "The root domain: $_domain" | |
148 | _debug "The sub domain: $_sub_domain" | |
149 | fi | |
150 | return 0 | |
151 | } | |
152 | ||
153 | # Usage: _DA_addTxt | |
154 | # Use the API to add a record | |
155 | _DA_addTxt() { | |
156 | curData="domain=${_domain}&action=add&type=TXT&name=${_sub_domain}&value=\"${txtvalue}\"" | |
157 | _debug "Calling _DA_addTxt: '${curData}' '${DA_Api}/CMD_API_DNS_CONTROL'" | |
399d6592 | 158 | _da_api CMD_API_DNS_CONTROL "${curData}" "${_domain}" |
14c27554 T |
159 | _debug "Result of _DA_addTxt: '$response'" |
160 | if _contains "${response}" 'error=0'; then | |
161 | _debug "Add TXT succeeded" | |
162 | return 0 | |
163 | fi | |
164 | _debug "Add TXT failed" | |
165 | return 1 | |
166 | } | |
167 | ||
168 | # Usage: _DA_rmTxt | |
169 | # Use the API to remove a record | |
170 | _DA_rmTxt() { | |
171 | curData="domain=${_domain}&action=select&txtrecs0=name=${_sub_domain}&value=\"${txtvalue}\"" | |
172 | _debug "Calling _DA_rmTxt: '${curData}' '${DA_Api}/CMD_API_DNS_CONTROL'" | |
399d6592 | 173 | if _da_api CMD_API_DNS_CONTROL "${curData}" "${_domain}"; then |
14c27554 T |
174 | _debug "Result of _DA_rmTxt: '$response'" |
175 | else | |
176 | _err "Result of _DA_rmTxt: '$response'" | |
177 | fi | |
178 | if _contains "${response}" 'error=0'; then | |
179 | _debug "RM TXT succeeded" | |
180 | return 0 | |
181 | fi | |
182 | _debug "RM TXT failed" | |
183 | return 1 | |
184 | } |