【Azure IoT Hub】SAS TokenはNew-AzIotHubSasTokenでなくaz iot hub generate-sas-tokenで発行する

# tl;dr

1. `New-AzIotHubSasToken`ではなく`az iot hub generate-sas-token`を使いましょう。
2. なお、AzureRMは2020年12月でサポートが終了します

# 経緯

日本で展開しているサービスを中国でも展開することになりました。
Azure IoT HubにREST APIでアクセスしている箇所があったので、リソース展開後にSAS Tokenを取得したらうまく接続できませんでした。（前、どうやって作成したっけ？）

なお、以下のコマンドはすべてPowerShellです。

## 試したこと1: Azure PortalからAzure Cloud Shellの実行

下記画像をご覧いただくと分かる通り、中国リージョンではCloud Shellが展開されていないようです。
あ、どうしよう・・ってなりました。
![iot_CloudShell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7886/dfd13034-0f0b-0566-5553-41c0b79104b5.png)

## 試したこと2: `New-AzIotHubSasToken`コマンドでSAS Token発行

たまたまPCに入っていたのがAzureRMだったのです。
というわけで、とても見事に壁にあたってしまいました。

### 手順

サインイン

```powershell
connect-azaccount -environment azurechinacloud
```
中国リージョンは`-environment azurechinacloud`必須です。
エンドポイントについての詳細は、[Azure から独立しているクラウドでの Azure PowerShell によるストレージの管理 > エンドポイントサフィックス](https://docs.microsoft.com/ja-jp/azure/storage/common/storage-powershell-independent-clouds#endpoint-suffix)を参照してください。

意気揚々とIoT HubのSAS Tokenを発行します。

```powershell
New-AzIotHubSasToken
  -ResourceGroupName "{resourceGroupName}"
  -IotHubName "{iotHubName}"
  -Duration 31104000
  -KeyName "iothubowner"
```

アクセスできるか試してみます。

```powershell
Invoke-WebRequest
  https://{iotHubName}.azure-devices.cn/twins/{deviceName}?api-version=2018-06-30
  -Headers @{
    "Authorization"="SharedAccessSignature sr={iotHubName}.azure-devices.cn&sig=x&se=x&skn=iothubowner"
  }
```

エラーがでます

```json
{
    "Message": "ErrorCode:IotHubUnauthorizedAccess;Unauthorized",
    "ExceptionMessage": "Tracking ID:00000000000000000000000000000000-G:7-TimeStamp:08/25/2020 00:00:00"
}
```
Unauthorized・・。
SAS Tokenが誤っていることが原因なのですが、SAS Tokenを送らなくても（空でも）同じメッセージが返されるので、最初、何が原因なのか分かりませんでした。

## 試したこと3: `az iot hub generate-sas-token`コマンドでSAS Token発行

### 手順

Azure CLI（Azure PowerShell Az モジュール）をインストールします
- [Azure CLI のインストール](https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli?view=azure-cli-latest)

ログインし、サブスクリプションを指定します。

```powershell
az login --tenant {tenantName}
az account set --subscription {subscriptionId}
```

疑心暗鬼になりながらSAS Tokenを発行してみます。

```powershell
az iot hub generate-sas-token -n {iotHubName}
```

アクセスできるか試してみます。

```powershell
Invoke-WebRequest
  https://{iotHubName}.azure-devices.cn/twins/{deviceName}?api-version=2018-06-30
  -Headers @{
    "Authorization"="SharedAccessSignature sr={iotHubName}.azure-devices.cn&sig=x&se=x&skn=iothubowner"
  }
```

あ、うまくいきました。

```
StatusCode        : 200
StatusDescription : OK
Content           : {"deviceId":"x","etag":"x","deviceEtag":"x","status":"enabled
                    ","statusUpdateTime":"0001-01-01T00:00:00Z","connectionState":"Disconnected","lastActivityTime":"20
                    20...
RawContent        : HTTP/1.1 200 OK
                    Vary: Origin
                    x-ms-request-id: 00000000-0000-0000-0000-000000000000
                    Content-Length: 1199
                    Content-Type: application/json; charset=utf-8
                    Date: Tue, 25 Aug 2020 00:00:00 GMT
                    Server: ...
Forms             : {}
Headers           : {[Vary, Origin], [x-ms-request-id, 00000000-0000-0000-0000-000000000000], [Content-Length, 1199], [
                    Content-Type, application/json; charset=utf-8]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 1199
```

## おまけ: Visual Studio Code拡張（vscode-azure-iot-toolkit）でSAS Token発行

Visual Studio Codeの拡張機能を使うと、とても簡単にSAS Tokenを発行することができます。
![Generate SAS Token for IoT Hub](https://raw.githubusercontent.com/wiki/Microsoft/vscode-azure-iot-toolkit/images/generatesastokeniothub.gif)
でもデバイスごとのSAS Tokenは、うまく動作しません。
なぜ？

# デバイスツインを取得する方法

```bash
curl -X GET "https://{iotHubName}.azure-devices.cn/twins/{deviceName}?api-version=2018-06-30"
     -H "Authorization: SharedAccessSignature sr=x&sig=x&se=x&skn=iothubowner"
```

# 雑記

ちなみに、この件を調べていたら、自分が書いた記事を見つけて「コマンド変えたくらいで発行されたToken変わるわけじゃないしなー」と思って、試すのが遅れました。

過去の私、ごめんなさい。

- [Azure Iot HubのダイレクトメソッドをREST APIから呼んでみる](https://qiita.com/hydrangeas/items/a30c7e7881369122c921)

アウトプットって本当に大事ですね。
あと、偏見と先入観をもたず、記事を読みましょう。

以上。