Unverified Commit cc0be6cd authored by Arnaud Launay's avatar Arnaud Launay Committed by GitHub
Browse files

Merge branch 'acmesh-official:dev' into dev

parents b71a088d a7455d7e
......@@ -18,15 +18,15 @@ dns_netlify_add() {
NETLIFY_ACCESS_TOKEN=""
_err "Please specify your Netlify Access Token and try again."
return 1
else
_saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN"
fi
_info "Using Netlify"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
_saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN"
if ! _get_root "$fulldomain" "$accesstoken"; then
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
......@@ -62,9 +62,9 @@ dns_netlify_rm() {
_debug txtdomain "$txtdomain"
_debug txt "$txt"
_saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN"
NETLIFY_ACCESS_TOKEN="${NETLIFY_ACCESS_TOKEN:-$(_readaccountconf_mutable NETLIFY_ACCESS_TOKEN)}"
if ! _get_root "$txtdomain" "$accesstoken"; then
if ! _get_root "$txtdomain"; then
_err "invalid domain"
return 1
fi
......@@ -114,7 +114,7 @@ _get_root() {
fi
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
_domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \")
_domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h\"" | cut -d , -f 1 | tr -d \")
if [ "$_domain_id" ]; then
if [ "$i" = 1 ]; then
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
......
......@@ -51,7 +51,7 @@ dns_nsd_rm() {
Nsd_ZoneFile="${Nsd_ZoneFile:-$(_readdomainconf Nsd_ZoneFile)}"
Nsd_Command="${Nsd_Command:-$(_readdomainconf Nsd_Command)}"
sed -i "/$fulldomain. $ttlvalue IN TXT \"$txtvalue\"/d" "$Nsd_ZoneFile"
_sed_i "/$fulldomain. $ttlvalue IN TXT \"$txtvalue\"/d" "$Nsd_ZoneFile"
_info "Removed TXT record for $fulldomain"
_debug "Running $Nsd_Command"
if eval "$Nsd_Command"; then
......
#!/usr/bin/env sh
#
# Acme.sh DNS API plugin for Oracle Cloud Infrastructure
# Copyright (c) 2021, Oracle and/or its affiliates
#
# The plugin will automatically use the default profile from an OCI SDK and CLI
# configuration file, if it exists.
#
# Alternatively, set the following environment variables:
# - OCI_CLI_TENANCY : OCID of tenancy that contains the target DNS zone
# - OCI_CLI_USER : OCID of user with permission to add/remove records from zones
# - OCI_CLI_REGION : Should point to the tenancy home region
#
# One of the following two variables is required:
# - OCI_CLI_KEY_FILE: Path to private API signing key file in PEM format; or
# - OCI_CLI_KEY : The private API signing key in PEM format
#
# NOTE: using an encrypted private key that needs a passphrase is not supported.
#
dns_oci_add() {
_fqdn="$1"
_rdata="$2"
if _get_oci_zone; then
_add_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"ttl\": 30,\"operation\":\"ADD\"}]}"
response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_add_record_body")
if [ "$response" ]; then
_info "Success: added TXT record for ${_sub_domain}.${_domain}."
else
_err "Error: failed to add TXT record for ${_sub_domain}.${_domain}."
_err "Check that the user has permission to add records to this zone."
return 1
fi
else
return 1
fi
}
dns_oci_rm() {
_fqdn="$1"
_rdata="$2"
if _get_oci_zone; then
_remove_record_body="{\"items\":[{\"domain\":\"${_sub_domain}.${_domain}\",\"rdata\":\"$_rdata\",\"rtype\":\"TXT\",\"operation\":\"REMOVE\"}]}"
response=$(_signed_request "PATCH" "/20180115/zones/${_domain}/records" "$_remove_record_body")
if [ "$response" ]; then
_info "Success: removed TXT record for ${_sub_domain}.${_domain}."
else
_err "Error: failed to remove TXT record for ${_sub_domain}.${_domain}."
_err "Check that the user has permission to remove records from this zone."
return 1
fi
else
return 1
fi
}
#################### Private functions below ##################################
_get_oci_zone() {
if ! _oci_config; then
return 1
fi
if ! _get_zone "$_fqdn"; then
_err "Error: DNS Zone not found for $_fqdn in $OCI_CLI_TENANCY"
return 1
fi
return 0
}
_oci_config() {
_DEFAULT_OCI_CLI_CONFIG_FILE="$HOME/.oci/config"
OCI_CLI_CONFIG_FILE="${OCI_CLI_CONFIG_FILE:-$(_readaccountconf_mutable OCI_CLI_CONFIG_FILE)}"
if [ -z "$OCI_CLI_CONFIG_FILE" ]; then
OCI_CLI_CONFIG_FILE="$_DEFAULT_OCI_CLI_CONFIG_FILE"
fi
if [ "$_DEFAULT_OCI_CLI_CONFIG_FILE" != "$OCI_CLI_CONFIG_FILE" ]; then
_saveaccountconf_mutable OCI_CLI_CONFIG_FILE "$OCI_CLI_CONFIG_FILE"
else
_clearaccountconf_mutable OCI_CLI_CONFIG_FILE
fi
_DEFAULT_OCI_CLI_PROFILE="DEFAULT"
OCI_CLI_PROFILE="${OCI_CLI_PROFILE:-$(_readaccountconf_mutable OCI_CLI_PROFILE)}"
if [ "$_DEFAULT_OCI_CLI_PROFILE" != "$OCI_CLI_PROFILE" ]; then
_saveaccountconf_mutable OCI_CLI_PROFILE "$OCI_CLI_PROFILE"
else
OCI_CLI_PROFILE="$_DEFAULT_OCI_CLI_PROFILE"
_clearaccountconf_mutable OCI_CLI_PROFILE
fi
OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readaccountconf_mutable OCI_CLI_TENANCY)}"
if [ "$OCI_CLI_TENANCY" ]; then
_saveaccountconf_mutable OCI_CLI_TENANCY "$OCI_CLI_TENANCY"
elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then
_debug "Reading OCI_CLI_TENANCY value from: $OCI_CLI_CONFIG_FILE"
OCI_CLI_TENANCY="${OCI_CLI_TENANCY:-$(_readini "$OCI_CLI_CONFIG_FILE" tenancy "$OCI_CLI_PROFILE")}"
fi
if [ -z "$OCI_CLI_TENANCY" ]; then
_err "Error: unable to read OCI_CLI_TENANCY from config file or environment variable."
return 1
fi
OCI_CLI_USER="${OCI_CLI_USER:-$(_readaccountconf_mutable OCI_CLI_USER)}"
if [ "$OCI_CLI_USER" ]; then
_saveaccountconf_mutable OCI_CLI_USER "$OCI_CLI_USER"
elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then
_debug "Reading OCI_CLI_USER value from: $OCI_CLI_CONFIG_FILE"
OCI_CLI_USER="${OCI_CLI_USER:-$(_readini "$OCI_CLI_CONFIG_FILE" user "$OCI_CLI_PROFILE")}"
fi
if [ -z "$OCI_CLI_USER" ]; then
_err "Error: unable to read OCI_CLI_USER from config file or environment variable."
return 1
fi
OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readaccountconf_mutable OCI_CLI_REGION)}"
if [ "$OCI_CLI_REGION" ]; then
_saveaccountconf_mutable OCI_CLI_REGION "$OCI_CLI_REGION"
elif [ -f "$OCI_CLI_CONFIG_FILE" ]; then
_debug "Reading OCI_CLI_REGION value from: $OCI_CLI_CONFIG_FILE"
OCI_CLI_REGION="${OCI_CLI_REGION:-$(_readini "$OCI_CLI_CONFIG_FILE" region "$OCI_CLI_PROFILE")}"
fi
if [ -z "$OCI_CLI_REGION" ]; then
_err "Error: unable to read OCI_CLI_REGION from config file or environment variable."
return 1
fi
OCI_CLI_KEY="${OCI_CLI_KEY:-$(_readaccountconf_mutable OCI_CLI_KEY)}"
if [ -z "$OCI_CLI_KEY" ]; then
_clearaccountconf_mutable OCI_CLI_KEY
OCI_CLI_KEY_FILE="${OCI_CLI_KEY_FILE:-$(_readini "$OCI_CLI_CONFIG_FILE" key_file "$OCI_CLI_PROFILE")}"
if [ "$OCI_CLI_KEY_FILE" ] && [ -f "$OCI_CLI_KEY_FILE" ]; then
_debug "Reading OCI_CLI_KEY value from: $OCI_CLI_KEY_FILE"
OCI_CLI_KEY=$(_base64 <"$OCI_CLI_KEY_FILE")
_saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY"
fi
else
_saveaccountconf_mutable OCI_CLI_KEY "$OCI_CLI_KEY"
fi
if [ -z "$OCI_CLI_KEY_FILE" ] && [ -z "$OCI_CLI_KEY" ]; then
_err "Error: unable to find key file path in OCI config file or OCI_CLI_KEY_FILE."
_err "Error: unable to load private API signing key from OCI_CLI_KEY."
return 1
fi
if [ "$(printf "%s\n" "$OCI_CLI_KEY" | wc -l)" -eq 1 ]; then
OCI_CLI_KEY=$(printf "%s" "$OCI_CLI_KEY" | _dbase64)
fi
return 0
}
# _get_zone(): retrieves the Zone name and OCID
#
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_ociid=ocid1.dns-zone.oc1..
_get_zone() {
domain=$1
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
# not valid
return 1
fi
_domain_id=$(_signed_request "GET" "/20180115/zones/$h" "" "id")
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
_debug _domain_id "$_domain_id"
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
#Usage: privatekey
#Output MD5 fingerprint
_fingerprint() {
pkey="$1"
if [ -z "$pkey" ]; then
_usage "Usage: _fingerprint privkey"
return 1
fi
printf "%s" "$pkey" | ${ACME_OPENSSL_BIN:-openssl} rsa -pubout -outform DER 2>/dev/null | ${ACME_OPENSSL_BIN:-openssl} md5 -c | cut -d = -f 2 | tr -d ' '
}
_signed_request() {
_sig_method="$1"
_sig_target="$2"
_sig_body="$3"
_return_field="$4"
_key_fingerprint=$(_fingerprint "$OCI_CLI_KEY")
_sig_host="dns.$OCI_CLI_REGION.oraclecloud.com"
_sig_keyId="$OCI_CLI_TENANCY/$OCI_CLI_USER/$_key_fingerprint"
_sig_alg="rsa-sha256"
_sig_version="1"
_sig_now="$(LC_ALL=C \date -u "+%a, %d %h %Y %H:%M:%S GMT")"
_request_method=$(printf %s "$_sig_method" | _lower_case)
_curl_method=$(printf %s "$_sig_method" | _upper_case)
_request_target="(request-target): $_request_method $_sig_target"
_date_header="date: $_sig_now"
_host_header="host: $_sig_host"
_string_to_sign="$_request_target\n$_date_header\n$_host_header"
_sig_headers="(request-target) date host"
if [ "$_sig_body" ]; then
_secure_debug3 _sig_body "$_sig_body"
_sig_body_sha256="x-content-sha256: $(printf %s "$_sig_body" | _digest sha256)"
_sig_body_type="content-type: application/json"
_sig_body_length="content-length: ${#_sig_body}"
_string_to_sign="$_string_to_sign\n$_sig_body_sha256\n$_sig_body_type\n$_sig_body_length"
_sig_headers="$_sig_headers x-content-sha256 content-type content-length"
fi
_tmp_file=$(_mktemp)
if [ -f "$_tmp_file" ]; then
printf '%s' "$OCI_CLI_KEY" >"$_tmp_file"
_signature=$(printf '%b' "$_string_to_sign" | _sign "$_tmp_file" sha256 | tr -d '\r\n')
rm -f "$_tmp_file"
fi
_signed_header="Authorization: Signature version=\"$_sig_version\",keyId=\"$_sig_keyId\",algorithm=\"$_sig_alg\",headers=\"$_sig_headers\",signature=\"$_signature\""
_secure_debug3 _signed_header "$_signed_header"
if [ "$_curl_method" = "GET" ]; then
export _H1="$_date_header"
export _H2="$_signed_header"
_response="$(_get "https://${_sig_host}${_sig_target}")"
elif [ "$_curl_method" = "PATCH" ]; then
export _H1="$_date_header"
# shellcheck disable=SC2090
export _H2="$_sig_body_sha256"
export _H3="$_sig_body_type"
export _H4="$_sig_body_length"
export _H5="$_signed_header"
_response="$(_post "$_sig_body" "https://${_sig_host}${_sig_target}" "" "PATCH")"
else
_err "Unable to process method: $_curl_method."
fi
_ret="$?"
if [ "$_return_field" ]; then
_response="$(echo "$_response" | sed 's/\\\"//g'))"
_return=$(echo "${_response}" | _egrep_o "\"$_return_field\"\\s*:\\s*\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d "\"")
else
_return="$_response"
fi
printf "%s" "$_return"
return $_ret
}
# file key [section]
_readini() {
_file="$1"
_key="$2"
_section="${3:-DEFAULT}"
_start_n=$(grep -n '\['"$_section"']' "$_file" | cut -d : -f 1)
_debug3 _start_n "$_start_n"
if [ -z "$_start_n" ]; then
_err "Can not find section: $_section"
return 1
fi
_start_nn=$(_math "$_start_n" + 1)
_debug3 "_start_nn" "$_start_nn"
_left="$(sed -n "${_start_nn},99999p" "$_file")"
_debug3 _left "$_left"
_end="$(echo "$_left" | grep -n "^\[" | _head_n 1)"
_debug3 "_end" "$_end"
if [ "$_end" ]; then
_end_n=$(echo "$_end" | cut -d : -f 1)
_debug3 "_end_n" "$_end_n"
_seg_n=$(echo "$_left" | sed -n "1,${_end_n}p")
else
_seg_n="$_left"
fi
_debug3 "_seg_n" "$_seg_n"
_lineini="$(echo "$_seg_n" | grep "^ *$_key *= *")"
_inivalue="$(printf "%b" "$(eval "echo $_lineini | sed \"s/^ *${_key} *= *//g\"")")"
_debug2 _inivalue "$_inivalue"
echo "$_inivalue"
}
#!/usr/bin/env sh
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
# one.com ui wrapper for acme.sh
# Author: github: @diseq
# Created: 2019-02-17
# Fixed by: @der-berni
# Modified: 2020-04-07
#
# Use ONECOM_KeepCnameProxy to keep the CNAME DNS record
# export ONECOM_KeepCnameProxy="1"
#
# export ONECOM_User="username"
# export ONECOM_Password="password"
#
# Usage:
# acme.sh --issue --dns dns_one -d example.com
#
# only single domain supported atm
dns_one_add() {
fulldomain=$1
......@@ -36,27 +23,9 @@ dns_one_add() {
subdomain="${_sub_domain}"
maindomain=${_domain}
useProxy=0
if [ "${_sub_domain}" = "_acme-challenge" ]; then
subdomain="proxy${_sub_domain}"
useProxy=1
fi
_debug subdomain "$subdomain"
_debug maindomain "$maindomain"
if [ $useProxy -eq 1 ]; then
#Check if the CNAME exists
_dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain"
if [ -z "$id" ]; then
_info "$(__red "Add CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")"
_dns_one_addrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain"
_info "Not valid yet, let's wait 1 hour to take effect."
_sleep 3600
fi
fi
#Check if the TXT exists
_dns_one_getrecord "TXT" "$subdomain" "$txtvalue"
if [ -n "$id" ]; then
......@@ -92,26 +61,8 @@ dns_one_rm() {
subdomain="${_sub_domain}"
maindomain=${_domain}
useProxy=0
if [ "${_sub_domain}" = "_acme-challenge" ]; then
subdomain="proxy${_sub_domain}"
useProxy=1
fi
_debug subdomain "$subdomain"
_debug maindomain "$maindomain"
if [ $useProxy -eq 1 ]; then
if [ "$ONECOM_KeepCnameProxy" = "1" ]; then
_info "$(__red "Keeping CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")"
else
#Check if the CNAME exists
_dns_one_getrecord "CNAME" "$_sub_domain" "$subdomain.$maindomain"
if [ -n "$id" ]; then
_info "$(__red "Removing CNAME Proxy record: '$(__green "\"$_sub_domain\" => \"$subdomain.$maindomain\"")'")"
_dns_one_delrecord "$id"
fi
fi
fi
#Check if the TXT exists
_dns_one_getrecord "TXT" "$subdomain" "$txtvalue"
......@@ -136,7 +87,7 @@ dns_one_rm() {
# _domain=domain.com
_get_root() {
domain="$1"
i=2
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
......@@ -163,8 +114,6 @@ _get_root() {
_dns_one_login() {
# get credentials
ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-$(_readaccountconf_mutable ONECOM_KeepCnameProxy)}"
ONECOM_KeepCnameProxy="${ONECOM_KeepCnameProxy:-0}"
ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}"
ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}"
if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then
......@@ -176,7 +125,6 @@ _dns_one_login() {
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable ONECOM_KeepCnameProxy "$ONECOM_KeepCnameProxy"
_saveaccountconf_mutable ONECOM_User "$ONECOM_User"
_saveaccountconf_mutable ONECOM_Password "$ONECOM_Password"
......
......@@ -57,16 +57,16 @@ _dns_openstack_create_recordset() {
if [ -z "$_recordset_id" ]; then
_info "Creating a new recordset"
if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record "$txtvalue" "$_zone_id" "$fulldomain."); then
if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record="$txtvalue" "$_zone_id" "$fulldomain."); then
_err "No recordset ID found after create"
return 1
fi
else
_info "Updating existing recordset"
# Build new list of --record <rec> args for update
_record_args="--record $txtvalue"
# Build new list of --record=<rec> args for update
_record_args="--record=$txtvalue"
for _rec in $_records; do
_record_args="$_record_args --record $_rec"
_record_args="$_record_args --record=$_rec"
done
# shellcheck disable=SC2086
if ! _recordset_id=$(openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain."); then
......@@ -107,13 +107,13 @@ _dns_openstack_delete_recordset() {
fi
else
_info "Found existing records, updating recordset"
# Build new list of --record <rec> args for update
# Build new list of --record=<rec> args for update
_record_args=""
for _rec in $_records; do
if [ "$_rec" = "$txtvalue" ]; then
continue
fi
_record_args="$_record_args --record $_rec"
_record_args="$_record_args --record=$_rec"
done
# shellcheck disable=SC2086
if ! openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain." >/dev/null; then
......
......@@ -137,7 +137,7 @@ _get_root() {
domain=$1
i=2
p=1
if _opns_rest "GET" "/domain/get"; then
if _opns_rest "GET" "/domain/searchPrimaryDomain"; then
_domain_response="$response"
else
return 1
......@@ -150,8 +150,7 @@ _get_root() {
return 1
fi
_debug h "$h"
id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\"(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2)
id=$(echo "$_domain_response" | _egrep_o "\"uuid\":\"[a-z0-9\-]*\",\"enabled\":\"1\",\"type\":\"primary\",\"domainname\":\"${h}\"" | cut -d ':' -f 2 | cut -d '"' -f 2)
if [ -n "$id" ]; then
_debug id "$id"
_host=$(printf "%s" "$domain" | cut -d . -f 1-$p)
......
......@@ -14,6 +14,9 @@
#'ovh-eu'
OVH_EU='https://eu.api.ovh.com/1.0'
#'ovh-us'
OVH_US='https://api.us.ovhcloud.com/1.0'
#'ovh-ca':
OVH_CA='https://ca.api.ovh.com/1.0'
......@@ -29,9 +32,6 @@ SYS_EU='https://eu.api.soyoustart.com/1.0'
#'soyoustart-ca'
SYS_CA='https://ca.api.soyoustart.com/1.0'
#'runabove-ca'
RAV_CA='https://api.runabove.com/1.0'
wiki="https://github.com/acmesh-official/acme.sh/wiki/How-to-use-OVH-domain-api"
ovh_success="https://github.com/acmesh-official/acme.sh/wiki/OVH-Success"
......@@ -45,6 +45,10 @@ _ovh_get_api() {
printf "%s" $OVH_EU
return
;;
ovh-us | ovhus)
printf "%s" $OVH_US
return
;;
ovh-ca | ovhca)
printf "%s" $OVH_CA
return
......@@ -65,14 +69,15 @@ _ovh_get_api() {
printf "%s" $SYS_CA
return
;;
runabove-ca | runaboveca)
printf "%s" $RAV_CA
# raw API url starts with https://
https*)
printf "%s" "$1"
return
;;
*)
_err "Unknown parameter : $1"
_err "Unknown endpoint : $1"
return 1
;;
esac
......@@ -92,7 +97,7 @@ _initAuth() {
if [ "$OVH_AK" != "$(_readaccountconf OVH_AK)" ]; then
_info "It seems that your ovh key is changed, let's clear consumer key first."
_clearaccountconf OVH_CK
_clearaccountconf_mutable OVH_CK
fi
_saveaccountconf_mutable OVH_AK "$OVH_AK"
_saveaccountconf_mutable OVH_AS "$OVH_AS"
......@@ -118,13 +123,14 @@ _initAuth() {
#return and wait for retry.
return 1
fi
_saveaccountconf_mutable OVH_CK "$OVH_CK"
_info "Checking authentication"
if ! _ovh_rest GET "domain" || _contains "$response" "INVALID_CREDENTIAL" || _contains "$response" "NOT_CREDENTIAL"; then
_err "The consumer key is invalid: $OVH_CK"
_err "Please retry to create a new one."
_clearaccountconf OVH_CK
_clearaccountconf_mutable OVH_CK
return 1
fi
_info "Consumer key is ok."
......@@ -198,6 +204,8 @@ dns_ovh_rm() {
if ! _ovh_rest DELETE "domain/zone/$_domain/record/$rid"; then
return 1
fi
_ovh_rest POST "domain/zone/$_domain/refresh"
_debug "Refresh:$response"
return 0
fi
done
......@@ -233,8 +241,7 @@ _ovh_authentication() {
_secure_debug consumerKey "$consumerKey"
OVH_CK="$consumerKey"
_saveaccountconf OVH_CK "$OVH_CK"
_saveaccountconf_mutable OVH_CK "$OVH_CK"
_info "Please open this link to do authentication: $(__green "$validationUrl")"
_info "Here is a guide for you: $(__green "$wiki")"
......@@ -261,7 +268,9 @@ _get_root() {
return 1
fi
if ! _contains "$response" "This service does not exist" >/dev/null && ! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then
if ! _contains "$response" "This service does not exist" >/dev/null &&
! _contains "$response" "This call has not been granted" >/dev/null &&
! _contains "$response" "NOT_GRANTED_CALL" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
......
......@@ -103,7 +103,7 @@ set_record() {
_build_record_string "$oldchallenge"
done
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}" "application/json"; then
_err "Set txt record error."
return 1
fi
......@@ -126,7 +126,7 @@ rm_record() {
if _contains "$_existing_challenges" "$txtvalue"; then
#Delete all challenges (PowerDNS API does not allow to delete content)
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}" "application/json"; then
_err "Delete txt record error."
return 1
fi
......@@ -140,7 +140,7 @@ rm_record() {
fi
done
#Recreate the existing challenges
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}"; then
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [$_record_string]}]}" "application/json"; then
_err "Set txt record error."
return 1
fi
......@@ -175,13 +175,13 @@ _get_root() {
i=1
if _pdns_rest "GET" "/api/v1/servers/$PDNS_ServerId/zones"; then
_zones_response="$response"
_zones_response=$(echo "$response" | _normalizeJson)
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if _contains "$_zones_response" "\"name\": \"$h.\""; then
if _contains "$_zones_response" "\"name\":\"$h.\""; then
_domain="$h."
if [ -z "$h" ]; then
_domain="=2E"
......@@ -203,12 +203,13 @@ _pdns_rest() {
method=$1
ep=$2
data=$3
ct=$4
export _H1="X-API-Key: $PDNS_Token"
if [ ! "$method" = "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$PDNS_Url$ep" "" "$method")"
response="$(_post "$data" "$PDNS_Url$ep" "" "$method" "$ct")"
else
response="$(_get "$PDNS_Url$ep")"
fi
......
......@@ -41,7 +41,7 @@ pleskxml_init_checks_done=0
NEWLINE='\
'
pleskxml_tplt_get_domains="<packet><customer><get-domain-list><filter/></get-domain-list></customer></packet>"
pleskxml_tplt_get_domains="<packet><webspace><get><filter/><dataset><gen_info/></dataset></get></webspace></packet>"
# Get a list of domains that PLESK can manage, so we can check root domain + host for acme.sh
# Also used to test credentials and URI.
# No params.
......@@ -145,22 +145,25 @@ dns_pleskxml_rm() {
)"
if [ -z "$reclist" ]; then
_err "No TXT records found for root domain ${root_domain_name} (Plesk domain ID ${root_domain_id}). Exiting."
_err "No TXT records found for root domain $fulldomain (Plesk domain ID ${root_domain_id}). Exiting."
return 1
fi
_debug "Got list of DNS TXT records for root domain '$root_domain_name':"
_debug "Got list of DNS TXT records for root Plesk domain ID ${root_domain_id} of root domain $fulldomain:"
_debug "$reclist"
# Extracting the id of the TXT record for the full domain (NOT case-sensitive) and corresponding value
recid="$(
_value "$reclist" |
grep "<host>${fulldomain}.</host>" |
grep -i "<host>${fulldomain}.</host>" |
grep "<value>${txtvalue}</value>" |
sed 's/^.*<id>\([0-9]\{1,\}\)<\/id>.*$/\1/'
)"
_debug "Got id from line: $recid"
if ! _value "$recid" | grep '^[0-9]\{1,\}$' >/dev/null; then
_err "DNS records for root domain '${root_domain_name}' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'"
_err "DNS records for root domain '${fulldomain}.' (Plesk ID ${root_domain_id}) + host '${sub_domain_name}' do not contain the TXT record '${txtvalue}'"
_err "Cannot delete TXT record. Exiting."
return 1
fi
......@@ -251,9 +254,12 @@ _call_api() {
# Detect any <status> that isn't "ok". None of the used calls should fail if the API is working correctly.
# Also detect if there simply aren't any status lines (null result?) and report that, as well.
# Remove <data></data> structure from result string, since it might contain <status> values that are related to the status of the domain and not to the API request
statuslines_count_total="$(echo "$pleskxml_prettyprint_result" | grep -c '^ *<status>[^<]*</status> *$')"
statuslines_count_okay="$(echo "$pleskxml_prettyprint_result" | grep -c '^ *<status>ok</status> *$')"
statuslines_count_total="$(echo "$pleskxml_prettyprint_result" | sed '/<data>/,/<\/data>/d' | grep -c '^ *<status>[^<]*</status> *$')"
statuslines_count_okay="$(echo "$pleskxml_prettyprint_result" | sed '/<data>/,/<\/data>/d' | grep -c '^ *<status>ok</status> *$')"
_debug "statuslines_count_total=$statuslines_count_total."
_debug "statuslines_count_okay=$statuslines_count_okay."
if [ -z "$statuslines_count_total" ]; then
......@@ -375,7 +381,7 @@ _pleskxml_get_root_domain() {
# Output will be one line per known domain, containing 2 <name> tages and a single <id> tag
# We don't actually need to check for type, name, *and* id, but it guarantees only usable lines are returned.
output="$(_api_response_split "$pleskxml_prettyprint_result" 'domain' '<type>domain</type>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')"
output="$(_api_response_split "$pleskxml_prettyprint_result" 'result' '<status>ok</status>' | sed 's/<ascii-name>/<name>/g;s/<\/ascii-name>/<\/name>/g' | grep '<name>' | grep '<id>')"
_debug 'Domains managed by Plesk server are (ignore the hacked output):'
_debug "$output"
......
#!/usr/bin/env sh
#
#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
PORKBUN_Api="https://porkbun.com/api/json/v3"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_porkbun_add() {
fulldomain=$1
txtvalue=$2
PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}"
PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}"
if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then
PORKBUN_API_KEY=''
PORKBUN_SECRET_API_KEY=''
_err "You didn't specify a Porkbun api key and secret api key yet."
_err "You can get yours from here https://porkbun.com/account/api."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY"
_saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY"
_debug 'First detect the root zone'
if ! _get_root "$fulldomain"; then
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
# For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so
# we can not use updating anymore.
# count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
# _debug count "$count"
# if [ "$count" = "0" ]; then
_info "Adding record"
if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" '\"status\":"SUCCESS"'; then
_info "Added, OK"
return 0
elif _contains "$response" "The record already exists"; then
_info "Already exists, OK"
return 0
else
_err "Add txt record error. ($response)"
return 1
fi
fi
_err "Add txt record error."
return 1
}
#fulldomain txtvalue
dns_porkbun_rm() {
fulldomain=$1
txtvalue=$2
PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}"
PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}"
_debug 'First detect the root zone'
if ! _get_root "$fulldomain"; then
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ")
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
record_id=$(echo "$response" | tr '{' '\n' | grep -- "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \")
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1
fi
if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then
_err "Delete record error."
return 1
fi
echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null
fi
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
return 1
fi
if _porkbun_rest POST "dns/retrieve/$h"; then
if _contains "$response" "\"status\":\"SUCCESS\""; then
_domain=$h
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")"
return 0
else
_debug "Go to next level of $_domain"
fi
else
_debug "Go to next level of $_domain"
fi
i=$(_math "$i" + 1)
done
return 1
}
_porkbun_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"')
secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"')
test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1),"
data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}"
export _H1="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")"
else
response="$(_get "$PORKBUN_Api/$ep")"
fi
_sleep 3 # prevent rate limit
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
#!/usr/bin/env sh
# Provider: RackCorp (www.rackcorp.com)
# Author: Stephen Dendtler (sdendtler@rackcorp.com)
# Report Bugs here: https://github.com/senjoo/acme.sh
# Alternate email contact: support@rackcorp.com
#
# You'll need an API key (Portal: ADMINISTRATION -> API)
# Set the environment variables as below:
#
# export RACKCORP_APIUUID="UUIDHERE"
# export RACKCORP_APISECRET="SECRETHERE"
#
RACKCORP_API_ENDPOINT="https://api.rackcorp.net/api/rest/v2.4/json.php"
######## Public functions #####################
dns_rackcorp_add() {
fulldomain="$1"
txtvalue="$2"
_debug fulldomain="$fulldomain"
_debug txtvalue="$txtvalue"
if ! _rackcorp_validate; then
return 1
fi
_debug "Searching for root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_debug _lookup "$_lookup"
_debug _domain "$_domain"
_info "Creating TXT record."
if ! _rackcorp_api dns.record.create "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\",\"ttl\":300"; then
return 1
fi
return 0
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_rackcorp_rm() {
fulldomain=$1
txtvalue=$2
_debug fulldomain="$fulldomain"
_debug txtvalue="$txtvalue"
if ! _rackcorp_validate; then
return 1
fi
_debug "Searching for root zone"
if ! _get_root "$fulldomain"; then
return 1
fi
_debug _lookup "$_lookup"
_debug _domain "$_domain"
_info "Creating TXT record."
if ! _rackcorp_api dns.record.delete "\"name\":\"$_domain\",\"type\":\"TXT\",\"lookup\":\"$_lookup\",\"data\":\"$txtvalue\""; then
return 1
fi
return 0
}
#################### Private functions below ##################################
#_acme-challenge.domain.com
#returns
# _lookup=_acme-challenge
# _domain=domain.com
_get_root() {
domain=$1
i=1
p=1
if ! _rackcorp_api dns.domain.getall "\"name\":\"$domain\""; then
return 1
fi
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug searchhost "$h"
if [ -z "$h" ]; then
_err "Could not find domain for record $domain in RackCorp using the provided credentials"
#not valid
return 1
fi
_rackcorp_api dns.domain.getall "\"exactName\":\"$h\""
if _contains "$response" "\"matches\":1"; then
if _contains "$response" "\"name\":\"$h\""; then
_lookup=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}
_rackcorp_validate() {
RACKCORP_APIUUID="${RACKCORP_APIUUID:-$(_readaccountconf_mutable RACKCORP_APIUUID)}"
if [ -z "$RACKCORP_APIUUID" ]; then
RACKCORP_APIUUID=""
_err "You require a RackCorp API UUID (export RACKCORP_APIUUID=\"<api uuid>\")"
_err "Please login to the portal and create an API key and try again."
return 1
fi
_saveaccountconf_mutable RACKCORP_APIUUID "$RACKCORP_APIUUID"
RACKCORP_APISECRET="${RACKCORP_APISECRET:-$(_readaccountconf_mutable RACKCORP_APISECRET)}"
if [ -z "$RACKCORP_APISECRET" ]; then
RACKCORP_APISECRET=""
_err "You require a RackCorp API secret (export RACKCORP_APISECRET=\"<api secret>\")"
_err "Please login to the portal and create an API key and try again."
return 1
fi
_saveaccountconf_mutable RACKCORP_APISECRET "$RACKCORP_APISECRET"
return 0
}
_rackcorp_api() {
_rackcorpcmd=$1
_rackcorpinputdata=$2
_debug cmd "$_rackcorpcmd $_rackcorpinputdata"
export _H1="Accept: application/json"
response="$(_post "{\"APIUUID\":\"$RACKCORP_APIUUID\",\"APISECRET\":\"$RACKCORP_APISECRET\",\"cmd\":\"$_rackcorpcmd\",$_rackcorpinputdata}" "$RACKCORP_API_ENDPOINT" "" "POST")"
if [ "$?" != "0" ]; then
_err "error $response"
return 1
fi
_debug2 response "$response"
if _contains "$response" "\"code\":\"OK\""; then
_debug code "OK"
else
_debug code "FAILED"
response=""
return 1
fi
return 0
}
......@@ -7,6 +7,7 @@
RACKSPACE_Endpoint="https://dns.api.rackspacecloud.com/v1.0"
# 20210923 - RS changed the fields in the API response; fix sed
# 20190213 - The name & id fields swapped in the API response; fix sed
# 20190101 - Duplicating file for new pull request to dev branch
# Original - tcocca:rackspace_dnsapi https://github.com/acmesh-official/acme.sh/pull/1297
......@@ -79,8 +80,8 @@ _get_root_zone() {
_debug2 response "$response"
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
# Response looks like:
# {"ttl":300,"accountId":12345,"id":1111111,"name":"example.com","emailAddress": ...<and so on>
_domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\([^,]*\),\"name\":\"$h\",.*/\1/p")
# {"id":"12345","accountId":"1111111","name": "example.com","ttl":3600,"emailAddress": ... <and so on>
_domain_id=$(echo "$response" | sed -n "s/^.*\"id\":\"\([^,]*\)\",\"accountId\":\"[0-9]*\",\"name\":\"$h\",.*/\1/p")
_debug2 domain_id "$_domain_id"
if [ -n "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
......
#!/usr/bin/env sh
#
#RAGE4_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje"
#
#RAGE4_USERNAME="xxxx@sss.com"
RAGE4_Api="https://rage4.com/rapi/"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_rage4_add() {
fulldomain=$1
txtvalue=$2
unquotedtxtvalue=$(echo "$txtvalue" | tr -d \")
RAGE4_USERNAME="${RAGE4_USERNAME:-$(_readaccountconf_mutable RAGE4_USERNAME)}"
RAGE4_TOKEN="${RAGE4_TOKEN:-$(_readaccountconf_mutable RAGE4_TOKEN)}"
if [ -z "$RAGE4_USERNAME" ] || [ -z "$RAGE4_TOKEN" ]; then
RAGE4_USERNAME=""
RAGE4_TOKEN=""
_err "You didn't specify a Rage4 api token and username yet."
return 1
fi
#save the api key and email to the account conf file.
_saveaccountconf_mutable RAGE4_USERNAME "$RAGE4_USERNAME"
_saveaccountconf_mutable RAGE4_TOKEN "$RAGE4_TOKEN"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_rage4_rest "createrecord/?id=$_domain_id&name=$fulldomain&content=$unquotedtxtvalue&type=TXT&active=true&ttl=1"
return 0
}
#fulldomain txtvalue
dns_rage4_rm() {
fulldomain=$1
txtvalue=$2
RAGE4_USERNAME="${RAGE4_USERNAME:-$(_readaccountconf_mutable RAGE4_USERNAME)}"
RAGE4_TOKEN="${RAGE4_TOKEN:-$(_readaccountconf_mutable RAGE4_TOKEN)}"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _domain_id "$_domain_id"
_debug "Getting txt records"
_rage4_rest "getrecords/?id=${_domain_id}"
_record_id=$(echo "$response" | sed -rn 's/.*"id":([[:digit:]]+)[^\}]*'"$txtvalue"'.*/\1/p')
_rage4_rest "deleterecord/?id=${_record_id}"
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
if ! _rage4_rest "getdomains"; then
return 1
fi
_debug _get_root_domain "$domain"
for line in $(echo "$response" | tr '}' '\n'); do
__domain=$(echo "$line" | sed -rn 's/.*"name":"([^"]*)",.*/\1/p')
__domain_id=$(echo "$line" | sed -rn 's/.*"id":([^,]*),.*/\1/p')
if [ "$domain" != "${domain%"$__domain"*}" ]; then
_domain_id="$__domain_id"
break
fi
done
if [ -z "$_domain_id" ]; then
return 1
fi
return 0
}
_rage4_rest() {
ep="$1"
_debug "$ep"
username_trimmed=$(echo "$RAGE4_USERNAME" | tr -d '"')
token_trimmed=$(echo "$RAGE4_TOKEN" | tr -d '"')
auth=$(printf '%s:%s' "$username_trimmed" "$token_trimmed" | _base64)
export _H1="Content-Type: application/json"
export _H2="Authorization: Basic $auth"
response="$(_get "$RAGE4_Api$ep")"
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
......@@ -92,9 +92,10 @@ _get_root() {
domains_list=$(echo "${response}" | grep dname | sed -r "s/.*dname=\"([^\"]+)\".*/\\1/g")
for ITEM in ${domains_list}; do
IDN_ITEM=${ITEM}
case "${domain}" in
*${ITEM}*)
_domain=${ITEM}
*${IDN_ITEM}*)
_domain="$(_idn "${ITEM}")"
_debug _domain "${_domain}"
return 0
;;
......
#!/usr/bin/env sh
# Scaleway API
# https://developers.scaleway.com/en/products/domain/dns/api/
#
# Requires Scaleway API token set in SCALEWAY_API_TOKEN
######## Public functions #####################
SCALEWAY_API="https://api.scaleway.com/domain/v2beta1"
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_scaleway_add() {
fulldomain=$1
txtvalue=$2
if ! _scaleway_check_config; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Adding record"
_scaleway_create_TXT_record "$_domain" "$_sub_domain" "$txtvalue"
if _contains "$response" "records"; then
return 0
else
_err error "$response"
return 1
fi
_info "Record added."
return 0
}
dns_scaleway_rm() {
fulldomain=$1
txtvalue=$2
if ! _scaleway_check_config; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Deleting record"
_scaleway_delete_TXT_record "$_domain" "$_sub_domain" "$txtvalue"
if _contains "$response" "records"; then
return 0
else
_err error "$response"
return 1
fi
_info "Record deleted."
return 0
}
#################### Private functions below ##################################
_scaleway_check_config() {
SCALEWAY_API_TOKEN="${SCALEWAY_API_TOKEN:-$(_readaccountconf_mutable SCALEWAY_API_TOKEN)}"
if [ -z "$SCALEWAY_API_TOKEN" ]; then
_err "No API key specified for Scaleway API."
_err "Create your key and export it as SCALEWAY_API_TOKEN"
return 1
fi
if ! _scaleway_rest GET "dns-zones"; then
_err "Invalid API key specified for Scaleway API."
return 1
fi
_saveaccountconf_mutable SCALEWAY_API_TOKEN "$SCALEWAY_API_TOKEN"
return 0
}
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=1
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
_scaleway_rest GET "dns-zones/$h/records"
if ! _contains "$response" "subdomain not found" >/dev/null; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
_err "Unable to retrive DNS zone matching this domain"
return 1
}
# this function add a TXT record
_scaleway_create_TXT_record() {
txt_zone=$1
txt_name=$2
txt_value=$3
_scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"add\":{\"records\":[{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\",\"ttl\":60}]}}]}"
if _contains "$response" "records"; then
return 0
else
_err "error1 $response"
return 1
fi
}
# this function delete a TXT record based on name and content
_scaleway_delete_TXT_record() {
txt_zone=$1
txt_name=$2
txt_value=$3
_scaleway_rest PATCH "dns-zones/$txt_zone/records" "{\"return_all_records\":false,\"changes\":[{\"delete\":{\"id_fields\":{\"name\":\"$txt_name\",\"data\":\"$txt_value\",\"type\":\"TXT\"}}}]}"
if _contains "$response" "records"; then
return 0
else
_err "error2 $response"
return 1
fi
}
_scaleway_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
_scaleway_url="$SCALEWAY_API/$ep"
_debug2 _scaleway_url "$_scaleway_url"
export _H1="x-auth-token: $SCALEWAY_API_TOKEN"
export _H2="Accept: application/json"
export _H3="Content-Type: application/json"
if [ "$data" ] || [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$_scaleway_url" "" "$m")"
else
response="$(_get "$_scaleway_url")"
fi
if [ "$?" != "0" ] || _contains "$response" "denied_authentication" || _contains "$response" "Method not allowed" || _contains "$response" "json parse error: unexpected EOF"; then
_err "error $response"
return 1
fi
_debug2 response "$response"
return 0
}
......@@ -76,7 +76,7 @@ dns_selectel_rm() {
return 1
fi
_record_seg="$(echo "$response" | _egrep_o "\"content\" *: *\"$txtvalue\"[^}]*}")"
_record_seg="$(echo "$response" | _egrep_o "[^{]*\"content\" *: *\"$txtvalue\"[^}]*}")"
_debug2 "_record_seg" "$_record_seg"
if [ -z "$_record_seg" ]; then
_err "can not find _record_seg"
......@@ -120,7 +120,7 @@ _get_root() {
return 1
fi
if _contains "$response" "\"name\": \"$h\","; then
if _contains "$response" "\"name\" *: *\"$h\","; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain=$h
_debug "Getting domain id for $h"
......
#!/usr/bin/env sh
#
# Author: Marvin Edeler
# Report Bugs here: https://github.com/Marvo2011/acme.sh/issues/1
# Last Edit: 17.02.2022
dns_selfhost_add() {
fulldomain=$1
txt=$2
_info "Calling acme-dns on selfhost"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txt"
SELFHOSTDNS_UPDATE_URL="https://selfhost.de/cgi-bin/api.pl"
# Get values, but don't save until we successfully validated
SELFHOSTDNS_USERNAME="${SELFHOSTDNS_USERNAME:-$(_readaccountconf_mutable SELFHOSTDNS_USERNAME)}"
SELFHOSTDNS_PASSWORD="${SELFHOSTDNS_PASSWORD:-$(_readaccountconf_mutable SELFHOSTDNS_PASSWORD)}"
# These values are domain dependent, so read them from there
SELFHOSTDNS_MAP="${SELFHOSTDNS_MAP:-$(_readdomainconf SELFHOSTDNS_MAP)}"
# Selfhost api can't dynamically add TXT record,
# so we have to store the last used RID of the domain to support a second RID for wildcard domains
# (format: 'fulldomainA:lastRid fulldomainB:lastRid ...')
SELFHOSTDNS_MAP_LAST_USED_INTERNAL=$(_readdomainconf SELFHOSTDNS_MAP_LAST_USED_INTERNAL)
if [ -z "${SELFHOSTDNS_USERNAME:-}" ] || [ -z "${SELFHOSTDNS_PASSWORD:-}" ]; then
_err "SELFHOSTDNS_USERNAME and SELFHOSTDNS_PASSWORD must be set"
return 1
fi
# get the domain entry from SELFHOSTDNS_MAP
# only match full domains (at the beginning of the string or with a leading whitespace),
# e.g. don't match mytest.example.com or sub.test.example.com for test.example.com
# if the domain is defined multiple times only the last occurance will be matched
mapEntry=$(echo "$SELFHOSTDNS_MAP" | sed -n -E "s/(^|^.*[[:space:]])($fulldomain)(:[[:digit:]]+)([:]?[[:digit:]]*)(.*)/\2\3\4/p")
_debug2 mapEntry "$mapEntry"
if test -z "$mapEntry"; then
_err "SELFHOSTDNS_MAP must contain the fulldomain incl. prefix and at least one RID"
return 1
fi
# get the RIDs from the map entry
rid1=$(echo "$mapEntry" | cut -d: -f2)
rid2=$(echo "$mapEntry" | cut -d: -f3)
# read last used rid domain
lastUsedRidForDomainEntry=$(echo "$SELFHOSTDNS_MAP_LAST_USED_INTERNAL" | sed -n -E "s/(^|^.*[[:space:]])($fulldomain:[[:digit:]]+)(.*)/\2/p")
_debug2 lastUsedRidForDomainEntry "$lastUsedRidForDomainEntry"
lastUsedRidForDomain=$(echo "$lastUsedRidForDomainEntry" | cut -d: -f2)
rid="$rid1"
if [ "$lastUsedRidForDomain" = "$rid" ] && ! test -z "$rid2"; then
rid="$rid2"
fi
_info "Trying to add $txt on selfhost for rid: $rid"
data="?username=$SELFHOSTDNS_USERNAME&password=$SELFHOSTDNS_PASSWORD&rid=$rid&content=$txt"
response="$(_get "$SELFHOSTDNS_UPDATE_URL$data")"
if ! echo "$response" | grep "200 OK" >/dev/null; then
_err "Invalid response of acme-dns for selfhost"
return 1
fi
# write last used rid domain
newLastUsedRidForDomainEntry="$fulldomain:$rid"
if ! test -z "$lastUsedRidForDomainEntry"; then
# replace last used rid entry for domain
SELFHOSTDNS_MAP_LAST_USED_INTERNAL=$(echo "$SELFHOSTDNS_MAP_LAST_USED_INTERNAL" | sed -n -E "s/$lastUsedRidForDomainEntry/$newLastUsedRidForDomainEntry/p")
else
# add last used rid entry for domain
if test -z "$SELFHOSTDNS_MAP_LAST_USED_INTERNAL"; then
SELFHOSTDNS_MAP_LAST_USED_INTERNAL="$newLastUsedRidForDomainEntry"
else
SELFHOSTDNS_MAP_LAST_USED_INTERNAL="$SELFHOSTDNS_MAP_LAST_USED_INTERNAL $newLastUsedRidForDomainEntry"
fi
fi
# Now that we know the values are good, save them
_saveaccountconf_mutable SELFHOSTDNS_USERNAME "$SELFHOSTDNS_USERNAME"
_saveaccountconf_mutable SELFHOSTDNS_PASSWORD "$SELFHOSTDNS_PASSWORD"
# These values are domain dependent, so store them there
_savedomainconf SELFHOSTDNS_MAP "$SELFHOSTDNS_MAP"
_savedomainconf SELFHOSTDNS_MAP_LAST_USED_INTERNAL "$SELFHOSTDNS_MAP_LAST_USED_INTERNAL"
}
dns_selfhost_rm() {
fulldomain=$1
txt=$2
_debug fulldomain "$fulldomain"
_debug txtvalue "$txt"
_info "Creating and removing of records is not supported by selfhost API, will not delete anything."
}
......@@ -49,16 +49,42 @@ dns_servercow_add() {
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then
if printf -- "%s" "$response" | grep "ok" >/dev/null; then
_info "Added, OK"
return 0
else
_err "add txt record error."
return 1
# check whether a txt record already exists for the subdomain
if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then
_info "A txt record with the same name already exists."
# trim the string on the left
txtvalue_old=${response#*{\"name\":\""$_sub_domain"\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"}
# trim the string on the right
txtvalue_old=${txtvalue_old%%\"*}
_debug txtvalue_old "$txtvalue_old"
_info "Add the new txtvalue to the existing txt record."
if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then
if printf -- "%s" "$response" | grep "ok" >/dev/null; then
_info "Added additional txtvalue, OK"
return 0
else
_err "add txt record error."
return 1
fi
fi
_err "add txt record error."
return 1
else
_info "There is no txt record with the name yet."
if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then
if printf -- "%s" "$response" | grep "ok" >/dev/null; then
_info "Added, OK"
return 0
else
_err "add txt record error."
return 1
fi
fi
_err "add txt record error."
return 1
fi
_err "add txt record error."
return 1
}
......
#!/usr/bin/env sh
# API-integration for Simply.com (https://www.simply.com)
#SIMPLY_AccountName="accountname"
#SIMPLY_ApiKey="apikey"
#
#SIMPLY_Api="https://api.simply.com/2/"
SIMPLY_Api_Default="https://api.simply.com/2"
#This is used for determining success of REST call
SIMPLY_SUCCESS_CODE='"status":200'
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_simply_add() {
fulldomain=$1
txtvalue=$2
if ! _simply_load_config; then
return 1
fi
_simply_save_config
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_info "Adding record"
if ! _simply_add_record "$_domain" "$_sub_domain" "$txtvalue"; then
_err "Could not add DNS record"
return 1
fi
return 0
}
dns_simply_rm() {
fulldomain=$1
txtvalue=$2
if ! _simply_load_config; then
return 1
fi
_simply_save_config
_debug "Find the DNS zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
_debug txtvalue "$txtvalue"
_info "Getting all existing records"
if ! _simply_get_all_records "$_domain"; then
_err "invalid domain"
return 1
fi
records=$(echo "$response" | tr '{' "\n" | grep 'record_id\|type\|data\|\name' | sed 's/\"record_id/;\"record_id/' | tr "\n" ' ' | tr -d ' ' | tr ';' ' ')
nr_of_deleted_records=0
_info "Fetching txt record"
for record in $records; do
_debug record "$record"
record_data=$(echo "$record" | sed -n "s/.*\"data\":\"\([^\"]*\)\".*/\1/p")
record_type=$(echo "$record" | sed -n "s/.*\"type\":\"\([^\"]*\)\".*/\1/p")
_debug2 record_data "$record_data"
_debug2 record_type "$record_type"
if [ "$record_data" = "$txtvalue" ] && [ "$record_type" = "TXT" ]; then
record_id=$(echo "$record" | cut -d "," -f 1 | grep "record_id" | cut -d ":" -f 2)
_info "Deleting record $record"
_debug2 record_id "$record_id"
if [ "$record_id" -gt 0 ]; then
if ! _simply_delete_record "$_domain" "$_sub_domain" "$record_id"; then
_err "Record with id $record_id could not be deleted"
return 1
fi
nr_of_deleted_records=1
break
else
_err "Fetching record_id could not be done, this should not happen, exiting function. Failing record is $record"
break
fi
fi
done
if [ "$nr_of_deleted_records" -eq 0 ]; then
_err "No record deleted, the DNS record needs to be removed manually."
else
_info "Deleted $nr_of_deleted_records record"
fi
return 0
}
#################### Private functions below ##################################
_simply_load_config() {
SIMPLY_Api="${SIMPLY_Api:-$(_readaccountconf_mutable SIMPLY_Api)}"
SIMPLY_AccountName="${SIMPLY_AccountName:-$(_readaccountconf_mutable SIMPLY_AccountName)}"
SIMPLY_ApiKey="${SIMPLY_ApiKey:-$(_readaccountconf_mutable SIMPLY_ApiKey)}"
if [ -z "$SIMPLY_Api" ]; then
SIMPLY_Api="$SIMPLY_Api_Default"
fi
if [ -z "$SIMPLY_AccountName" ] || [ -z "$SIMPLY_ApiKey" ]; then
SIMPLY_AccountName=""
SIMPLY_ApiKey=""
_err "A valid Simply API account and apikey not provided."
_err "Please provide a valid API user and try again."
return 1
fi
return 0
}
_simply_save_config() {
if [ "$SIMPLY_Api" != "$SIMPLY_Api_Default" ]; then
_saveaccountconf_mutable SIMPLY_Api "$SIMPLY_Api"
fi
_saveaccountconf_mutable SIMPLY_AccountName "$SIMPLY_AccountName"
_saveaccountconf_mutable SIMPLY_ApiKey "$SIMPLY_ApiKey"
}
_simply_get_all_records() {
domain=$1
if ! _simply_rest GET "my/products/$domain/dns/records/"; then
return 1
fi
return 0
}
_get_root() {
domain=$1
i=2
p=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _simply_rest GET "my/products/$h/dns/"; then
return 1
fi
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
_debug "$h not found"
else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$h"
return 0
fi
p="$i"
i=$(_math "$i" + 1)
done
return 1
}
_simply_add_record() {
domain=$1
sub_domain=$2
txtval=$3
data="{\"name\": \"$sub_domain\", \"type\":\"TXT\", \"data\": \"$txtval\", \"priority\":0, \"ttl\": 3600}"
if ! _simply_rest POST "my/products/$domain/dns/records/" "$data"; then
_err "Adding record not successfull!"
return 1
fi
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
_err "Call to API not sucessfull, see below message for more details"
_err "$response"
return 1
fi
return 0
}
_simply_delete_record() {
domain=$1
sub_domain=$2
record_id=$3
_debug record_id "Delete record with id $record_id"
if ! _simply_rest DELETE "my/products/$domain/dns/records/$record_id/"; then
_err "Deleting record not successfull!"
return 1
fi
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
_err "Call to API not sucessfull, see below message for more details"
_err "$response"
return 1
fi
return 0
}
_simply_rest() {
m=$1
ep="$2"
data="$3"
_debug2 data "$data"
_debug2 ep "$ep"
_debug2 m "$m"
basicauth=$(printf "%s:%s" "$SIMPLY_AccountName" "$SIMPLY_ApiKey" | _base64)
if [ "$basicauth" ]; then
export _H1="Authorization: Basic $basicauth"
fi
export _H2="Content-Type: application/json"
if [ "$m" != "GET" ]; then
response="$(_post "$data" "$SIMPLY_Api/$ep" "" "$m")"
else
response="$(_get "$SIMPLY_Api/$ep")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
response="$(echo "$response" | _normalizeJson)"
_debug2 response "$response"
if _contains "$response" "Invalid account authorization"; then
_err "It seems that your api key or accountnumber is not correct."
return 1
fi
return 0
}
#!/usr/bin/env sh
TRANSIP_Api_Url="https://api.transip.nl/v6"
TRANSIP_Token_Read_Only="false"
TRANSIP_Token_Global_Key="false"
TRANSIP_Token_Expiration="30 minutes"
# You can't reuse a label token, so we leave this empty normally
TRANSIP_Token_Label=""
......@@ -96,7 +95,11 @@ _transip_get_token() {
nonce=$(echo "TRANSIP$(_time)" | _digest sha1 hex | cut -c 1-32)
_debug nonce "$nonce"
data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key}\"}"
# make IP whitelisting configurable
TRANSIP_Token_Global_Key="${TRANSIP_Token_Global_Key:-$(_readaccountconf_mutable TRANSIP_Token_Global_Key)}"
_saveaccountconf_mutable TRANSIP_Token_Global_Key "$TRANSIP_Token_Global_Key"
data="{\"login\":\"${TRANSIP_Username}\",\"nonce\":\"${nonce}\",\"read_only\":\"${TRANSIP_Token_Read_Only}\",\"expiration_time\":\"${TRANSIP_Token_Expiration}\",\"label\":\"${TRANSIP_Token_Label}\",\"global_key\":\"${TRANSIP_Token_Global_Key:-false}\"}"
_debug data "$data"
#_signature=$(printf "%s" "$data" | openssl dgst -sha512 -sign "$TRANSIP_Key_File" | _base64)
......@@ -139,6 +142,18 @@ _transip_setup() {
_saveaccountconf_mutable TRANSIP_Username "$TRANSIP_Username"
_saveaccountconf_mutable TRANSIP_Key_File "$TRANSIP_Key_File"
# download key file if it's an URL
if _startswith "$TRANSIP_Key_File" "http"; then
_debug "download transip key file"
TRANSIP_Key_URL=$TRANSIP_Key_File
TRANSIP_Key_File="$(_mktemp)"
chmod 600 "$TRANSIP_Key_File"
if ! _get "$TRANSIP_Key_URL" >"$TRANSIP_Key_File"; then
_err "Error getting key file from : $TRANSIP_Key_URL"
return 1
fi
fi
if [ -f "$TRANSIP_Key_File" ]; then
if ! grep "BEGIN PRIVATE KEY" "$TRANSIP_Key_File" >/dev/null 2>&1; then
_err "Key file doesn't seem to be a valid key: ${TRANSIP_Key_File}"
......@@ -156,6 +171,12 @@ _transip_setup() {
fi
fi
if [ -n "${TRANSIP_Key_URL}" ]; then
_debug "delete transip key file"
rm "${TRANSIP_Key_File}"
TRANSIP_Key_File=$TRANSIP_Key_URL
fi
_get_root "$fulldomain" || return 1
return 0
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment