FormsとPower AutomateでEntra IDのゲスト招待システム&棚卸システムをつくってみる(その3)

ゲスト招待システム

テナント内のゲスト管理は、いちど招待したあとほったらかしになっていることありませんか?

過去に取引のあった企業でも、当時の取引先担当者がその後もずっと我社のSharePointなどにアクセス権をもった状態というのは、セキュリティ上よろしくないことは想像できますね。

取引先のユーザーを招待するということは、社内の誰かが要望したということ。このシリーズでは、ゲスト招待の申請をした人を明らかにしつつ、ゲストとしてサインインできる期間も申請させ、期限が近づいたら招待を申請したユーザー(自社の社員)に延長するかどうかを決めさせる仕組みを作ってみようという試みです。

システムと言っても、Microsoft 365 E3 ライセンスを持つユーザーなら追加費用がかからない範囲での作成を目指します。具体的にいうと、Power PlatformのPower AutomateおででよびFormsを使います。

Entra IDへのゲスト追加自体は一般ユーザーの権限では行えない(というあたりも作りながら確認するのですが)ので、そのあたりは適切なロールが何なのかも探ろうと思います。

ここまでの開発についての試行錯誤は、

その1 SharePointリストと紐付いたFormsで申請画面をつくる

その2 承認要求を送信する

をご覧ください。

全体の構想をおさらいします

処理を文章で書き起こしました。前回までとその3のあたりの構想を見直しました。

  1. (その1)Formsでユーザーがゲスト招待申請を投稿する
  2. (その1)クラウドフローがSPOリストの追加によってトリガーされる
  3. (その2)入力されたゲストEmailがメールアドレスとして妥当か(正規表現が使える?)確認して、受付または却下メールを申請者へ送る(却下ならステータスを「却下」にして、備考に理由を書き込む。妥当ならステータスを「承認待ち」にして申請日を書き込む)
  4. (その2)承認者ユーザーに承認要求を送る。
  5. (その3)承認が通ったら承認日時に書き込み、ステータスを「承認済み」に更新して次へ進む。
  6. (その3)却下の場合は、承認者のコメントを含めたメールを申請者に送る
  7. (その3)14日間承認されない場合は、ステータスを「承認待ち14日期限切れ」に変えて申請者へメールを送る。
  8. 管理者としてEntra IDのゲストを登録する
  9. 登録が成功したら、SPOリストの棚卸期限列に、ゲスト招待期間の数字を加えた日付を登録する
  10. 登録が成功したら、承認者と申請者にメールで通知する
  11. 登録が失敗したら、管理者へ通知する(チャネル投稿)→Teamsチャネルを見て、エラーを確認し、手動でゲスト登録をしてSPOリストを書き換え、チャネルに行った対応を投稿する運用で回避。SPOリストにTeamsの投稿URLを入力できる列があっても良いかも。

承認要求を送ってコメントも書いてみる

その2のおさらいです。Formsで作ったゲスト招待システムの申請を行っていましょう。

フローは実行中になって、「開始して承認を待機」アクションが待機中になっています。

承認者のアデルさんに承認要求が届きました。今回はコメントに入力をしてから「ゲストを承認する」をクリックします。

すると待機状態だったアクションが完了しました。承認者が入力したコメントは、comentsに表示されています。このあたりを使いながら、申請者に経過を知らせるメールを送ってあげれば良さそうです。

承認しない場合の動作

次は、「承認しない」を選んだ場合の動きを確認します。コメントもつけてみます。

却下の結果はこんなJSONが返ってきます。responsesの値が配列担っているのが気になります。複数の承認者が想定された作りになっていますが、今回の承認は1名だけなので注意が必要です。

