Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
getssl / usr / share / getssl / dns_scripts / dns_godaddy
Size: Mime:
#!/usr/bin/env bash

# Copyright (C) 2017,2018 Timothe Litt  litt at acm _dot org

VERSION="2.0"
PROG="$(basename "$0")"

# This script is used to update TXT records in GoDaddy DNS server
# It depends on JSON.sh from https://github.com/dominictarr/JSON.sh
# Place it in (or softlink it to) the same directory as this script,
# or specify its location with GODADDY_JSON
#
# See the usage text below, 00GoDaddy-README.txt, dns_add_godaddy
# and dns_del_godaddy for additional information.
#
# It may be freely used providing this notice is included with
# all copies.  The name of the author may not be used to endorse
# any other product or derivative work.  No warranty is provided
# and the user assumes all responsibility for use of this software.
#
# Bug reports are welcome at https://github.com/tlhackque/getssl/issues.

API='https://api.godaddy.com/v1/domains'
APISIGNUP='https://developer.godaddy.com/getstarted'
GETJSON='https://github.com/dominictarr/JSON.sh'

VERB="y"
DEBUG="$GODADDY_DEBUG"
[ -z "$JSON" ] && JSON="$GODADDY_JSON"
[ -z "$JSON" ] && JSON="$(dirname "$0")/JSON.sh"

while getopts 'dhj:k:s:t:qv' opt; do
    case $opt in
        d) DEBUG="Y"                                   ;;
        j) JSON="$OPTARG"                              ;;
        k) GODADDY_KEY="$OPTARG"                       ;;
        s) GODADDY_SECRET="$OPTARG"                    ;;
        t) TRACE="$OPTARG"                             ;;
        q) VERB=                                       ;;
        v) echo "dns_godaddy version $VERSION"; exit 0 ;;
        *)
            cat <<EOF
Usage
    $PROG [-dt -h -j JSON -k:KEY -s:SECRET -q] add name data [ttl]
    $PROG [-dt -h -j JSON -k:KEY -s:SECRET -q] del name data

Add or delete TXT records from GoDaddy DNS

Obtain the Key and Secret from $APISIGNUP
You must obtain a "Production" key - NOT the "Test" key you're required
to get first.

With getssl, this script is called from the dns_add_godaddy and
dns_del_godaddy wrapper scripts.

Arguments:
    add - add the specified record to the domain

    del - remove the specified record from the domain

    name is the DNS record name to add, e.g. _acme-challenge.example.org.
         Note that trailing '.' is significant in DNS.

    data is the record data, e.g. "myverificationtoken"

    ttl is optional, and defaults to the GoDaddy minimum of 600.

    If it is necessary to turn on debugging externally, define
    GODADDY_DEBUG="y" (any non-null string will do).
    For minimal trace output (to override -q), define GODADDY_TRACE="y".

Options
    -d    Provide debugging output - all requests and responses
    -h    This help.
    -j:   Location of JSON.sh Default $(dirname "$0")/JSON.sh, or
          the GODADDY_JSON variable.
    -k:   The GoDaddy API key    Default from GODADDY_KEY
    -s:   The GoDaddy API secret Default from GODADDY_SECRET
    -t:   Detailed protocol trace data is appended to specified file
    -q    Quiet - omit normal success messages,

    All output, except for this help text, is to stderr.

Environment variables
    GODADDY_JSON    location of the JSOH.sh script
    GODADDY_KEY     default API key
    GODADDY_SCRIPT  location of this script, default location of JSON.sh
    GODADDY_SECRET  default API secret
    GODADDY_TRACE   forces -q off if true
    GODADDY_TFILE   appends protocol trace to file. Overrides -t

