Skip to content

Commit d8053ed

Browse files
authored
Merge pull request #6760 from OpusDNS/add-opusdns-provider
[CLOUD-31] Add acme.sh OpusDNS provider
2 parents e44809c + 9c245eb commit d8053ed

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

dnsapi/dns_opusdns.sh

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#!/usr/bin/env sh
2+
3+
# shellcheck disable=SC2034
4+
dns_opusdns_info='OpusDNS.com
5+
Site: OpusDNS.com
6+
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_opusdns
7+
Options:
8+
OPUSDNS_API_Key API Key. Can be created at https://dashboard.opusdns.com/settings/api-keys
9+
OPUSDNS_API_Endpoint API Endpoint URL. Default "https://api.opusdns.com". Optional.
10+
OPUSDNS_TTL TTL for DNS challenge records in seconds. Default "60". Optional.
11+
Issues: github.com/acmesh-official/acme.sh/issues/XXXX
12+
Author: OpusDNS Team <https://github.com/opusdns>
13+
'
14+
15+
OPUSDNS_API_Endpoint_Default="https://api.opusdns.com"
16+
OPUSDNS_TTL_Default=60
17+
18+
######## Public functions ###########
19+
20+
# Add DNS TXT record
21+
dns_opusdns_add() {
22+
fulldomain=$1
23+
txtvalue=$2
24+
25+
_info "Using OpusDNS DNS API"
26+
_debug fulldomain "$fulldomain"
27+
_debug txtvalue "$txtvalue"
28+
29+
if ! _opusdns_init; then
30+
return 1
31+
fi
32+
33+
if ! _get_zone "$fulldomain"; then
34+
return 1
35+
fi
36+
37+
_info "Zone: $_zone, Record: $_record_name"
38+
39+
if ! _opusdns_api PATCH "/v1/dns/$_zone/records" "{\"ops\":[{\"op\":\"upsert\",\"record\":{\"name\":\"$_record_name\",\"type\":\"TXT\",\"ttl\":$OPUSDNS_TTL,\"rdata\":\"\\\"$txtvalue\\\"\"}}]}"; then
40+
_err "Failed to add TXT record"
41+
return 1
42+
fi
43+
44+
_info "TXT record added successfully"
45+
return 0
46+
}
47+
48+
# Remove DNS TXT record
49+
dns_opusdns_rm() {
50+
fulldomain=$1
51+
txtvalue=$2
52+
53+
_info "Removing OpusDNS DNS record"
54+
_debug fulldomain "$fulldomain"
55+
_debug txtvalue "$txtvalue"
56+
57+
if ! _opusdns_init; then
58+
return 1
59+
fi
60+
61+
if ! _get_zone "$fulldomain"; then
62+
_err "Zone not found, cleanup skipped"
63+
return 0
64+
fi
65+
66+
_info "Zone: $_zone, Record: $_record_name"
67+
68+
if ! _opusdns_api PATCH "/v1/dns/$_zone/records" "{\"ops\":[{\"op\":\"remove\",\"record\":{\"name\":\"$_record_name\",\"type\":\"TXT\",\"ttl\":$OPUSDNS_TTL,\"rdata\":\"\\\"$txtvalue\\\"\"}}]}"; then
69+
_err "Warning: Failed to remove TXT record"
70+
return 0
71+
fi
72+
73+
_info "TXT record removed successfully"
74+
return 0
75+
}
76+
77+
######## Private functions ###########
78+
79+
# Initialize and validate configuration
80+
_opusdns_init() {
81+
OPUSDNS_API_Key="${OPUSDNS_API_Key:-$(_readaccountconf_mutable OPUSDNS_API_Key)}"
82+
OPUSDNS_API_Endpoint="${OPUSDNS_API_Endpoint:-$(_readaccountconf_mutable OPUSDNS_API_Endpoint)}"
83+
OPUSDNS_TTL="${OPUSDNS_TTL:-$(_readaccountconf_mutable OPUSDNS_TTL)}"
84+
85+
if [ -z "$OPUSDNS_API_Key" ]; then
86+
_err "OPUSDNS_API_Key not set"
87+
return 1
88+
fi
89+
90+
[ -z "$OPUSDNS_API_Endpoint" ] && OPUSDNS_API_Endpoint="$OPUSDNS_API_Endpoint_Default"
91+
[ -z "$OPUSDNS_TTL" ] && OPUSDNS_TTL="$OPUSDNS_TTL_Default"
92+
93+
_saveaccountconf_mutable OPUSDNS_API_Key "$OPUSDNS_API_Key"
94+
_saveaccountconf_mutable OPUSDNS_API_Endpoint "$OPUSDNS_API_Endpoint"
95+
_saveaccountconf_mutable OPUSDNS_TTL "$OPUSDNS_TTL"
96+
97+
_debug "Endpoint: $OPUSDNS_API_Endpoint"
98+
return 0
99+
}
100+
101+
# Make API request
102+
# Usage: _opusdns_api METHOD PATH [DATA]
103+
_opusdns_api() {
104+
method=$1
105+
path=$2
106+
data=$3
107+
108+
export _H1="X-Api-Key: $OPUSDNS_API_Key"
109+
export _H2="Content-Type: application/json"
110+
111+
url="$OPUSDNS_API_Endpoint$path"
112+
_debug2 "API: $method $url"
113+
[ -n "$data" ] && _debug2 "Data: $data"
114+
115+
if [ -n "$data" ]; then
116+
response=$(_post "$data" "$url" "" "$method")
117+
else
118+
response=$(_get "$url")
119+
fi
120+
121+
if [ $? -ne 0 ]; then
122+
_err "API request failed"
123+
_debug "Response: $response"
124+
return 1
125+
fi
126+
127+
_debug2 "Response: $response"
128+
return 0
129+
}
130+
131+
# Detect zone from FQDN
132+
# Sets: _zone, _record_name
133+
_get_zone() {
134+
domain=$(echo "$1" | sed 's/\.$//')
135+
_debug "Finding zone for: $domain"
136+
137+
i=1
138+
p=1
139+
while true; do
140+
h=$(printf "%s" "$domain" | cut -d . -f "$i"-100)
141+
142+
if [ -z "$h" ]; then
143+
_err "No valid zone found for: $domain"
144+
return 1
145+
fi
146+
147+
_debug "Trying: $h"
148+
if _opusdns_api GET "/v1/dns/$h" && _contains "$response" '"dnssec_status"'; then
149+
_zone="$h"
150+
_record_name=$(printf "%s" "$domain" | cut -d . -f 1-"$p")
151+
[ -z "$_record_name" ] && _record_name="@"
152+
return 0
153+
fi
154+
155+
p="$i"
156+
i=$(_math "$i" + 1)
157+
done
158+
}

0 commit comments

Comments
 (0)