IIJ DNSサービスREST API(DO-API)をPowerShellから操作してみる


PowerShellの勉強を兼ねて、IIJのDNSサービスを操作するスクリプトを作成してみました。

## サンプルコード
サンプルですので、一部の機能だけをFunctionとして実装してます。APIへのアクセス、認証などの基本部分は書いてあるので、あとは必要な機能を追加していけば使えるモノになると思います。

```ps1
##################################################################
# iij_do_api.ps1
# IIJ DNSサービスREST API(DO-API)アクセス用サンプルスクリプト
#
# API Reference
# http://manual.iij.jp/dns/doapi/index.html
##################################################################

$IIJAPI_ACCESS_KEY = "YOUR_ACCESS_KEY_HERE"
$IIJAPI_SECRET_KEY = "YOUR_SECRET_KEY_HERE"
$ApiVersion = "20140601"
$DoServiceCode = "do1234567"            # サービスコード(IIJサービスオンラインで確認)
$ExpireOffset = "60"                    # APIの有効期限を分で指定する
$AccessDomain = "do.api.iij.jp"         # アクセスドメイン
$DebugFileName = "c:\IIJDNS_DEBUG.txt"  # エラーレスポンスの出力先ファイル


##################################################################
# URLエンコード
##################################################################
function Encode-URL($s){
    ($s.ToCharArray() | foreach {
			if ($_ -match "[a-z]|[-,_,.,~,)]|[0-9]") { 
				$_
			} else {
				"{0}{1:X}" -f "%", [System.Text.Encoding]::ASCII.GetBytes($_)[0]
			}
		}) -join ""
}

##################################################################
# 認証用シグネチャ生成
##################################################################
function Get-Signature($Method, $Api, $ContentMd5Value, $ContentTypeValue, $IIJApiExpire, $RequestPath) {
  
  $TempStr = New-Object System.Text.UTF8Encoding($false)
  $TempStr = $Method + "`n" `
           + $ContentMd5Value + "`n" `
           + $ContentTypeValue + "`n" `
           + "x-iijapi-expire:" + $IIJApiExpire + "`n" `
           + "x-iijapi-signaturemethod:HmacSHA256" + "`n" `
           + "x-iijapi-signatureversion:2" + "`n" `
           + $RequestPath
  
  $hmac = New-Object System.Security.Cryptography.HMACSHA256
  $hmac.Key = $IIJAPI_SECRET_KEY.ToCharArray()
  $hash = $hmac.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($TempStr))
  $signature = [System.Convert]::ToBase64String($hash)

  return $signature
}

##################################################################
# ゾーン情報の取得
##################################################################
function Get-Zones ($IIJApiExpire) {

  $RequestPath = "/r/$ApiVersion/$DOServiceCode/zones.json"
  $Signature = Get-Signature "GET" "zones" "" "" "$IIJApiExpire" "$RequestPath"
  $Headers = @{  "x-iijapi-expire" = "$IIJApiExpire";
                 "x-iijapi-signaturemethod" = "HmacSHA256";
                 "x-iijapi-signatureversion" = "2";
                 "Authorization" = "IIJAPI ${IIJAPI_ACCESS_KEY}:${Signature}";
              }

  try{
    $Resp = Invoke-RestMethod -Uri "https://${AccessDomain}${RequestPath}" -Headers $Headers
  }
  catch {
    $Resp = $_.Exception.Response.GetResponseStream()
    $Reader = New-Object System.IO.StreamReader($Resp)
    $ResponseBody = $Reader.ReadToEnd();
    $ResponseBody | Out-File $DebugFileName -Append
  }

  return $Resp.Zonelist
}

##################################################################
# ゾーン詳細情報の取得
##################################################################
function Get-ZoneDetail ($IIJApiExpire, $ZoneName) {

  $RequestPath = "/r/$ApiVersion/$DOServiceCode/$ZoneName/zone.json"
  $Signature = Get-Signature "GET" "zone" "" "" "$IIJApiExpire" "$RequestPath"
  $Headers = @{  "x-iijapi-expire" = "$IIJApiExpire";
                 "x-iijapi-signaturemethod" = "HmacSHA256";
                 "x-iijapi-signatureversion" = "2";
                 "Authorization" = "IIJAPI ${IIJAPI_ACCESS_KEY}:${Signature}";
              }

  try{
    $Resp = Invoke-RestMethod -Uri "https://${AccessDomain}${RequestPath}" -Headers $Headers
  }
  catch {
    $Resp = $_.Exception.Response.GetResponseStream()
    $Reader = New-Object System.IO.StreamReader($Resp)
    $ResponseBody = $Reader.ReadToEnd();
    $ResponseBody | Out-File $DebugFileName -Append
   }

  return $Resp
}

##################################################################
# レコード情報の取得
##################################################################
function Get-Records ($IIJApiExpire, $Zone) {

  $RequestPath = "/r/$ApiVersion/$DOServiceCode/$Zone/records/detail.json"
  $Signature = Get-Signature "GET" "records" "" "" "$IIJApiExpire" "$RequestPath"
  $Headers = @{  "x-iijapi-expire" = "$IIJApiExpire";
                 "x-iijapi-signaturemethod" = "HmacSHA256";
                 "x-iijapi-signatureversion" = "2";
                 "Authorization" = "IIJAPI ${IIJAPI_ACCESS_KEY}:${Signature}";
              }

  try{
    $Resp = Invoke-RestMethod -Uri "https://${AccessDomain}${RequestPath}" -Headers $Headers
  }
  catch {
    $Resp = $_.Exception.Response.GetResponseStream()
    $Reader = New-Object System.IO.StreamReader($Resp)
    $ResponseBody = $Reader.ReadToEnd();
    $ResponseBody | Out-File $DebugFileName -Append
  }

  return $Resp
}

##################################################################
# Main Application Logic
##################################################################

# API有効期間の設定
$TempDate = (Get-Date).AddMinutes($ExpireOffset)
$IIJApiExpire = "{0:s}" -f $TempDate
$IIJApiExpire = $IIJApiExpire + "Z"

# ゾーン情報の取得(配列として取得）
$Zones = Get-Zones "$IIJApiExpire"

# ゾーン詳細情報の取得
for($i=0; $i -lt $Zones.Length; $i++){
  $ZoneDetail = Get-ZoneDetail "$IIJApiExpire" $Zones[$i]
  Write-Host $ZoneDetail.RequestId
  Write-Host $ZoneDetail.Zone  # Type; Name; TTL; Serial; Status; RecordNum; Committable
}

# レコード情報の取得
$Signature = Get-Signature "GET" "records" "" "" "$IIJApiExpire"
$Records = Get-Records "$IIJApiExpire" $Zones[0]
Write-Host $Records

```