社内VPNに接続したままZoomを行う人が多いと帯域が圧迫して辛いですね。
そんなわけで、VPNに接続した状態でZoomに接続している人に、Slackで通知を飛ばすような仕組みを作りましょう。
なお、コードサンプルではLaravelを用いて実装しています。
前提
- VPNで固定なGlobalIPとなる
- SlackとZoomの登録メールアドレスが一致している
- ZoomがBusinessPlan以上であること
つくりかた
VPNのアクセスユーザーとZoomの接続ユーザーを突き合わせる形でもできますが、今回はZoomのAPIを利用してGIPと接続種別を見る形とします。
- Zoomの Participant/Host joined meeting を利用してWebHook通知を受ける
- Zoomの Get Meeting Detail API を利用してMeetingの参加者リストを取得する
- 参加者リストから、参加したユーザーのネットワーク情報を取得する
- SlackAPIの users.lookupByEmailを利用し、ユーザーのSlackUserIDを取得する
- SlackAPIの chat.postMessageを利用し、ユーザーにメッセージを送信する
つくる
SlackのApp及びZoomのAppは、予め作成し、APIDocsを参照の上、適切な権限を付与しておいてください。
1. ZoomのWebHook通知を受ける
Participant/Host joined meeting を利用すると、Zoomに人が参加してきたときに、WebHookで通知を受けることができます。
これを利用して、ユーザーのアカウント情報を取得します。
これ自体は単純なEventWebhookなので、適当にPOSTで受け取れるURLを準備しましょう。
今回使用するのは meeting.participant_joined
のEventなので、適当にデータを抜き出します。
if($request->event == 'meeting.participant_joined'){
$payload = $request->payload;
$meeting_id = $payload['object']['id'];
$joined_user_id = $payload['object']['participant']['participant_user_id'];
}
2. Zoomミーティングの参加者リストを取得する
Zoomの管理者ダッシュボード、あるいはGet Meeting Participants APIを利用すると、ミーティングに参加しているすべてのユーザーのGIPとネットワーク接続種別を取得することができます。
EventWebHookで取得するデータにはこれらの情報が存在しないので、二度手間になるのですが、先程取得したMeetingIDを利用して、ミーティングの参加者リストを取得しましょう。
$headers = [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . config('zoom.token'),
];
$params = [
'page_size' => 300,
];
$response = Http::withHeaders($headers)
->get("https://api.zoom.us/v2//metrics/meetings/$meeting_id/participants", $params);
$participants = json_decode($response->body(), 1);
3. ターゲットユーザーのネットワーク情報を取得する
2.で取得したミーティングリストから、今回のターゲットのユーザーIDを検索します。
今回はLaravelを使用しているので、データをcollectionに入れて検索をします。
$users = collect($participants['participants']);
$check = $users->where('id', '=', $joined_user_id)
->where('ip_address', '=', '127.0.0.1') // 対象となるGIPを入れる
->where('network_type', '=', 'PPP') // IPSecの場合はPPP, SSL-VPNの場合は...確認していない
->where('status', '=', 'in_meeting')
->first();
4. ターゲットのSlackのUserIdを取得する
3.でミーティングにjoinしてきたユーザーが存在する場合、メールアドレスからSlackのUserIdを取得します。
このとき、ZoomのEmailが取得できない、Slackに該当するユーザーが居ない場合に向けたエラーハンドリングを準備することを推奨します。
5. ターゲットにSlackでメッセージを送信する
4.で取得したUserIDに対して適当なメッセージを送信します。
if(!is_null($check)){
// SlackのUserIDを取得
$email = $payload['object']['participant']['email'];
$headers = [
'Authorization' => 'Bearer ' . config('slack.token'),
'Content-Type' => 'application/x-www-form-urlencoded',
];
$response = Http::withHeaders($headers)
->asForm()
->get('https://slack.com/api/users.lookupByEmail', ['email' => $email]);
$slack_user_data = json_decode($response->body(), 1);
// メッセージを送信
$params = [
'channel' => $slack_user_data['id'],
'text' => "VPNに接続した状態でZoomを行っている可能性があります。\nVPN負荷軽減のため、可能な場合VPNから切断を行ってください。",
];
$response = Http::withHeaders($headers)
->asForm()
->post('https://slack.com/api/chat.postMessage', $params);
$response = json_decode($response->body(), 1);
}
できました。
皆様もZoom接続やYouTube視聴をする際はVPNを外すようにしましょう。