Power Automate「Teams Webhook 要求を受信したとき」トリガーの「誰でも（認証なし）」オプションを使うフローを自動的に無効にするフローの作り方

TeamsにおけるOffice 365コネクタの廃止に伴い、利用が求められているPower Automate「Teams Webhook 要求を受信したとき」トリガーのガバナンスコントロールを追加で行うフローの作成方法及びサンプル実装を紹介します！

:::note warn
免責事項
* 本記事の内容およびサンプルは公開時のドキュメントとサービス仕様に基づいています。最新情報はマイクロソフト公式ドキュメントをご参照ください。
* 本記事の内容およびサンプルの使用に起因して、利用者に生じた損害または第三者からの請求に基づく利用者の損害について、原因の如何を問わず、一切の責任を負いません。ご自身の責任で検証の上ご利用ください。
:::

## 概要
Microsoft Teams における Office 365 コネクタの廃止が発表され、従来のWebhookを利用した仕組みはPower Automate への移行が現在推奨アクションとしてアナウンスが行われました。

https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/

本アナウンスに伴った必要なアクションや従来との変更点等々は@tomoyasasaki1204さんの書かれている記事が分かりやすくまとまっております。

https://qiita.com/tomoyasasaki1204/items/48ea14c442ea80171daa

本記事では、Power Autoamteも移行をする上での「Teams Webhook 要求を受信したとき」トリガーのガバナンスをよりサポートする仕組みを紹介します。

「Teams Webhook 要求を受信したとき」トリガーはこれまでのTeamsのOffice 365コネクタと違いHTTPのエンドポイントに認証を設定したり、実行可能ユーザーを制限したりとセキュリティ面で強化がされている一方、「誰でも」という認証なしでワークフローの実行が可能なオプションを管理者側で制御する機能が現状は提供されていません。

未認証（誰でも）のオプションは従来のTeams Webhookの仕組みを移行する上では必要なオプションかと思いますので、必ずしも禁止するべきものではないと考えております。一方で、仕様を理解し正しく利用・管理する必要はあるかと思います。

:::note info
「誰でも」を選択した場合、認証なしではあるものの生成されるURLは予測不可なものになる為、いきなり外部ユーザーの実行のリスクにさらされるというものではありません
:::

そんな背景のもと、標準では提供されていないガバナンスコントロールをPower Automateを利用し実現する方法をご紹介します。今回記事で紹介する内容およびサンプルの実装は、コントロールのレベルとしては厳しめのものをイメージし以下の機能を実現します。
1. 「Teams Webhook 要求を受信したとき」トリガーおよび、その認証オプションとして「誰でも」が指定されているワークフローが指定した環境で作成・更新された事を検知
2. 当該ワークフローを強制的に無効（オフ）にする

今回は検知したものを無効化というアプローチを取り、実質的に未認証のオプションを禁止する実装になっていますが、2の部分をその他のアクション（フローの削除、管理者へ通知、台帳に記録など）に変えて頂くことで、ガバナンスコントロールのレベルを調整頂くことが可能です。

## 前提条件
* Dataverseを利用する為、Dataverseの利用が可能なPower Automateのスタンドアロンライセンス(PremiumやProcessプラン等)が必要です
* ワークフロー実行ユーザーにはPower Platform 管理者ロールが必要になります
* (推奨事項)「Teams Webhook 要求を受信したとき」トリガーのコネクタを許可する、個別の環境
※既存の環境でコネクタを許可する事も可能ですが、今回のような特定のコネクタを利用するワークフローを一元管理する目的では環境を分離することを推奨します。

## 実装方法
今回対象のトリガーとオプションを利用しているフローを検知する仕組みとして、Dataverseを利用します。実は、Power Automateのクラウドフローはソリューション内で作成を行うと、Dataverseのシステムテーブルであるプロセス(workflow)テーブルに定義情報などの保存が行われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/1fbb7cbb-2d05-db27-b1af-947183614012.png)

:::note info
実際の定義情報はクライアントデータ(clientdata)という列にjsonの形式で格納されています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/b29bf31c-b9cd-deaf-e1bd-f9f42f32bee1.png)

:::

その為、本テーブルに保存されている定義情報を読み解くことで、どういったトリガー・アクション、パラメータが設定されているかなどを解析する事が可能なことに加え、今回検知に利用する「レコードの作成・更新」といったDataverseのイベントでPower Automateをトリガーさせることも可能です。

ただ、ここで一点重要なポイントがあり、それは **「ソリューション内で作成する必要がある」** という点です。ソリューションを介さず、マイフロー等の動線で作成した場合はこのプロセステーブルには保存が行われません。

今回はこの仕様に対応する為に、「既定でクラウドフローをソリューションに作成する」機能を利用します。本機能を環境の設定よりオンにすることで、明示的にソリューションからフローを作成せずマイフローなどから作成した場合でもユーザーが意識することなく自動的に既定のソリューション領域にクラウドフローの作成が行われるようになり、様々なソリューションに関連する恩恵を受ける事が出来るようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/530ebb31-820f-8b47-102f-7cb7774cf791.png)

https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/add-app-solution-default

:::note warn
本機能は2024/08/15時点でプレビュー機能の為、ご利用の際はプレビュー機能という点を理解した上でご利用下さい
:::

