Hunter0x7c7
2022-08-11 708a5ba64e1ac19cd3d007edb36a471a7863589b
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
#!/usr/bin/env sh
 
# Author: Radek Sprta <sprta@vshosting.cz>
 
#CLOUDDNS_EMAIL=XXXXX
#CLOUDDNS_PASSWORD="YYYYYYYYY"
#CLOUDDNS_CLIENT_ID=XXXXX
 
CLOUDDNS_API='https://admin.vshosting.cloud/clouddns'
CLOUDDNS_LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'
 
########  Public functions #####################
 
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_clouddns_add() {
  fulldomain=$1
  txtvalue=$2
  _debug "fulldomain" "$fulldomain"
 
  CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
  CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
  CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
 
  if [ -z "$CLOUDDNS_PASSWORD" ] || [ -z "$CLOUDDNS_EMAIL" ] || [ -z "$CLOUDDNS_CLIENT_ID" ]; then
    CLOUDDNS_CLIENT_ID=""
    CLOUDDNS_EMAIL=""
    CLOUDDNS_PASSWORD=""
    _err "You didn't specify a CloudDNS password, email and client ID yet."
    return 1
  fi
  if ! _contains "$CLOUDDNS_EMAIL" "@"; then
    _err "It seems that the CLOUDDNS_EMAIL=$CLOUDDNS_EMAIL is not a valid email address."
    _err "Please check and retry."
    return 1
  fi
  # Save CloudDNS client id, email and password to config file
  _saveaccountconf_mutable CLOUDDNS_CLIENT_ID "$CLOUDDNS_CLIENT_ID"
  _saveaccountconf_mutable CLOUDDNS_EMAIL "$CLOUDDNS_EMAIL"
  _saveaccountconf_mutable CLOUDDNS_PASSWORD "$CLOUDDNS_PASSWORD"
 
  _debug "First detect the root zone"
  if ! _get_root "$fulldomain"; then
    _err "Invalid domain"
    return 1
  fi
  _debug _domain_id "$_domain_id"
  _debug _sub_domain "$_sub_domain"
  _debug _domain "$_domain"
 
  # Add TXT record
  data="{\"type\":\"TXT\",\"name\":\"$fulldomain.\",\"value\":\"$txtvalue\",\"domainId\":\"$_domain_id\"}"
  if _clouddns_api POST "record-txt" "$data"; then
    if _contains "$response" "$txtvalue"; then
      _info "Added, OK"
    elif _contains "$response" '"code":4136'; then
      _info "Already exists, OK"
    else
      _err "Add TXT record error."
      return 1
    fi
  fi
 
  _debug "Publishing record changes"
  _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
}
 
# Usage: rm _acme-challenge.www.domain.com
dns_clouddns_rm() {
  fulldomain=$1
  _debug "fulldomain" "$fulldomain"
 
  CLOUDDNS_CLIENT_ID="${CLOUDDNS_CLIENT_ID:-$(_readaccountconf_mutable CLOUDDNS_CLIENT_ID)}"
  CLOUDDNS_EMAIL="${CLOUDDNS_EMAIL:-$(_readaccountconf_mutable CLOUDDNS_EMAIL)}"
  CLOUDDNS_PASSWORD="${CLOUDDNS_PASSWORD:-$(_readaccountconf_mutable CLOUDDNS_PASSWORD)}"
 
  _debug "First detect the root zone"
  if ! _get_root "$fulldomain"; then
    _err "Invalid domain"
    return 1
  fi
  _debug _domain_id "$_domain_id"
  _debug _sub_domain "$_sub_domain"
  _debug _domain "$_domain"
 
  # Get record ID
  _clouddns_api GET "domain/$_domain_id"
  if _contains "$response" "lastDomainRecordList"; then
    re="\"lastDomainRecordList\".*\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
    _last_domains=$(echo "$response" | _egrep_o "$re")
    re2="\"id\":\"([^\"}]*)\"[^}]*\"name\":\"$fulldomain.\","
    _record_id=$(echo "$_last_domains" | _egrep_o "$re2" | _head_n 1 | cut -d : -f 2 | cut -d , -f 1 | tr -d "\"")
    _debug _record_id "$_record_id"
  else
    _err "Could not retrieve record ID"
    return 1
  fi
 
  _info "Removing record"
  if _clouddns_api DELETE "record/$_record_id"; then
    if _contains "$response" "\"error\":"; then
      _err "Could not remove record"
      return 1
    fi
  fi
 
  _debug "Publishing record changes"
  _clouddns_api PUT "domain/$_domain_id/publish" "{\"soaTtl\":300}"
}
 
