LoginSignup
5
0

More than 1 year has passed since last update.

VPNに繋いだままZoom接続した人にSlackを飛ばそう

Last updated at Posted at 2021-12-03

社内VPNに接続したままZoomを行う人が多いと帯域が圧迫して辛いですね。
そんなわけで、VPNに接続した状態でZoomに接続している人に、Slackで通知を飛ばすような仕組みを作りましょう。

なお、コードサンプルではLaravelを用いて実装しています。

前提

  • VPNで固定なGlobalIPとなる
  • SlackとZoomの登録メールアドレスが一致している
  • ZoomがBusinessPlan以上であること

つくりかた

VPNのアクセスユーザーとZoomの接続ユーザーを突き合わせる形でもできますが、今回はZoomのAPIを利用してGIPと接続種別を見る形とします。

  1. Zoomの Participant/Host joined meeting を利用してWebHook通知を受ける
  2. Zoomの Get Meeting Detail API を利用してMeetingの参加者リストを取得する
  3. 参加者リストから、参加したユーザーのネットワーク情報を取得する
  4. SlackAPIの users.lookupByEmailを利用し、ユーザーのSlackUserIDを取得する
  5. 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);
}

pipi.png

できました。

皆様もZoom接続やYouTube視聴をする際はVPNを外すようにしましょう。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0