こちらの設定が完了すれば、プロセステーブルをPower Automateを利用し監視することで、新規ワークフローの作成や更新を常に検知する事が可能となります。

### 検知用のトリガーについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/9ed932ec-406b-c539-3dcc-9fb7f2e0b2a6.png)
Dataverseのレコード操作を検知するトリガーを利用し、「作成または更新」を選択します。対象のテーブルは前述した「プロセス」テーブルです。

肝心となる、当該トリガーとオプションを含むワークフローの作成だけ検知する方法は、以下のトリガー条件を利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/3dc5d8ca-5806-efb1-c5fd-1bc7176b8fa5.png)

関数の細かな仕様まではここでは紹介しませんが、以下3つの条件に一致したワークフロー（レコード）の作成と更新を検知します。

``` :triggerのkindがTeamsWebhookか
@equals(json(triggerOutputs()?['body/clientdata'])?['properties']?['definition']?['triggers']?['manual']?['kind'], 'TeamsWebhook')
```

``` :triggerAuthenticationTypeにAllが設定されているか
@equals(json(triggerOutputs()?['body/clientdata'])?['properties']?['definition']?['triggers']?['manual']?['inputs']?['triggerAuthenticationType'], 'All')
```
``` :ステータスがアクティブか（トリガーのループ回避に必要）
@equals(triggerOutputs()?['body/statuscode'], 2)
```

こちらのトリガーと条件により、「Teams Webhook 要求を受信したとき」トリガーおよび、その認証オプションとして「誰でも」が指定されているワークフローが作成・更新された際に検知するところまでできました。あとは、このワークフローを無効化するアクションを設定します。

:::note warn
サービスとして提供されるコネクタ自体の更新などで、特定に利用する条件として利用するパラメータや値は適宜メンテナンスが必要になるケースがあります。上手くトリガーされない場合にご確認下さい。
:::

### 検知したフローの無効化

「Power Automate 管理」コネクタの「フローを無効にする」を利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/68ddbcd9-6b03-e30a-a93b-76c352ecfc5f.png)

パラメータには、対象となる環境（サンプルでは設定を容易にするために環境変数を利用）と、「Flow」の欄にはトリガーで取得できる、「WorkflowIdUnique」を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/5bfb348f-21c4-8992-ceeb-e7a10e212459.png)

フロー全体は以下のようなイメージになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/582c8131-c946-7439-16fa-614b81005684.png)

以上で、この環境内でワークフローが作られる限り対象のフローを自動的に無効化をし続けられることが可能です。あとはDLPポリシーでTeams Webhook コネクタの許可を本環境に限定することでテナントの他の環境でワークフローが作成されるという心配もありません。

## サンプルの導入方法
ここまで実装方法を説明してきました。
今回記事と合わせて前述の内容を実装したサンプルのワークフローも作成をしましたので、以下にその導入方法を解説します。

### 環境の設定
* 「Teams Webhook 要求を受信したとき」トリガーの利用を許可する環境を新規に作成、もしくは既存の環境を利用
* Power Platform 管理センターにアクセスし、対象環境の[設定]を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/c23f9af0-2802-a4c5-e783-a937d854287e.png)

* [製品] > [機能] を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/a01d8562-06de-053c-4ee5-60eb49dea2bc.png)

* 「Dataverse ソリューションで新しいキャンバス アプリとクラウド フローを作成する (プレビュー)」の「クラウドフロー」のトグルをオンにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/1c95509f-b1eb-f0e8-96e7-457891cd4636.png)

* [保存]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/c3d89f9b-8cab-cf33-1ac9-282608fe2d01.png)


### ソリューションのダウンロード
以下よりソリューションファイルをダウンロード

https://github.com/yuichi-masuda/Audit-Anonymous-Webhook-Flows/releases/download/release/AuditAnonymousWebhookFlows_1_0_0_0.zip

### ソリューションのインポート
* 監視対象の環境に移動し、ダウンロードしたソリューションをインポート。

* 途中のステップで表示される環境変数にインポート先の環境の環境IDを入力下さい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/d16c3636-8f05-4956-039d-e7060a6c919a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/1c22b979-a3a0-1625-ff21-87e0c476e40d.png)

以上

## 「Teams Webhook 要求を受信したとき」トリガーを利用したフロー作成時のエラーについて
2024/08/15時点で、ソリューション内で「Teams Webhook 要求を受信したとき」トリガーを利用したフローをモダンデザイナーで保存時に、以下のようなエラーが発生する場合があるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/33a02fc8-6f6b-2927-55fa-4348d3dbe650.png)

その場合、デザイナーをクラシックに変更することで、エラーを回避する事が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171651/dde2cc48-e1ad-6758-85df-b0d43a4fd26d.png)

## まとめ
今回は、未認証（誰でも）オプションを利用しているフローを無条件でオフにするという比較的厳しいガバナンスを利かせる例をご紹介しました。ただ、冒頭にも記載した通り未認証オプションが必要なユースケースもあるかと思います。その場合には、一般的に開放する環境は本ワークフローを適用し認証オプション前提で利用してもらい、未認証オプションが必要な限られたユーザー用にはもう一つ分けた環境の用意＋申請・ガイダンスの受講、定期棚卸を必須にするなどでガバナンスのレベルを分けるなども考えられるかもしれません。

本サンプルで利用しているテクニックは他のシナリオにも流用できるかと思いますので、ご参考に頂けますと幸いです！