TeamsのWebhookを使いオンプレからPowerShellなどでSPOリストに書き込む

## こんな人向けの記事です
オンプレから、何かの情報をSharePointリストなどのMicrosoft 365のクラウド側へ値を渡したいけれど、OneDriveアプリも、PnP Onlineも、サービスプリンシパルもSharePoint APIも塞がれているような方向けの、選択肢のひとつとして書いてみています。

BlobストレージならAzcopyコマンドをSASで使うような方法があるのですが、SPOに値を持っていくってハードル高くないですか？

## TeamsのIncomming Webhookって使えなくなるらしい
なんか最近この話題が出ていて、いろいろなシステムからTeamsのチャネルへ投稿させるのに使われていたInComming Webhookが使えなくなり、代替手段としてWorkflowを使いましょうということになっているようです。

まず、これまでの方法からおさらいします。まだIncomming Webhookは消えていません。

新しいTeamsから従来のIncomming Webhookを使う場合は、チャネルの3点リーダーから「チャネルを管理」を開き、コネクタの項目にある「編集」を開きます。
![スクリーンショット 2024-07-12 15.47.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/94c56a30-f471-6ea4-52de-021d6ae499a1.png)

ここに表示されているのが話題のIncomming Webhookです。

![スクリーンショット 2024-07-12 15.48.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/e229167d-6608-9d4d-7f62-1608aed48c37.png)

## これからはWorkflowをつかう
今後のお作法はワークフローをつかうこと。チャネルの3点リーダーから「ワークフロー」をクリックします。

![スクリーンショット 2024-07-12 15.50.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/378cffa8-27a1-2c94-7b9b-383e81c01ecd.png)

中央あたりに「Webhook要求を受信するとチャネルに投稿する」を選択します。

![スクリーンショット 2024-07-12 15.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/6b398afa-3697-c7f5-b847-131ab05f628f.png)

フローに適当な名前をつけて「次へ」進みます。

![スクリーンショット 2024-07-12 15.52.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/66bddf8f-3a9c-8f27-d6d2-beafe7105a3a.png)

すると、Webhook用のURLが発行されました。「変更を行いますか？ワークフローを管理する」の部分にリンクがあるので開いてみます。

![スクリーンショット 2024-07-12 15.54.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/6fdc0866-8c93-6e4a-e895-fbae1e2fa168.png)

