IBM NSOne shell scripts

I have been using IBM’s NSOne system to manage the DNS for my domains. I needed a good way to manage those domains via scripts, so I put these together. Hopefully they’ll be useful for someone else as well.

NSOne seems to have very good features, the most unique of which is a ‘linked record’. A linked record (for example a linked A record) behaves the same as a manually configured entry in terms of lookup. But, if the link target is updated then the linked record is updated too. While similar to CNAME it actually saves a nameserver lookup since the A record is returned immediately instead of the resolver having to look up the CNAME target. You can even extend that to even ‘linked zones’ that keep similar domains in lockstep. Kinda cool, I thought.

Make sure you have the requisites for the scripts below installed by doing the following:

apt -y install curl jq

The updater shell script

First of all I needed a shell script to update the DNS entry on my domains with NS1. The API is quite simple to use. I knocked up the following BASH script to be able to update a record on the NS1 side easily. It will also. Save this as ‘updatensonerecord‘, for example.

#!/bin/bash

APIKEY=<your IBM NS1 API Key>

DOMAIN=$1
HOST=$2
RECORDTYPE=$3
DATA=$4
MODE=$5

if [ "$HOST" == "$DOMAIN" ]; then
  RECORDNAME=$DOMAIN
else
  RECORDNAME=${HOST}.${DOMAIN}
fi

if [ "$MODE" == "" ]; then
  MODE='auto'
fi

if [ "$DATA" != "" ]; then
  if [ "$MODE" == "append" ]; then
    sleep 2
  fi
  RCVDATA=`curl --silent --request GET --url https://api.nsone.net/v1/zones/${DOMAIN}/${RECORDNAME}/${RECORDTYPE} --header "X-NSONE-Key: $APIKEY" --header 'Accept: application/json'`
  RESPONSE=`echo $RCVDATA | jq -r '.message'`
  PREVIOUSDATA=""
  if [ "$RESPONSE" == "record not found" ]; then
    OP='PUT'
  else
    if [ "$MODE" != "overwrite" ]; then
      PREVIOUSDATA=`echo $RCVDATA | jq -r '.answers[]'`
      #for PREVANS in `echo $RCVDATA | jq -r '.answers[].answer[]'`
      #do
      #  PREVIOUSDATA="${PREVIOUSDATA}, \"${PREVANS}\""
      #done
    fi
    OP='POST'
  fi

  if [ "$PREVIOUSDATA" != "" ]; then
    NEWDATA="{\"answers\": [ { \"answer\": [ \"${DATA}\" ] }, ${PREVIOUSDATA} ], \"domain\": \"${RECORDNAME}\", \"zone\":\"${DOMAIN}\", \"type\":\"${RECORDTYPE}\"}"
  else
    NEWDATA="{\"answers\": [ { \"answer\": [ \"${DATA}\" ] } ], \"domain\": \"${RECORDNAME}\", \"zone\":\"${DOMAIN}\", \"type\":\"${RECORDTYPE}\"}"
  fi

  RESPONSE=`curl --silent --request $OP --data "$NEWDATA" --url https://api.nsone.net/v1/zones/${DOMAIN}/${RECORDNAME}/${RECORDTYPE} --header "X-NSONE-Key: $APIKEY" --header 'Accept: application/json' | jq -r '.id'`
  if [ "$RESPONSE" != "" ]; then
    echo "Set $RECORDTYPE for $RECORDNAME to $DATA"
  fi
fi

The record reading/fetching script

To fetch and check data. Save this as ‘fetchnsonerecord‘, for example.

#!/bin/bash

APIKEY=<your IBM NS1 API Key>

DOMAIN=$1
HOST=$2
RECORDTYPE=$3

if [ "$HOST" == "$DOMAIN" ]; then
  RECORDNAME=$DOMAIN
else
  RECORDNAME=${HOST}.${DOMAIN}
fi

RCVDATA=`curl --silent --request GET --url https://api.nsone.net/v1/zones/${DOMAIN}/${RECORDNAME}/${RECORDTYPE} --header "X-NSONE-Key: $APIKEY" --header 'Accept: application/json'`
echo $RCVDATA

The record removal script

To remove records (helpful when adding temporary records). Save this as ‘removensonerecord‘, for example.

#!/bin/bash

APIKEY=<your IBM NS1 API Key>

DOMAIN=$1
HOST=$2
RECORDTYPE=$3

if [ "$HOST" == "$DOMAIN" ]; then
  RECORDNAME=$DOMAIN
else
  RECORDNAME=${HOST}.${DOMAIN}
fi

if [ "$RECORDTYPE" != "" ]; then
  RESPONSE=`curl --silent --request GET --url https://api.nsone.net/v1/zones/${DOMAIN}/${RECORDNAME}/${RECORDTYPE} --header "X-NSONE-Key: $APIKEY" --header 'Accept: application/json' | jq -r '.message'`
  if [ "$RESPONSE" != "record not found" ]; then
    RESPONSE=`curl --silent --request DELETE --url https://api.nsone.net/v1/zones/${DOMAIN}/${RECORDNAME}/${RECORDTYPE} --header "X-NSONE-Key: $APIKEY" --header 'Accept: application/json' | jq .id`
    echo "Removed $RECORDTYPE for $RECORDNAME"
  fi
fi