{
  "responses": [
    {
      "responder": {
        "id": "f23dabca-2439-4b8f-a17a-a10cd4a22592",
        "displayName": "Adele Vance",
        "email": "AdeleV@0phny.onmicrosoft.com",
        "tenantId": "f91ab2b5-8d05-4237-91ab-1939d17d05cc",
        "userPrincipalName": "AdeleV@0phny.onmicrosoft.com"
      },
      "requestDate": "2025-04-27T02:42:51Z",
      "responseDate": "2025-04-27T02:45:26Z",
      "approverResponse": "承認しない",
      "comments": "なんとなくって、なんやねん!!"
    }
  ],
  "responseSummary": "承認者: Adele Vance (AdeleV@0phny.onmicrosoft.com)\r\n応答: 承認しない\r\n依頼日: 2025年4月27日 2:42:51\r\n応答日: 2025年4月27日 2:45:26",
  "completionDate": "2025-04-27T02:45:26Z",
  "outcome": "承認しない",
  "name": "5cef1b61-4bfa-4bff-9e8f-8ea3d2492f72",
  "title": "【ゲスト招待承認の依頼】mocabrown daddyさんから承認の依頼がとどきました。",
  "details": "mocabrown daddy<daddy@0phny.onmicrosoft.com>さんより、ゲスト招待の申請がありました。下記の内容を確認の上、承認をお願いいたします。\n\nゲストEmail:daddy@mocabrown.com\nゲスト氏名:DD in ランゲルハンス島\nゲスト所属:株式会社モカ式\n招待期間:180\n招待理由;\nなんとなく\n",
  "requestDate": "2025-04-27T02:42:51Z",
  "expirationDate": "9999-12-31T23:59:59Z",
  "priority": "Medium"
}

承認者が判断できないので、他の人にお願いする再割当て

では、承認者が別の人に承認をお願いした場合はどうなるのか。再割当てしてみます。

なるほど。自分が承認できないときには、他の人を指名できるみたいです。

アデルさんのTeams承認アプリ上では、ステータスが「要求しました」のままメーガンさんに対して承認依頼した状態になりました。

メーガンさんのところには、アデルさんが承認を再割当てした記録とともに承認要求が届きました。コメントをつけて承認しておきます。

このとき返ってきたJSONのBodyはこんな感じでした。responsesは配列担っていますが、中身の要素は1つだけ。再割当てをしたアデルさんの記録は残らないようです。

responder{
  "responses": [
    {
      "responder": {
        "id": "ed7204ee-19c4-4383-9f64-602824abb8ed",
        "displayName": "Megan Bowen",
        "email": "MeganB@0phny.onmicrosoft.com",
        "tenantId": "f91ab2b5-8d05-4237-91ab-1939d17d05cc",
        "userPrincipalName": "MeganB@0phny.onmicrosoft.com"
      },
      "requestDate": "2025-04-27T02:51:15Z",
      "responseDate": "2025-04-27T02:58:57Z",
      "approverResponse": "ゲストを承認する",
      "comments": "アデルさんが私に承認をまわしたのね? わかった。承認するわ。"
    }
  ],
  "responseSummary": "承認者: Megan Bowen (MeganB@0phny.onmicrosoft.com)\r\n応答: ゲストを承認する\r\n依頼日: 2025年4月27日 2:51:15\r\n応答日: 2025年4月27日 2:58:57",
  "completionDate": "2025-04-27T02:58:57Z",
  "outcome": "ゲストを承認する",
  "name": "d4ee1e91-73ec-4385-8f47-af272d55b3f5",
  "title": "【ゲスト招待承認の依頼】mocabrown daddyさんから承認の依頼がとどきました。",
  "details": "mocabrown daddy<daddy@0phny.onmicrosoft.com>さんより、ゲスト招待の申請がありました。下記の内容を確認の上、承認をお願いいたします。\n\nゲストEmail:daddy@mocabrown.com\nゲスト氏名:DD in ランゲルハンス島\nゲスト所属:株式会社モカ式\n招待期間:180\n招待理由;\n誰かが承認してくれるかと思って\n",
  "requestDate": "2025-04-27T02:48:53Z",
  "expirationDate": "9999-12-31T23:59:59Z",
  "priority": "Medium"
}

却下された場合の通知を申請者に送る処理

ここまでで承認の動作を確認できたので、ゲスト招待を承認されなかった場合の申請者への通知をメールで行う処理を追加してみます。素直に作ってみると、メール送信アクションの中に、承認者の動的なコンテンツを追加した瞬間にApply to eachが自動的に作られてしまいます。これは、先程確認したように承認者の情報が配列の要素として記録されているからです。

