]>
Commit | Line | Data |
---|---|---|
d30b441e TC |
1 | #!/usr/bin/env sh |
2 | # | |
3 | # | |
4 | #RACKSPACE_Username="" | |
5 | # | |
6 | #RACKSPACE_Apikey="" | |
7 | ||
8 | RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0" | |
9 | ||
10 | # 20190213 - The name & id fields swapped in the API response; fix sed | |
11 | # 20190101 - Duplicating file for new pull request to dev branch | |
d795fac3 | 12 | # Original - tcocca:rackspace_dnsapi https://github.com/acmesh-official/acme.sh/pull/1297 |
d30b441e TC |
13 | |
14 | ######## Public functions ##################### | |
15 | #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | |
16 | dns_rackspace_add() { | |
17 | fulldomain="$1" | |
18 | _debug fulldomain="$fulldomain" | |
19 | txtvalue="$2" | |
20 | _debug txtvalue="$txtvalue" | |
21 | _rackspace_check_auth || return 1 | |
22 | _rackspace_check_rootzone || return 1 | |
23 | _info "Creating TXT record." | |
24 | if ! _rackspace_rest POST "$RACKSPACE_Tenant/domains/$_domain_id/records" "{\"records\":[{\"name\":\"$fulldomain\",\"type\":\"TXT\",\"data\":\"$txtvalue\",\"ttl\":300}]}"; then | |
25 | return 1 | |
26 | fi | |
27 | _debug2 response "$response" | |
28 | if ! _contains "$response" "$txtvalue" >/dev/null; then | |
29 | _err "Could not add TXT record." | |
30 | return 1 | |
31 | fi | |
32 | return 0 | |
33 | } | |
34 | ||
35 | #fulldomain txtvalue | |
36 | dns_rackspace_rm() { | |
37 | fulldomain=$1 | |
38 | _debug fulldomain="$fulldomain" | |
39 | txtvalue=$2 | |
40 | _debug txtvalue="$txtvalue" | |
41 | _rackspace_check_auth || return 1 | |
42 | _rackspace_check_rootzone || return 1 | |
43 | _info "Checking for TXT record." | |
44 | if ! _get_recordid "$_domain_id" "$fulldomain" "$txtvalue"; then | |
45 | _err "Could not get TXT record id." | |
46 | return 1 | |
47 | fi | |
48 | if [ "$_dns_record_id" = "" ]; then | |
49 | _err "TXT record not found." | |
50 | return 1 | |
51 | fi | |
52 | _info "Removing TXT record." | |
53 | if ! _delete_txt_record "$_domain_id" "$_dns_record_id"; then | |
54 | _err "Could not remove TXT record $_dns_record_id." | |
55 | fi | |
56 | return 0 | |
57 | } | |
58 | ||
59 | #################### Private functions below ################################## | |
60 | #_acme-challenge.www.domain.com | |
61 | #returns | |
62 | # _sub_domain=_acme-challenge.www | |
63 | # _domain=domain.com | |
64 | # _domain_id=sdjkglgdfewsdfg | |
65 | _get_root_zone() { | |
66 | domain="$1" | |
67 | i=2 | |
68 | p=1 | |
69 | while true; do | |
70 | h=$(printf "%s" "$domain" | cut -d . -f $i-100) | |
71 | _debug h "$h" | |
72 | if [ -z "$h" ]; then | |
73 | #not valid | |
74 | return 1 | |
75 | fi | |
8b3d792b | 76 | if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains/search?name=$h"; then |
d30b441e TC |
77 | return 1 |
78 | fi | |
79 | _debug2 response "$response" | |
80 | if _contains "$response" "\"name\":\"$h\"" >/dev/null; then | |
81 | # Response looks like: | |
82 | # {"ttl":300,"accountId":12345,"id":1111111,"name":"example.com","emailAddress": ...<and so on> | |
83 | _domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\([^,]*\),\"name\":\"$h\",.*/\1/p") | |
84 | _debug2 domain_id "$_domain_id" | |
85 | if [ -n "$_domain_id" ]; then | |
86 | _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | |
87 | _domain=$h | |
88 | return 0 | |
89 | fi | |
90 | return 1 | |
91 | fi | |
92 | p=$i | |
93 | i=$(_math "$i" + 1) | |
94 | done | |
95 | return 1 | |
96 | } | |
97 | ||
98 | _get_recordid() { | |
99 | domainid="$1" | |
100 | fulldomain="$2" | |
101 | txtvalue="$3" | |
102 | if ! _rackspace_rest GET "$RACKSPACE_Tenant/domains/$domainid/records?name=$fulldomain&type=TXT"; then | |
103 | return 1 | |
104 | fi | |
105 | _debug response "$response" | |
106 | if ! _contains "$response" "$txtvalue"; then | |
107 | _dns_record_id=0 | |
108 | return 0 | |
109 | fi | |
110 | _dns_record_id=$(echo "$response" | tr '{' "\n" | grep "\"data\":\"$txtvalue\"" | sed -n 's/^.*"id":"\([^"]*\)".*/\1/p') | |
111 | _debug _dns_record_id "$_dns_record_id" | |
112 | return 0 | |
113 | } | |
114 | ||
115 | _delete_txt_record() { | |
116 | domainid="$1" | |
117 | _dns_record_id="$2" | |
118 | if ! _rackspace_rest DELETE "$RACKSPACE_Tenant/domains/$domainid/records?id=$_dns_record_id"; then | |
119 | return 1 | |
120 | fi | |
121 | _debug response "$response" | |
122 | if ! _contains "$response" "RUNNING"; then | |
123 | return 1 | |
124 | fi | |
125 | return 0 | |
126 | } | |
127 | ||
128 | _rackspace_rest() { | |
129 | m="$1" | |
130 | ep="$2" | |
131 | data="$3" | |
132 | _debug ep "$ep" | |
133 | export _H1="Accept: application/json" | |
134 | export _H2="X-Auth-Token: $RACKSPACE_Token" | |
135 | export _H3="X-Project-Id: $RACKSPACE_Tenant" | |
136 | export _H4="Content-Type: application/json" | |
137 | if [ "$m" != "GET" ]; then | |
138 | _debug data "$data" | |
139 | response="$(_post "$data" "$RACKSPACE_Endpoint/$ep" "" "$m")" | |
140 | retcode=$? | |
141 | else | |
142 | _info "Getting $RACKSPACE_Endpoint/$ep" | |
143 | response="$(_get "$RACKSPACE_Endpoint/$ep")" | |
144 | retcode=$? | |
145 | fi | |
146 | ||
147 | if [ "$retcode" != "0" ]; then | |
148 | _err "error $ep" | |
149 | return 1 | |
150 | fi | |
151 | _debug2 response "$response" | |
152 | return 0 | |
153 | } | |
154 | ||
155 | _rackspace_authorization() { | |
156 | export _H1="Content-Type: application/json" | |
157 | data="{\"auth\":{\"RAX-KSKEY:apiKeyCredentials\":{\"username\":\"$RACKSPACE_Username\",\"apiKey\":\"$RACKSPACE_Apikey\"}}}" | |
158 | _debug data "$data" | |
159 | response="$(_post "$data" "https://identity.api.rackspacecloud.com/v2.0/tokens" "" "POST")" | |
160 | retcode=$? | |
161 | _debug2 response "$response" | |
162 | if [ "$retcode" != "0" ]; then | |
163 | _err "Authentication failed." | |
164 | return 1 | |
165 | fi | |
166 | if _contains "$response" "token"; then | |
167 | RACKSPACE_Token="$(echo "$response" | _normalizeJson | sed -n 's/^.*"token":{.*,"id":"\([^"]*\)",".*/\1/p')" | |
168 | RACKSPACE_Tenant="$(echo "$response" | _normalizeJson | sed -n 's/^.*"token":{.*,"id":"\([^"]*\)"}.*/\1/p')" | |
169 | _debug RACKSPACE_Token "$RACKSPACE_Token" | |
170 | _debug RACKSPACE_Tenant "$RACKSPACE_Tenant" | |
171 | fi | |
172 | return 0 | |
173 | } | |
174 | ||
175 | _rackspace_check_auth() { | |
176 | # retrieve the rackspace creds | |
177 | RACKSPACE_Username="${RACKSPACE_Username:-$(_readaccountconf_mutable RACKSPACE_Username)}" | |
178 | RACKSPACE_Apikey="${RACKSPACE_Apikey:-$(_readaccountconf_mutable RACKSPACE_Apikey)}" | |
179 | # check their vals for null | |
180 | if [ -z "$RACKSPACE_Username" ] || [ -z "$RACKSPACE_Apikey" ]; then | |
181 | RACKSPACE_Username="" | |
182 | RACKSPACE_Apikey="" | |
183 | _err "You didn't specify a Rackspace username and api key." | |
184 | _err "Please set those values and try again." | |
185 | return 1 | |
186 | fi | |
187 | # save the username and api key to the account conf file. | |
188 | _saveaccountconf_mutable RACKSPACE_Username "$RACKSPACE_Username" | |
189 | _saveaccountconf_mutable RACKSPACE_Apikey "$RACKSPACE_Apikey" | |
190 | if [ -z "$RACKSPACE_Token" ]; then | |
191 | _info "Getting authorization token." | |
192 | if ! _rackspace_authorization; then | |
193 | _err "Can not get token." | |
194 | fi | |
195 | fi | |
196 | } | |
197 | ||
198 | _rackspace_check_rootzone() { | |
199 | _debug "First detect the root zone" | |
200 | if ! _get_root_zone "$fulldomain"; then | |
201 | _err "invalid domain" | |
202 | return 1 | |
203 | fi | |
204 | _debug _domain_id "$_domain_id" | |
205 | _debug _sub_domain "$_sub_domain" | |
206 | _debug _domain "$_domain" | |
207 | } |