BUGS
    Due to a limitation of the GoDaddy API, deleting the last TXT record
    would be too risky for my taste.  So in that case, I replace it with
    _dummy.record_.domain.  TXT "Ihis record is not used".  This record is
    not automatically deleted by this script, though it's perfectly OK to
    do so manually. (Via another mechanism, or if it's no longer the last.)

    This really shouldn't happen often, since most domains have at least
    one TXT record - for SPF, tracking APIs, etc.

    Report any issues to https://github.com/tlhackque/getssl/issues
EOF
            exit 0
            ;;
    esac
done
shift $((OPTIND-1))

# Check for JSON -- required for delete, but if records are added,
# we assume they'll be deleted later & don't want to strand them.

[[ "$JSON" =~ ^~ ]] && \
    eval 'JSON=`readlink -nf ' "$JSON" '`'
if [ ! -x "$JSON" ]; then
    cat <<EOF >&2
$0: requires JSON.sh as "$JSON"

The full path to JSON.sh can be specified with -j, or the
GODADDY_JSON environment variable.

You can obtain a copy from $GETJSON

Then place or softlink it to $JSON or set GODADDY_JSON.
EOF
    exit 2
fi

if [ -z "$GODADDY_KEY" ] || [ -z "$GODADDY_SECRET" ]; then
    echo "GODADDY_KEY and GODADDY secret must be defined" >&2
    exit 3
fi

[ -n "$DEBUG" ] && VERB="y"
[ -n "$GODADDY_TRACE" ] && VERB="Y"
[ -n "$GODADDY_TFILE" ] && TRACE="$GODADDY_TFILE"

# Get parameters & validate

op="$1"
if ! [[ "$op" =~ ^(add|del)$ ]]; then
    echo "Operation must be \"add\" or \"del\"" >&2
    exit 3
fi
name="$2"
if [ -z "$name" ]; then
    echo "'name' parameter is required, see -h" >&2
    exit 3
fi
data="$3"
if [ -z "$data" ]; then
    echo "'data' parameter is required, see -h" >&2
    exit 3
fi

if [ "$op" = 'del' ]; then
    ttl=
elif [ -z "$5" ]; then
    ttl="600"  # GoDaddy minimum TTL is 600
elif ! [[ "$5" =~ ^[0-9]+$ ]]; then
    echo "TTL $5 is not numeric" >&2
    exit 3
elif [ "$5" -lt 600 ]; then
    [ -n "$VERB" ] && \
        echo "$5 is less than GoDaddy minimum of 600; increased to 600" >&2
    ttl="600"
else
    ttl="$5"
fi

# --- Done with parameters

[ -n "$DEBUG" ] && \
    echo "$PROG: $op $name \"$data\" $ttl" >&2

# Authorization header has secret and key

authhdr="Authorization: sso-key $GODADDY_KEY:$GODADDY_SECRET"

if [ -n "$TRACE" ]; then
    function timestamp { local tm="$(LC_TIME=C date '+%T.%N')"
        local class="$1"; shift
        echo "${tm:0:15} ** ${class}: $*" >>"$TRACE"
    }
    timestamp 'Info' "$PROG" "V$VERSION" 'Starting new protocol trace'
    timestamp 'Args' "$@"
    curl --help | grep -q -- --trace-time && CURL_TFLAGS="--trace-time" # 7.14.0
    function curl {
        command curl ${CURL_TFLAGS} --trace-ascii % "$@" 2>>"$TRACE"
    }
    [ -n "$VERB" ] && echo "Appending protocol trace to $TRACE"
fi

[ -n "$DEBUG" ] &&  echo "$authhdr" >&2

#strip off the last period
if [[ "$name" =~ ^.+\. ]]; then
        name=${name%?}
fi

reqdomain=
reqname=

# GoDaddy REST API URL is in the format /v1/domains/{domain}/records/{type}/{name}
# for adding/updating (PUT) or deleting (DELETE) a record. The API will support up 
# to three segments in domain names (ex. mydomain.com and www.mydomain.com)
# in order to determine which domain the API call will affect (both mydomain.com and 
# www.mydomain.com will result in the modification of the mydomain.com domain.  Any 
# more than three segments (ex. sub.something.mydomain.com will result in 
# the API throwing a MISMATCH_FORMAT error.
#
# Examples
# 1. If mydomain.com was provided to this script as the domain parameter, and 
#    _acme-challengemydomain.com was provided as the name, then the URL 
#    /v1/domains/mydomain.com/records/TXT/_acme-challenge will be used which
#
# 2. If www.mydomain.com was provided to this script as the domain parameter, 
#    and _acme-challenge.www.mydomain.com was provided as the name, then the 
#    URL /v1/domains/mydomain.com/records/TXT/_acme-challenge.www will be used.

# Determine the domain and the name to use for the API the URL
# The name parameter given to us is in the format challenge.domain.
# (ex _acme-challenge.mydomain.com. - note the trailing period).  We will just
# use the name given us to determine the domain

while [[ "$name" =~ ^([^.]+)\.([^.]+.*) ]]; do
        if [ -n "${reqname}" ]; then reqname="${reqname}."; fi
        reqname="${reqname}${BASH_REMATCH[1]}"
        testdomain="${BASH_REMATCH[2]}"
        name=$testdomain
        if [[ ! "$name" =~ [^.]+\.[^.]+ ]]; then
                exit 1
        fi

        url="$API/$testdomain"

        [ -n "$DEBUG" ] && echo "Looking for domain ${testdomain}"

        response="$(curl -i -s -X GET --config - "${url}" <<EOF
                header = "Content-Type: application/json"
                header = "$authhdr"
EOF
)"
        sts=$?

        [ -n "$DEBUG" ] && cat >&2 <<EOF