今回の作りだと、配列の中身はつねに1つしかありませんので、ループする必要はありません。添字をつけて配列の0番目だけを使えばオッケーです。先程メールの送信の中に貼り付けた動的なコンテンツの部分をコピーしてテキストエディタに貼り付けると以下のようになります。

@{items('Apply_to_each')?['responder/email']}

Aplly to eachの入力部分も同じようにテキストエディタに貼り付けてみると以下のようになってます。

@{outputs('開始して承認を待機')?['body/responses']}

先程取得したJSONを見返すと、responsesの要素0番目のresponderのemailが承認者のメールアドレスで、displayNameが氏名ですので、以下のように式を組み立てると良いですね。

# 承認者のメールアドレス
outputs('開始して承認を待機')?['body']?['responses'][0]?['responder']?['email']
# 承認者の氏名
outputs('開始して承認を待機')?['body']?['responses'][0]?['responder']?['displayName']
# 承認者のコメント
outputs('開始して承認を待機')?['body']?['responses'][0]?['comments']

これをメール送信の中に式として埋め込みます。

承認が一定期間行われなかった場合の処理を作る

承認要求が行われたけれど、一定期間承認してもらえなかった場合にも、そのままだとクラウドフローがずっと待機状態になってしまうので対応しておかなくてはいけません。

何日経過したらタイムアウトとするのかは、「開始して承認を待機」の設定画面から指定します。アクションの右角にある三点リーダーから「設定」をクリックします。

タイムアウトの項目があるので、例えば14日間を指定する場合は「P14D」のように入力します。

期間を指定する場合の文法は、ISO 8601 形式という方法で行います。詳しいところはCopilotくんに聞いてみましょう。

このとおり、期間が1分間なら PT1M、1時間なら PT1H、1日間なら P1D、1週間なら P1W、一ヶ月間なら P1M、一年間なら P1Y のように表記するようです。

ちなみに、28日を超えて応答がない場合、フローは失敗しますが、承認自体はアクション センターに残ります。また、フローの実行自体にも30日の制限があり、承認フローのような長期間のフローではタイムアウトになることがあるようです。

テストするのに14日間も待っていられないので、1分間でタイムアウトさせるように「PT1M」を指定してみます。テスト実行して承認しないまま放置すると・・・。スコープには"An action failed. No dependent action succeeded." 。「開始して承認を待機」アクションには"ActionTimeOut"が表示されてます。このエラーを拾いに行きましょう。

「開始して承認を待機」のあとに、並列分岐を設定して、タイムアウトした場合にのみ動作するよう「メール送信」アクションを追加します。タイムアウトの場合のみ実行させるには、三点リーダーから「実行条件の構成」をクリックし、「☑がタイムアウトしました」にチェックを入れます。

メールの中身はこんな感じでしょうか。メールを送信したあとには次のアクションに進まないように「終了」も加えておきます。

ふたたび1分間待ちました。

承認の時間切れでメール送信に処理が流れました。

いい感じです!

SPOリストにステータスを書き込む

メールを送ると同時に、SPOリストにも却下と期限切れのステータスを書き込んでおかなくてはいけません。

この処理は(その2)で作成したものをコピーしてきて、ステータスの値だけを書き換えてやるだけなので簡単ですね。

おさらい

今回は承認された場合と、却下された場合、および他のユーザーに承認者を任せた場合に、「開始して承認を待機」アクションがどのような値を返すのかを確認しました。

承認者の名前などは配列の中にあるため、0番目という添字をつかってループしなくても値が取れるようにしました。

承認要求がタイムアウトになる期間を日付や時間などで指定できることを確認し、タイムアウトした場合の処理をどのように分けるのかを実践してみました。

次回(その4)では、いよいよEntra IDへのゲスト登録を行っていく予定です。

どんな人が作っている?

お仕事でPower BIやPower Automateクラウドフローを中心に承認要求アクションを加えました。ちょっとした自動化などを行っています。

QiitaやこのブログではPower Automateの話題を中心に投稿を行っていますので、ぜひ「いいね」してくださると励みになります。