Teams内ですが自動で作成されたクラウドフローが見えました。ちなみに、ふつうに　 [https://make.powerautomate.com](https://make.powerautomate.com)　からもここで作成されたクラウドフローは開くことができます。クラウドフローは規定の環境に保存されていました。「編集」をクリックしてみます。

![スクリーンショット 2024-07-12 15.57.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/50366dc8-ce9a-8a7d-4145-4618fd905d26.png)

中身を見ると、先ほどのURLが変更できない状態で「When a Teams webhook request is received」トリガーに設定されています。その中身をアダプティブカードでチャネルに投稿するというシンプルな仕組みです。

![スクリーンショット 2024-07-12 15.59.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/b89613e5-64a3-b325-f4e0-ba1ce504f1aa.png)

POSTMANを使って、先ほどのURLにメッセージをPOSTしてみます。

POSTMANはMicrosoftのLearnでも紹介されているツールで、インストール版もWEB版もあり、Googleアカウントなどで簡単にサインインできます。　URLを入れてSendするだけなのですが、POSTも送信したい情報をBodyにペタリ。ヘッダーも枠に入力したり変数使えたり。おまけに主要な言語やスクリプトの場合はどう書けば良いのか、テストした結果を簡単にコピーして使えるという神仕様。日本語もエンコード処理せずにつかえるので使って損なしです。　始めてでしたらこちらが参考になりそうです。

https://qiita.com/shinry/items/c0e9a67838085497811f

Teams Webhookに対して、どんな本文を送れば良いかは、こちらのLearnに書いてありますので覗いてみましょう。

https://learn.microsoft.com/en-us/connectors/teams/?tabs=text1#when-a-teams-webhook-request-is-received

Learnのページの、Exampleに書かれているJSON文字列をそのままコピーしておきます。

![スクリーンショット 2024-07-12 16.04.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/4c1625a6-0fb8-1220-76bd-42e3aaa1b303.png)

先ほどのURLに対して、BodyにJSONをぺたりと貼り付けて、POSTに切り替えた状態で「Send」をクリックしてみます。

![スクリーンショット 2024-07-12 16.05.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/9f622801-b10f-54be-1248-5c18a2a97844.png)

URLに対して投稿されると、クラウドフローがトリガーされ、JSONの内容が後続のアダプティブカード投稿に渡されて処理が成功しました。

![スクリーンショット 2024-07-12 16.08.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/cd57051c-3a81-ddc5-07db-3e3b4da731bc.png)

結果として、チームのチャネルにJSONで送った内容がアダプティブカードとして表示されました。なるほど。これがWebhook! 便利そうですね。

![スクリーンショット 2024-07-12 16.11.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/3cc5288c-b455-f69d-9b31-004eaaf12c66.png)

## さて、ここからが本題
決まった形のJSONを送信してやると、アダプティブカードに投稿できることはわかったけれど、JSONなら何でも送信できるんじゃない？　と思ったので実験します。アダプティブカードの処理部分を削除して「作成」アクションをおき、トリガーの本文が表示できるようにしました。

![スクリーンショット 2024-07-12 16.16.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/bd1cb0b9-eb19-b5c7-3bd5-b13b54b87c96.png)

Bodyには以下のとおり。送信してみると、202 Accepted!!ですやん。受け付けられました。

    {"text":"はろーわーるど"}

![スクリーンショット 2024-07-12 16.17.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/8cb603ff-a6d9-5eef-53ec-aced1f48968d.png)

やっぱり！　普通に文字列を受け取れています。
![スクリーンショット 2024-07-12 16.21.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/6ec40057-b530-8577-6854-60b9a4c3404b.png)

というわけで、POSTMANで試したことをコマンドにするとこんな感じ。いずれでも投稿できました。

``` PowerShell:wget
wget --no-check-certificate --quiet \
  --method POST \
  --timeout=0 \
  --header 'Content-Type: application/json' \
  --body-data '{"text":"はろーわーるど"}' \
   'https://取得したURL'
```

``` PowerShell:Curl
curl --location 'https://取得したURL' \
--header 'Content-Type: application/json' \
--data '{"text":"はろーわーるど"}'

```

```PowerShell:PowerShell
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/json")

$body = @"
{`"text`":`"はろーわーるど`"}
"@

Invoke-RestMethod 'https://取得したURL' -Method 'POST' -Headers $headers -Body $body
```

## 値を渡せるということは、SharePointリストにだって
Teamsの機能としてのWebhookを借用して、値をアダプティブカードではなくてSharePointリストにだって渡せるでしょう？ということでやってみましょう。

トリガーのBodyをSharePointリストに渡します。動的な選択肢にはでてこなかったので、以下のように式を設定してください。

    triggerBody()?['text']
![スクリーンショット 2024-07-12 16.47.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/1b9dbc02-e526-2dd4-af0a-314d7b95c51f.png)

SharePointリストに、PowerShellから投稿することができました！
![スクリーンショット 2024-07-12 16.54.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/cbdb5ccc-faed-81ec-dea5-acca2d805c6e.png)

## ところで、MACでPowerShell使えるんですね。
普段はあまり使ってないのですが、たまたまこの記事はMacを使って書いていたので、いけねっ！ PowerShellつかえないやん！　と思ったのですが。

HomeBrewを使ってMacにもPowerShellを簡単にインストールできました。CurlもWgetでも、コマンドひとつで簡単インストール。　

https://learn.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-macos

Homebrewってすごいですね。

https://brew.sh/ja/


## Anyoneを避けるには？
すでにお気づきでしょうが、WebhookはURLさえ知っていればそこにPOSTするだけで受信してしまいます。

テナントのユーザー、特定のユーザーというトリガーの指定ができるのですが、POSTのヘッダーに　Graph Explorerから取得したトークンを、Authorization: Bearer　hogehoge　をつけてみてもうまく認証できませんでした。

このあたり方法をご存知でしたら是非教えていただきたいです。

![スクリーンショット 2024-07-12 16.41.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/bfcc87b9-7621-cd48-4b17-da8022076b9f.png)

## Webhooｋを使う時の注意点
こんなに簡単に渡せて良いのかしら？　と素人ながら思います。やっぱり認証は必要ですよね。

Webhookを使う場合のベストプラクティスがこちらの記事で触れられていました。認証。どうやったらいいんだろう？

https://qiita.com/minimabot/items/9d044e613a51c90018b1#webhook%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E3%83%99%E3%82%B9%E3%83%88%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B9