#!/usr/bin/env sh
# Namecheap API
# https://www.namecheap.com/support/api/intro.aspx
#
# Requires Namecheap API key set in NAMECHEAP_API_KEY, NAMECHEAP_SOURCEIP and NAMECHEAP_USERNAME set as environment variable
# Due to Namecheap's API limitation all the records of your domain will be read and re applied, make sure to have a backup of your records you could apply if any issue would arise.
######## Public functions #####################
if [ " $STAGE " -eq 1 ] ; then
NAMECHEAP_API = "https://api.sandbox.namecheap.com/xml.response"
else
NAMECHEAP_API = "https://api.namecheap.com/xml.response"
fi
#Usage: dns_namecheap_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_namecheap_add( ) {
fulldomain = $1
txtvalue = $2
if ! _namecheap_check_config; then
_err " $error "
return 1
fi
if ! _namecheap_set_publicip; then
return 1
fi
_debug "First detect the root zone"
if ! _get_root " $fulldomain " ; then
_err "invalid domain"
return 1
fi
_debug fulldomain " $fulldomain "
_debug txtvalue " $txtvalue "
_debug domain " $_domain "
_debug sub_domain " $_sub_domain "
_set_namecheap_TXT " $_domain " " $_sub_domain " " $txtvalue "
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_namecheap_rm( ) {
fulldomain = $1
txtvalue = $2
if ! _namecheap_set_publicip; then
return 1
fi
if ! _namecheap_check_config; then
_err " $error "
return 1
fi
_debug "First detect the root zone"
if ! _get_root " $fulldomain " ; then
_err "invalid domain"
return 1
fi
_debug fulldomain " $fulldomain "
_debug txtvalue " $txtvalue "
_debug domain " $_domain "
_debug sub_domain " $_sub_domain "
_del_namecheap_TXT " $_domain " " $_sub_domain " " $txtvalue "
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root( ) {
domain = $1
if ! _namecheap_post "namecheap.domains.getList" ; then
_err " $error "
return 1
fi
i = 2
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
if ! _contains " $response " " $h " ; 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
}
_namecheap_set_publicip( ) {
if [ -z " $NAMECHEAP_SOURCEIP " ] ; then
_err "No Source IP specified for Namecheap API."
_err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP"
return 1
else
_saveaccountconf NAMECHEAP_SOURCEIP " $NAMECHEAP_SOURCEIP "
_debug sourceip " $NAMECHEAP_SOURCEIP "
ip = $( echo " $NAMECHEAP_SOURCEIP " | _egrep_o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' )
addr = $( echo " $NAMECHEAP_SOURCEIP " | _egrep_o '(http|https)://.*' )
_debug2 ip " $ip "
_debug2 addr " $addr "
if [ -n " $ip " ] ; then
_publicip = " $ip "
elif [ -n " $addr " ] ; then
_publicip = $( _get " $addr " )
else
_err "No Source IP specified for Namecheap API."
_err "Use your public ip address or an url to retrieve it (e.g. https://ipconfig.co/ip) and export it as NAMECHEAP_SOURCEIP"
return 1
fi
fi
_debug publicip " $_publicip "
return 0
}
_namecheap_post( ) {
command = $1
data = " ApiUser= ${ NAMECHEAP_USERNAME } &ApiKey= ${ NAMECHEAP_API_KEY } &ClientIp= ${ _publicip } &UserName= ${ NAMECHEAP_USERNAME } &Command= ${ command } "
response = " $( _post " $data " " $NAMECHEAP_API " "" "POST" ) "
_debug2 response " $response "
if _contains " $response " "Status=\"ERROR\"" >/dev/null; then
error = $( echo " $response " | _egrep_o ">.*<\\/Error>" | cut -d '<' -f 1 | tr -d '>' )
_err " error $error "
return 1
fi
return 0
}
_namecheap_parse_host( ) {
_host = $1
_debug _host " $_host "
_hostid = $( echo " $_host " | _egrep_o '\sHostId="[^"]*' | cut -d '"' -f 2)
_hostname = $( echo " $_host " | _egrep_o '\sName="[^"]*' | cut -d '"' -f 2)
_hosttype = $( echo " $_host " | _egrep_o '\sType="[^"]*' | cut -d '"' -f 2)
_hostaddress = $( echo " $_host " | _egrep_o '\sAddress="[^"]*' | cut -d '"' -f 2)
_hostmxpref = $( echo " $_host " | _egrep_o '\sMXPref="[^"]*' | cut -d '"' -f 2)
_hostttl = $( echo " $_host " | _egrep_o '\sTTL="[^"]*' | cut -d '"' -f 2)
_debug hostid " $_hostid "
_debug hostname " $_hostname "
_debug hosttype " $_hosttype "
_debug hostaddress " $_hostaddress "
_debug hostmxpref " $_hostmxpref "
_debug hostttl " $_hostttl "
}
_namecheap_check_config( ) {
if [ -z " $NAMECHEAP_API_KEY " ] ; then
_err "No API key specified for Namecheap API."
_err "Create your key and export it as NAMECHEAP_API_KEY"
return 1
fi
if [ -z " $NAMECHEAP_USERNAME " ] ; then
_err "No username key specified for Namecheap API."
_err "Create your key and export it as NAMECHEAP_USERNAME"
return 1
fi
_saveaccountconf NAMECHEAP_API_KEY " $NAMECHEAP_API_KEY "
_saveaccountconf NAMECHEAP_USERNAME " $NAMECHEAP_USERNAME "
return 0
}
_set_namecheap_TXT( ) {
subdomain = $2
txt = $3
tld = $( echo " $1 " | cut -d '.' -f 2)
sld = $( echo " $1 " | cut -d '.' -f 1)
request = " namecheap.domains.dns.getHosts&SLD= $sld &TLD= $tld "
if ! _namecheap_post " $request " ; then
_err " $error "
return 1
fi
hosts = $( echo " $response " | _egrep_o '<host[^>]*' )
_debug hosts " $hosts "
if [ -z " $hosts " ] ; then
_error "Hosts not found"
return 1
fi
_namecheap_reset_hostList
while read -r host; do
if _contains " $host " "<host" ; then
_namecheap_parse_host " $host "
_namecheap_add_host " $_hostname " " $_hosttype " " $_hostaddress " " $_hostmxpref " " $_hostttl "
fi
done <<EOT
echo " $hosts "
EOT
_namecheap_add_host " $subdomain " "TXT" " $txt " 10 120
_debug hostrequestfinal " $_hostrequest "
request = " namecheap.domains.dns.setHosts&SLD= ${ sld } &TLD= ${ tld } ${ _hostrequest } "
if ! _namecheap_post " $request " ; then
_err " $error "
return 1
fi
return 0
}
_del_namecheap_TXT( ) {
subdomain = $2
txt = $3
tld = $( echo " $1 " | cut -d '.' -f 2)
sld = $( echo " $1 " | cut -d '.' -f 1)
request = " namecheap.domains.dns.getHosts&SLD= $sld &TLD= $tld "
if ! _namecheap_post " $request " ; then
_err " $error "
return 1
fi
hosts = $( echo " $response " | _egrep_o '<host[^>]*' )
_debug hosts " $hosts "
if [ -z " $hosts " ] ; then
_error "Hosts not found"
return 1
fi
_namecheap_reset_hostList
found = 0
while read -r host; do
if _contains " $host " "<host" ; then
_namecheap_parse_host " $host "
if [ " $_hosttype " = "TXT" ] && [ " $_hostname " = " $subdomain " ] && [ " $_hostaddress " = " $txt " ] ; then
_debug "TXT entry found"
found = 1
else
_namecheap_add_host " $_hostname " " $_hosttype " " $_hostaddress " " $_hostmxpref " " $_hostttl "
fi
fi
done <<EOT
echo " $hosts "
EOT
if [ $found -eq 0 ] ; then
_debug "TXT entry not found"
return 0
fi
_debug hostrequestfinal " $_hostrequest "
request = " namecheap.domains.dns.setHosts&SLD= ${ sld } &TLD= ${ tld } ${ _hostrequest } "
if ! _namecheap_post " $request " ; then
_err " $error "
return 1
fi
return 0
}
_namecheap_reset_hostList( ) {
_hostindex = 0
_hostrequest = ""
}
#Usage: _namecheap_add_host HostName RecordType Address MxPref TTL
_namecheap_add_host( ) {
_hostindex = $( _math " $_hostindex " + 1)
_hostrequest = $( printf '%s&HostName%d=%s&RecordType%d=%s&Address%d=%s&MXPref%d=%d&TTL%d=%d' " $_hostrequest " " $_hostindex " " $1 " " $_hostindex " " $2 " " $_hostindex " " $3 " " $_hostindex " " $4 " " $_hostindex " " $5 " )
}