[go: up one dir, main page]

File: dns_dynv6.sh

package info (click to toggle)
acme.sh 3.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,704 kB
  • sloc: sh: 36,037; makefile: 12
file content (291 lines) | stat: -rw-r--r-- 9,037 bytes parent folder | download
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
289
290
291
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_dynv6_info='DynV6.com
Site: DynV6.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_dynv6
Options:
 DYNV6_TOKEN REST API token. Get from https://DynV6.com/keys
OptionsAlt:
 KEY Path to SSH private key file. E.g. "/root/.ssh/dynv6"
Issues: github.com/acmesh-official/acme.sh/issues/2702
Author: StefanAbl
'

dynv6_api="https://dynv6.com/api/v2"
########  Public functions #####################
# Please Read this guide first: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
#Usage: dns_dynv6_add  _acme-challenge.www.domain.com  "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_dynv6_add() {
  fulldomain="$(echo "$1" | _lower_case)"
  txtvalue="$2"
  _info "Using dynv6 api"
  _debug fulldomain "$fulldomain"
  _debug txtvalue "$txtvalue"
  _get_authentication
  if [ "$dynv6_token" ]; then
    _dns_dynv6_add_http
    return $?
  else
    _info "using key file $dynv6_keyfile"
    _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
    if ! _get_domain "$fulldomain" "$_your_hosts"; then
      _err "Host not found on your account"
      return 1
    fi
    _debug "found host on your account"
    returnval="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts \""$_host"\" records set \""$_record"\" txt data \""$txtvalue"\")"
    _debug "Dynv6 returned this after record was added: $returnval"
    if _contains "$returnval" "created"; then
      return 0
    elif _contains "$returnval" "updated"; then
      return 0
    else
      _err "Something went wrong! it does not seem like the record was added successfully"
      return 1
    fi
  fi

}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_dynv6_rm() {
  fulldomain="$(echo "$1" | _lower_case)"
  txtvalue="$2"
  _info "Using dynv6 API"
  _debug fulldomain "$fulldomain"
  _debug txtvalue "$txtvalue"
  _get_authentication
  if [ "$dynv6_token" ]; then
    _dns_dynv6_rm_http
    return $?
  else
    _info "using key file $dynv6_keyfile"
    _your_hosts="$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts)"
    if ! _get_domain "$fulldomain" "$_your_hosts"; then
      _err "Host not found on your account"
      return 1
    fi
    _debug "found host on your account"
    _info "$(ssh -i "$dynv6_keyfile" api@dynv6.com hosts "\"$_host\"" records del "\"$_record\"" txt)"
    return 0
  fi
}
#################### Private functions below ##################################
#Usage: No Input required
#returns
#dynv6_keyfile the path to the new key file that has been generated
_generate_new_key() {
  dynv6_keyfile="$(eval echo ~"$USER")/.ssh/dynv6"
  _info "Path to key file used: $dynv6_keyfile"
  if [ ! -f "$dynv6_keyfile" ] && [ ! -f "$dynv6_keyfile.pub" ]; then
    _debug "generating key in $dynv6_keyfile and $dynv6_keyfile.pub"
    ssh-keygen -f "$dynv6_keyfile" -t ssh-ed25519 -N ''
  else
    _err "There is already a file in $dynv6_keyfile or $dynv6_keyfile.pub"
    return 1
  fi
}

#Usage: _acme-challenge.www.example.dynv6.net "$_your_hosts"
#where _your_hosts is the output of ssh -i ~/.ssh/dynv6.pub api@dynv6.com hosts
#returns
#_host= example.dynv6.net
#_record=_acme-challenge.www
#aborts if not a valid domain
_get_domain() {
  #_your_hosts="$(ssh -i ~/.ssh/dynv6.pub api@dynv6.com hosts)"
  _full_domain="$1"
  _your_hosts="$2"

  _your_hosts="$(echo "$_your_hosts" | awk '/\./ {print $1}')"
  for l in $_your_hosts; do
    #echo "host: $l"
    if test "${_full_domain#*"$l"}" != "$_full_domain"; then
      _record=${_full_domain%."$l"}
      _host=$l
      _debug "The host is $_host and the record $_record"
      return 0
    fi
  done
  _err "Either their is no such host on your dnyv6 account or it cannot be accessed with this key"
  return 1
}

# Usage: No input required
#returns
#dynv6_keyfile path to the key that will be used
_get_authentication() {
  dynv6_token="${DYNV6_TOKEN:-$(_readaccountconf_mutable dynv6_token)}"
  if [ "$dynv6_token" ]; then
    _debug "Found HTTP Token. Going to use the HTTP API and not the SSH API"
    if [ "$DYNV6_TOKEN" ]; then
      _saveaccountconf_mutable dynv6_token "$dynv6_token"
    fi
  else
    _debug "no HTTP token found. Looking for an SSH key"
    dynv6_keyfile="${dynv6_keyfile:-$(_readaccountconf_mutable dynv6_keyfile)}"
    _debug "Your key is $dynv6_keyfile"
    if [ -z "$dynv6_keyfile" ]; then
      if [ -z "$KEY" ]; then
        _err "You did not specify a key to use with dynv6"
        _info "Creating new dynv6 API key to add to dynv6.com"
        _generate_new_key
        _info "Please add this key to dynv6.com $(cat "$dynv6_keyfile.pub")"
        _info "Hit Enter to continue"
        read -r _
        #save the credentials to the account conf file.
      else
        dynv6_keyfile="$KEY"
      fi
      _saveaccountconf_mutable dynv6_keyfile "$dynv6_keyfile"
    fi
  fi
}

