Azure Blob Storage for SFTP の BlobCreated イベントを Azure Event Grid で拾ってみる

## 背景と目的

システムの外部連携で SFTP を使用したファイルアップロード後に後続処理を走らせたいユースケースは多いと思います。そこで、まだパブリックプレビューですが、当初対応していなかった東日本リージョンで Azure Blob Storage for SFTP が試せるようになっていました。さらに、こちらも当初対応していなかった SFTP でファイルをアップロードしたときなどのイベントも Azure Event Grid で拾えるようになっていました。もう一つ、こちらも当初対応していなかった Azure CLI での SFTP 有効化も出来るようになっていたので、実際に試してみました。

## 前提条件

```bash:bash
# SFTP サポートを有効にする
$ az extension add \
  --name storage-preview

# このバージョンで試しました
$ az version
{
  "azure-cli": "2.39.0",
  "azure-cli-core": "2.39.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {
    "storage-preview": "0.8.3"
  }
}
```

## Azure Blob Storage for SFTP を作成

```bash:bash
# 環境変数をセットします
region=japaneast
prefix=mnrsftp

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region

# 汎用 v2 ＋ 階層名前空間 ＋ SFTP を有効
az storage account create \
  --name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --sku Standard_LRS \
  --kind StorageV2 \
  --enable-hierarchical-namespace true \
  --enable-sftp=true

# コンテナを作成します
az storage container create \
  --account-name ${prefix}stor \
  --name ${prefix}container
```

## SFTP 専用ユーザーを作成

```bash:bash
# Read Write Delete List Create 権限を付与したユーザーを作成します
az storage account local-user create \
  --account-name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --name ${prefix}user01 \
  --home-directory ${prefix}container \
  --permission-scope permissions=rwdlc service=blob resource-name=${prefix}container

# SFTP 専用ユーザーのパスワードを設定します
sftppass01=$(az storage account local-user regenerate-password \
  --account-name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --name ${prefix}user01 \
  --query sshPassword \
  --output tsv)

# パスワードを確認します
echo $sftppass01
```

## ファイルのアップロードが出来ることを確認

```bash:bash
# アップロード用のテストファイルを作成します
date > date.txt

# テストファイルをアップロードします（パスワードプロンプトでパスワードを入力します）
sftp ${prefix}stor.${prefix}user01@${prefix}stor.blob.core.windows.net <<EOF
put date.txt
ls
quit
EOF
```

## ファイルアップロードイベントを Webhook で動作確認する準備

```bash:bash
# ブラウザで webhook.site にアクセスして検証用の URL を取得します
open https://webhook.site

# 検証用の URL をセットします
endpoint=https://webhook.site/15263831-5c10-43fa-a684-4c6648a60e37
```

## Azure Event Grid を作成

```bash:bash
# イベントサブスクリプションを作成します
az eventgrid event-subscription create \
  --source-resource-id $(az storage account show \
  --name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --query id \
  --output tsv) \
  --name ${prefix}-eg \
  --endpoint $endpoint

# webhook.site に表示された validationUrl にアクセスします
curl -s https://rp-japaneast.eventgrid.azure.net:553/eventsubscriptions/mnrsftp-eg/validate?id=0AA88533-32EE-409E-B8CA-A07F3784B09F&t=2022-08-28T00:42:25.9458146Z&apiVersion=2021-10-15-preview&token=peEf6V8EwJP8AIqa7PTzoWLbrcsjmisUYz3UlP0vaKw%3d
```

## ファイルをアップロードしてイベントが発生するか確認

```bash:bash
# アップロード用のテストファイルを作成します
date > date2.txt

# テストファイルをアップロードします（パスワードプロンプトでパスワードを入力します）
sftp ${prefix}stor.${prefix}user01@${prefix}stor.blob.core.windows.net <<EOF
put date2.txt
ls
quit
EOF
```

## webhook.site に表示された JSON を確認

```json:json
[
  {
    "topic": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mnrsftp-rg/providers/Microsoft.Storage/storageAccounts/mnrsftpstor",
    "subject": "/blobServices/default/containers/mnrsftpcontainer/blobs/date2.txt",
    "eventType": "Microsoft.Storage.BlobCreated",
    "id": "48210a9f-501e-0058-0077-ba8baa068339",
    "data": {
      "api": "SftpCommit",
      "requestId": "48210a9f-501e-0058-0077-ba8baa000000",
      "eTag": "0x8DA888E7524C8A4",
      "contentType": "application/octet-stream",
      "contentLength": 48,
      "contentOffset": 0,
      "blobType": "BlockBlob",
      "blobProperties": [
        {
          "acl": [
            {
              "access": "u::rw,g::r,o::",
              "permission": "0640",
              "owner": "$superuser",
              "group": "$superuser"
            }
          ]
        }
      ],
      "blobUrl": "https://mnrsftpstor.blob.core.windows.net/mnrsftpcontainer/date2.txt",
      "url": "https://mnrsftpstor.blob.core.windows.net/mnrsftpcontainer/date2.txt",
      "sequencer": "0000000000000000000000000001881d0000000000039348",
      "identity": "mnrsftpuser01",
      "storageDiagnostics": {
        "batchId": "f371bc8e-e006-0010-0077-ba969d000000"
      }
    },
    "dataVersion": "3",
    "metadataVersion": "1",
    "eventTime": "2022-08-28T00:44:25.8395331Z"
  }
]
```

## 検証環境を削除

```bash:bash
# リソースグループを削除します
az group delete \
  --name ${prefix}-rg \
  --yes
```

## 参考

https://docs.microsoft.com/ja-jp/azure/storage/blobs/secure-file-transfer-protocol-support-how-to

https://docs.microsoft.com/ja-jp/azure/event-grid/event-schema-blob-storage?tabs=event-grid-event-schema#list-of-the-events-for-sftp-apis