Response:
curl status = $sts
--------
$response
--------
EOF
        if [ $sts -ne 0 ]; then
            echo "curl error $sts querying domain" >&2
            exit $sts
        fi

        if echo "$response" | grep -q '^HTTP/.* 200 '; then
            [ -n "$DEBUG" ] && echo "Found domain ${testdomain}"
            reqdomain=${testdomain}
            break
        fi

        code="$(echo "$response" | grep '"code":' | sed -e's/^.*"code":"//; s/\".*$//')"
        if [ "$code" = 'NOT_FOUND' ]; then
                continue
        fi
done


if [ -z "$reqdomain" ] || [ -z "$reqname" ]; then
    echo "Unable to determine domain or RR name" >&2
    exit 3
fi



if [ "$op" = "add" ]; then

        url="$API/$reqdomain/records/TXT/$reqname"

        request='[{"data":"'$data'","ttl":'$ttl'}]'
        [ -n "$DEBUG" ] && cat >&2 <<EOF
Add request to: $url
--------
$request"
--------
EOF

        result="$(curl -i -s -X PUT -d "$request" --config - "$url" <<EOF
                       header = "Content-Type: application/json" 
                       header = "$authhdr"
EOF
)"
        sts=$?
        [ -n "$DEBUG" ] && cat >&2 <<EOF

Result:
curl status = $sts
--------
$result
--------
EOF
    if [ $sts -ne 0 ]; then
        echo "curl error $sts adding record" >&2
        exit $sts
    fi
    if ! echo "$result" | grep -q '^HTTP/.* 200 '; then
        code="$(echo "$result" | grep '"code":' | sed -e's/^.*"code":"//; s/\".*$//')"
        msg="$(echo "$result" | grep '"message":' | sed -e's/^.*"message":"//; s/\".*$//')"
        if [ "$code" = "DUPLICATE_RECORD" ]; then
            if [ -n "$VERB" ]; then
                echo "$msg in $reqdomain" >&2
            fi
            exit 0 # Duplicate record is still success
        fi
        echo "Request failed $msg" >&2
        exit 1
    fi
    [ -n "$VERB" ] && echo "$reqdomain: added $reqname $ttl TXT \"$data\"" >&2
    exit 0
    
fi



if [ "$op" = "del" ]; then
    url="$API/$reqdomain/records/TXT/$reqname"
    [ -n "$DEBUG" ] && echo "Deleting challenge TXT records at: $url" >&2    

    current="$(curl -i -s -X DELETE --config - "$url" <<EOF
                    header = "$authhdr" 
EOF
)"

    sts=$?
    if [ $sts -ne 0 ]; then
        echo "curl error $sts for query" >&2
        exit $sts
    fi
    [ -n "$DEBUG" ] && cat >&2 <<EOF

Response
--------
$current
--------
EOF

    if ! echo "$current" | grep -q '^HTTP/.* 204 '; then
        code="$(echo "$current" | grep '"code":' | sed -e's/^.*"code":"//; s/\".*$//')"
        msg="$(echo "$current" | grep '"message":' | sed -e's/^.*"message":"//; s/\".*$//')"
        echo "Request failed $msg" >&2
        exit 1
    fi

    [ -n "$VERB" ] && echo "$reqdomain: deleted $reqname TXT \"$data\"" >&2
    exit 0
fi