Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: DNS API for IONOS cloud #5110

Merged
merged 22 commits into from
Jun 15, 2024
Merged
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ebaa39b
Merge pull request #5075 from acmesh-official/dev
Neilpang Apr 1, 2024
bc90376
Merge pull request #5102 from acmesh-official/dev
Neilpang Apr 21, 2024
0d8a314
Merge pull request #5123 from acmesh-official/dev
Neilpang Apr 29, 2024
3ae4ba3
dns_ionos.sh: implement dns_ionos_add for ionos cloud
zak905 Apr 18, 2024
f35e152
implement dns_ionos_rm function
zak905 Apr 22, 2024
ff357dd
fix syntax error
zak905 Apr 22, 2024
dc29799
fix zone search
zak905 Apr 24, 2024
96c35b4
fix TXT record lookup and removal
zak905 Apr 24, 2024
ffde1f8
linting based on ShellCheck results
zak905 Apr 25, 2024
30d0945
fix regexp for findind acme challenge record from API response
zak905 Apr 30, 2024
d852549
attempt to use custom fork of acmetest
zak905 Apr 30, 2024
b7b1714
add some debug statements
zak905 Apr 30, 2024
c64aae6
more debugging - add function argument printing
zak905 Apr 30, 2024
0974c74
transform record name to lower case when searching for TXT record
zak905 Apr 30, 2024
adc8031
fix shell linter and formating
zak905 Apr 30, 2024
c3cc135
use posix compliant lower case shell command
zak905 May 2, 2024
52d1d42
escape brackets in regexp and format using shfmt
zak905 May 3, 2024
373c2b3
remove debug print statements and usage of custom fork of acmetest
zak905 May 6, 2024
f440656
create new script for ionos cloud and rollback changes to dns_ionos.sh
zak905 May 14, 2024
2797d2c
fix add and rm method names
zak905 May 14, 2024
cc9c85c
use lower_case util function instead of raw bash command
zak905 Jun 9, 2024
74ffbb2
fix forgotten parenthensis
zak905 Jun 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions dnsapi/dns_ionos_cloud.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/usr/bin/env sh

# Supports IONOS Cloud DNS API v1.15.4
#
# Usage:
# Export IONOS_TOKEN before calling acme.sh:
# $ export IONOS_TOKEN="..."
#
# $ acme.sh --issue --dns dns_ionos_cloud ...

IONOS_CLOUD_API="https://dns.de-fra.ionos.com"
IONOS_CLOUD_ROUTE_ZONES="/zones"

dns_ionos_cloud_add() {
fulldomain=$1
txtvalue=$2

if ! _ionos_init; then
return 1
fi

_record_name=$(printf "%s" "$fulldomain" | cut -d . -f 1)
_body="{\"properties\":{\"name\":\"$_record_name\", \"type\":\"TXT\", \"content\":\"$txtvalue\"}}"

if _ionos_cloud_rest POST "$IONOS_CLOUD_ROUTE_ZONES/$_zone_id/records" "$_body" && [ "$_code" = "202" ]; then
_info "TXT record has been created successfully."
return 0
fi

return 1
}

dns_ionos_cloud_rm() {
fulldomain=$1
txtvalue=$2

if ! _ionos_init; then
return 1
fi

if ! _ionos_cloud_get_record "$_zone_id" "$txtvalue" "$fulldomain"; then
_err "Could not find _acme-challenge TXT record."
return 1
fi

if _ionos_cloud_rest DELETE "$IONOS_CLOUD_ROUTE_ZONES/$_zone_id/records/$_record_id" && [ "$_code" = "202" ]; then
_info "TXT record has been deleted successfully."
return 0
fi

return 1
}

_ionos_init() {
IONOS_TOKEN="${IONOS_TOKEN:-$(_readaccountconf_mutable IONOS_TOKEN)}"

if [ -z "$IONOS_TOKEN" ]; then
_err "You didn't specify an IONOS token yet."
_err "Read https://api.ionos.com/docs/authentication/v1/#tag/tokens/operation/tokensGenerate to learn how to get a token."
_err "You need to set it before calling acme.sh:"
_err "\$ export IONOS_TOKEN=\"...\""
_err "\$ acme.sh --issue -d ... --dns dns_ionos_cloud"
return 1
fi

_saveaccountconf_mutable IONOS_TOKEN "$IONOS_TOKEN"

if ! _get_cloud_zone "$fulldomain"; then
_err "Cannot find zone $zone in your IONOS account."
return 1
fi

return 0
}

_get_cloud_zone() {
domain=$1
zone=$(printf "%s" "$domain" | cut -d . -f 2-)

if _ionos_cloud_rest GET "$IONOS_CLOUD_ROUTE_ZONES?filter.zoneName=$zone"; then
_response="$(echo "$_response" | tr -d "\n")"

_zone_list_items=$(echo "$_response" | _egrep_o "\"items\":.*")

_zone_id=$(printf "%s\n" "$_zone_list_items" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"')
if [ "$_zone_id" ]; then
return 0
fi
fi

return 1
}

_ionos_cloud_get_record() {
zone_id=$1
txtrecord=$2
# this is to transform the domain to lower case
fulldomain=$(printf "%s" "$3" | tr "[:upper:]" "[:lower:]")
zak905 marked this conversation as resolved.
Show resolved Hide resolved
# this is to transform record name to lower case
# IONOS Cloud API transforms all record names to lower case
_record_name=$(printf "%s" "$fulldomain" | cut -d . -f 1 | tr "[:upper:]" "[:lower:]")
zak905 marked this conversation as resolved.
Show resolved Hide resolved

if _ionos_cloud_rest GET "$IONOS_CLOUD_ROUTE_ZONES/$zone_id/records"; then
_response="$(echo "$_response" | tr -d "\n")"

pattern="\{\"id\":\"[a-fA-F0-9\-]*\",\"type\":\"record\",\"href\":\"/zones/$zone_id/records/[a-fA-F0-9\-]*\",\"metadata\":\{\"createdDate\":\"[A-Z0-9\:\.\-]*\",\"lastModifiedDate\":\"[A-Z0-9\:\.\-]*\",\"fqdn\":\"$fulldomain\",\"state\":\"AVAILABLE\",\"zoneId\":\"$zone_id\"\},\"properties\":\{\"content\":\"$txtrecord\",\"enabled\":true,\"name\":\"$_record_name\",\"priority\":[0-9]*,\"ttl\":[0-9]*,\"type\":\"TXT\"\}\}"

_record="$(echo "$_response" | _egrep_o "$pattern")"
if [ "$_record" ]; then
_record_id=$(printf "%s\n" "$_record" | _egrep_o "\"id\":\"[a-fA-F0-9\-]*\"" | _head_n 1 | cut -d : -f 2 | tr -d '\"')
return 0
fi
fi

return 1
}

_ionos_cloud_rest() {
method="$1"
route="$2"
data="$3"

export _H1="Authorization: Bearer $IONOS_TOKEN"

# clear headers
: >"$HTTP_HEADER"

if [ "$method" != "GET" ]; then
_response="$(_post "$data" "$IONOS_CLOUD_API$route" "" "$method" "application/json")"
else
_response="$(_get "$IONOS_CLOUD_API$route")"
fi

_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"

if [ "$?" != "0" ]; then
_err "Error $route: $_response"
return 1
fi

_debug2 "_response" "$_response"
_debug2 "_code" "$_code"

return 0
}
Loading