LoginSignup
0
0

More than 5 years have passed since last update.

Azure VMの動的パブリックIPをローテートする

Posted at

Azure VMのIPはNICからパブリックIP(PIP)の関連付けを解除→もう一度割当てを行うと別のIPになるので、
これを利用してIPをローテートする小技。
azure-cliではNICからPIPの関連付け解除ができないので、直接RESTを叩いています。

rotate-pip.sh
#!/bin/bash

# VM情報
: ${SUBSCRIPTION_ID:?}
: ${RESOURCE_GROUP_NAME:?}
: ${NIC_NAME:?}
: ${PIP_NAME:?}
: ${VNET_NAME:?}
: ${VNET_SUBNET_NAME:="Subnet"}
: ${IPCONFIG_NAME:="ipconfig1"}

# アプリケーション認証情報
: ${CLIENT_ID:?}
: ${TENANT_ID:?}
: ${CLIENT_SECRET:?}

type jq > /dev/null || exit 1

# -------------

# OAuthトークン取得
AUTHORIZATION_STRING="Bearer $(curl -sXPOST -H "Content-Type: application/x-www-form-urlencoded" "https://login.windows.net/${TENANT_ID}/oauth2/token" -d "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&resource=https://management.core.windows.net/" | jq -r '.access_token')"

NIC_ENTRYPOINT="https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/networkInterfaces/${NIC_NAME}?api-version=2016-03-30"
PIP_ENTRYPOINT="https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/publicIPAddresses/${PIP_NAME}?api-version=2016-03-30"

# NICにPUTするときのJSONのテンプレ
JSON_TEMPLATE=$(cat <<EOT
{
  "name": "${NIC_NAME}",
  "location": "japaneast",
  "properties": {
    "ipConfigurations": [
      {
        "name": "${IPCONFIG_NAME}",
        "id": "/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/networkInterfaces/${NIC_NAME}/ipConfigurations/${IPCONFIG_NAME}",
        "properties": {
          "publicIPAddress": %s,
          "subnet": {
            "id":"/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/virtualNetworks/${VNET_NAME}/subnets/${VNET_SUBNET_NAME}"
          }
        }
      }
    ]
  }
}
EOT
)

# NICへの変更リクエスト
request(){
    curl -sXPUT -H "Content-Type: application/json" -H "Authorization: ${AUTHORIZATION_STRING}" "$NIC_ENTRYPOINT" -d "$1" -o /dev/null
}

# 現在のパブリックIPアドレスを取得
get_ip() {
    curl -s -H "Authorization: ${AUTHORIZATION_STRING}" "${PIP_ENTRYPOINT}" | jq -r ".properties.ipAddress"
}

# NICの変更が完了するまで待つ
wait_for_completion() {
    printf "wait for completion"
    until [[ "$(curl -s -H "Authorization: ${AUTHORIZATION_STRING}" "${NIC_ENTRYPOINT}" | jq -r ".properties.provisioningState")" != "Updating" ]]
    do
      sleep 15
      printf "."
    done
    echo
}

# -------------

OLD_IP="$(get_ip)"
echo "OLD_IP: $OLD_IP"

# PIP取り外し
echo "remove PIP"
JSON="$(printf "$JSON_TEMPLATE" null)"
request "$JSON"

wait_for_completion

# すぐ振り直すと同じIPが付くので少し待つ
echo "wait 30 seconds for rotate"
sleep 30

# PIP付け直し
echo "set new PIP"
PIP="{\"id\":\"/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Network/publicIPAddresses/${PIP_NAME}\"}"
JSON="$(printf "$JSON_TEMPLATE" "$PIP")"
request "$JSON"

wait_for_completion

NEW_IP="$(get_ip)"
echo "NEW_IP: $NEW_IP"

# 変わってなかったら失敗扱い
[[ "$OLD_IP" != "$NEW_IP" ]] || exit 1
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0