_dns_dynv6_add_http() {
  _debug "Got HTTP token form _get_authentication method. Going to use the HTTP API"
  if ! _get_zone_id "$fulldomain"; then
    _err "Could not find a matching zone for $fulldomain. Maybe your HTTP Token is not authorized to access the zone"
    return 1
  fi
  _get_zone_name "$_zone_id"
  record=${fulldomain%%."$_zone_name"}
  _set_record TXT "$record" "$txtvalue"
  if _contains "$response" "$txtvalue"; then
    _info "Successfully added record"
    return 0
  else
    _err "Something went wrong while adding the record"
    return 1
  fi
}

_dns_dynv6_rm_http() {
  _debug "Got HTTP token form _get_authentication method. Going to use the HTTP API"
  if ! _get_zone_id "$fulldomain"; then
    _err "Could not find a matching zone for $fulldomain. Maybe your HTTP Token is not authorized to access the zone"
    return 1
  fi
  _get_zone_name "$_zone_id"
  record=${fulldomain%%."$_zone_name"}
  _get_record_id "$_zone_id" "$record" "$txtvalue"
  _del_record "$_zone_id" "$_record_id"
  if [ -z "$response" ]; then
    _info "Successfully deleted record"
    return 0
  else
    _err "Something went wrong while deleting the record"
    return 1
  fi
}

#get the zoneid for a specifc record or zone
#usage: _get_zone_id §record
#where $record is the record to get the id for
#returns _zone_id the id of the zone
_get_zone_id() {
  record="$1"
  _debug "getting zone id for $record"
  _dynv6_rest GET zones

  zones="$(echo "$response" | tr '}' '\n' | tr ',' '\n' | grep name | sed 's/\[//g' | tr -d '{' | tr -d '"')"
  #echo $zones

  selected=""
  for z in $zones; do
    z="${z#name:}"
    _debug zone: "$z"
    if _contains "$record" "$z"; then
      _debug "$z found in $record"
      selected="$z"
    fi
  done
  if [ -z "$selected" ]; then
    _err "no zone found"
    return 1
  fi

  zone_id="$(echo "$response" | tr '}' '\n' | grep "$selected" | tr ',' '\n' | grep '"id":' | tr -d '"')"
  _zone_id="${zone_id#id:}"
  _debug "zone id: $_zone_id"
}

_get_zone_name() {
  _zone_id="$1"
  _dynv6_rest GET zones/"$_zone_id"
  _zone_name="$(echo "$response" | tr ',' '\n' | tr -d '{' | grep name | tr -d '"')"
  _zone_name="${_zone_name#name:}"
}

#usaage _get_record_id $zone_id $record
# where zone_id is thevalue returned by _get_zone_id
# and record ist in the form _acme.www for an fqdn of _acme.www.example.com
# returns _record_id
_get_record_id() {
  _zone_id="$1"
  record="$2"
  value="$3"
  _dynv6_rest GET "zones/$_zone_id/records"
  if ! _get_record_id_from_response "$response"; then
    _err "no such record $record found in zone $_zone_id"
    return 1
  fi
}

_get_record_id_from_response() {
  response="$1"
  _record_id="$(echo "$response" | tr '}' '\n' | grep "\"name\":\"$record\"" | grep "\"data\":\"$value\"" | tr ',' '\n' | grep id | tr -d '"' | tr -d 'id:')"
  #_record_id="${_record_id#id:}"
  if [ -z "$_record_id" ]; then
    _err "no such record: $record found in zone $_zone_id"
    return 1
  fi
  _debug "record id: $_record_id"
  return 0
}
#usage: _set_record TXT _acme_challenge.www longvalue 12345678
#zone id is optional can also be set as vairable bevor calling this method
_set_record() {
  type="$1"
  record="$2"
  value="$3"
  if [ "$4" ]; then
    _zone_id="$4"
  fi
  data="{\"name\": \"$record\", \"data\": \"$value\", \"type\": \"$type\"}"
  #data='{ "name": "acme.test.thorn.dynv6.net", "type": "A", "data": "192.168.0.1"}'
  echo "$data"
  #"{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":120}"
  _dynv6_rest POST "zones/$_zone_id/records" "$data"
}
_del_record() {
  _zone_id=$1
  _record_id=$2
  _dynv6_rest DELETE zones/"$_zone_id"/records/"$_record_id"
}

_dynv6_rest() {
  m=$1    #method GET,POST,DELETE or PUT
  ep="$2" #the endpoint
  data="$3"
  _debug "$ep"

  token_trimmed=$(echo "$dynv6_token" | tr -d '"')

  export _H1="Authorization: Bearer $token_trimmed"
  export _H2="Content-Type: application/json"

  if [ "$m" != "GET" ]; then
    _debug data "$data"
    response="$(_post "$data" "$dynv6_api/$ep" "" "$m")"
  else
    response="$(_get "$dynv6_api/$ep")"
  fi

  if [ "$?" != "0" ]; then
    _err "error $ep"
    return 1
  fi
  _debug2 response "$response"
  return 0
}