####################  Private functions below ##################################
 
# Usage: _get_root _acme-challenge.www.domain.com
# Returns:
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
  domain=$1
 
  # Get domain root
  data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}]}"
  _clouddns_api "POST" "domain/search" "$data"
  domain_slice="$domain"
  while [ -z "$domain_root" ]; do
    if _contains "$response" "\"domainName\":\"$domain_slice\.\""; then
      domain_root="$domain_slice"
      _debug domain_root "$domain_root"
    fi
    domain_slice="$(echo "$domain_slice" | cut -d . -f 2-)"
  done
 
  # Get domain id
  data="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$CLOUDDNS_CLIENT_ID\"}, \
      {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}"
  _clouddns_api "POST" "domain/search" "$data"
  if _contains "$response" "\"id\":\""; then
    re='domainType\":\"[^\"]*\",\"id\":\"([^\"]*)\",' # Match domain id
    _domain_id=$(echo "$response" | _egrep_o "$re" | _head_n 1 | cut -d : -f 3 | tr -d "\",")
    if [ "$_domain_id" ]; then
      _sub_domain=$(printf "%s" "$domain" | sed "s/.$domain_root//")
      _domain="$domain_root"
      return 0
    fi
    _err 'Domain name not found on your CloudDNS account'
    return 1
  fi
  return 1
}
 
# Usage: _clouddns_api GET domain/search '{"data": "value"}'
# Returns:
#  response='{"message": "api response"}'
_clouddns_api() {
  method=$1
  endpoint="$2"
  data="$3"
  _debug endpoint "$endpoint"
 
  if [ -z "$CLOUDDNS_TOKEN" ]; then
    _clouddns_login
  fi
  _debug CLOUDDNS_TOKEN "$CLOUDDNS_TOKEN"
 
  export _H1="Content-Type: application/json"
  export _H2="Authorization: Bearer $CLOUDDNS_TOKEN"
 
  if [ "$method" != "GET" ]; then
    _debug data "$data"
    response="$(_post "$data" "$CLOUDDNS_API/$endpoint" "" "$method" | tr -d '\t\r\n ')"
  else
    response="$(_get "$CLOUDDNS_API/$endpoint" | tr -d '\t\r\n ')"
  fi
 
  # shellcheck disable=SC2181
  if [ "$?" != "0" ]; then
    _err "Error $endpoint"
    return 1
  fi
  _debug2 response "$response"
  return 0
}
 
# Returns:
#  CLOUDDNS_TOKEN=dslfje2rj23l
_clouddns_login() {
  login_data="{\"email\": \"$CLOUDDNS_EMAIL\", \"password\": \"$CLOUDDNS_PASSWORD\"}"
  response="$(_post "$login_data" "$CLOUDDNS_LOGIN_API" "" "POST" "Content-Type: application/json")"
 
  if _contains "$response" "\"accessToken\":\""; then
    CLOUDDNS_TOKEN=$(echo "$response" | _egrep_o "\"accessToken\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
    export CLOUDDNS_TOKEN
  else
    echo 'Could not get CloudDNS access token; check your credentials'
    return 1
  fi
  return 0
}