8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GCP で Google Calendar を CalDAV サーバに複製する

Last updated at Posted at 2019-09-23

概要

Python バッチスクリプトで Google Calendar からスケジュール情報を採取し、CalDAV サーバへ複製する例を紹介します。

  • GSuite 上の任意のユーザの Calendar に、Google Calendar API を介してアクセスする
  • GCP の Cloud Functions にデプロイした Pythonバッチスクリプトを、Cloud Scheduler + Pub/Sub で定時実行する
  • APIアクセス認証をGCPのサービスアカウントキーで行い、個々のカレンダーオーナーからのアクセス許可は不要とする

サンプルコード

構成

グレーは環境設定、ブルーはバッチ処理です。

image.png

1. GSuiteでAPIアクセスを許可する

アクセス対象としたいカレンダーが存在する GSuite 環境に対して、外部からのAPIアクセスを受付可能に設定をします。公式ドキュメントの、管理コンソールで API アクセスを有効にする 手順になります。

APIリファレンスを有効にする

image.png

APIアクセスを有効にする

image.png

2. GCPにサービスアカウントを作成しキーを得る

今回は サービスアカウントキー を用いた認証ストラテジで Calendar API を利用します。なお、サービスアカウントではなくパーソナルなアカウントの認証ストラテジでAPIを利用する方式もありますが、当記事では対象外です。認証ストラテジの選択肢と差の解説は、こちらの公式ドキュメントが分かりよいと思います。

IAMと管理 > サービスアカウント でサービスアカウントを作成します。
image.png

サービスアカウントの鍵を生成し、JSON形式で取得します。鍵は、バッチスクリプトがAPIアクセス認証時に使います。

image.png
image.png

サービスアカウントのクライアントIDを確認します。クライアントIDは、バッチスクリプトの認証情報および、GSuiteのAPIクライアントアクセス許可対象として使います。

image.png

3. GSuiteでAPIクライアントアクセスを許可する

GSuite で、どのリソースに対するAPIアクセス操作を、誰に許可するかを設定します。設定手順は、OAuth: API クライアント アクセスの管理 になります。

設定内容は、クライアント名 には先にGCP上で作成したサービスアカウントの クライアントID を指定し、
スコープ には https://www.googleapis.com/auth/calendar.readonly, https://www.googleapis.com/auth/calendar.events.readonly を指定して承認します。

image.png

余談ですが、指定可能なスコープとAPIの仕様は APIリファレンス に書かれています。

4. CalDAV サーバを立てる

当サンプルでは、CalDAV サーバである Radicale に、Google Calendar から採取した情報を吐き出して、ユーザに利用させます。試験版のRadicaleは dockerコンテナ で立てるのが手っ取り早いです。

起動するとこんな感じです。サーバのURLがアプリに与える環境変数の CALDAV_SERVER_URL、 ログイン情報が CALDAV_SERVER_USER, CALDAV_SERVER_PASS です。

image.png

ログインすると、即カレンダーの作成画面になりますので、こんな感じで作ります。Titleがカレンダー名であり、アプリに与える環境変数の CALDAV_SERVER_CALENDAR_NAME です。

image.png

作成したカレンダーのURLは、http://${HOSTNAME}:5232/${USERNAME}/${CALENDAR_ID}/ になり、環境変数 CALDAV_SERVER_URL に相当します。

image.png

  • 余談
    • CalDAV サーバは、例えばThunderbirdのカレンダー拡張(Lightning)のようなクライアントから参照・同期できる、ネットワークカレンダーサーバの規格です。RFC 4791で仕様が定義されており、いわゆるiCAL形式(RFC 2445) でデータ交換をします。
    • そもそもカレンダーというモノは、割と面倒くさい概念(タイムゾーン、Free/Busy、参加者と参加不参加、繰り返しタスクなど)がありますので、車輪があるなら再発明しないで利用するのがお得です。

5. GCP上にバッチ処理を設置する

Pub/Subの作成

トピックを作成し、トピックの名前を確認しておきます。

image.png
image.png

作成したトピックに対する、Pullタイプのサブスクリプションを作成します。サブスクライバとなるCloudFunction宛のメッセージングを定義する事に相当します。

image.png
image.png

Cloud Scheduleの登録

先ほど作成したPub/Subトピックをターゲットとするスケジュールを作成します。スケジュールが、Pub/Subに対するパブリッシャとなる事に相当します。

image.png

作成したら、試しにジョブを実行して Publish メッセージングが成功する事を確認しておきます。

image.png

Pythonスクリプトのデプロイ準備をする

Cloud Storageに、非公開バケット function-codes を1つ作ります。

image.png

次に、スクリプトcredentials.json を、先の手順で取得したサービスアカウントのJSON形式の鍵に差し替えて、Pipfile, Pipfile.lock, main.pyおよび、差し替え後の credential.json を1つのZipファイル gcalendar-fetcher.zip に圧縮し、先に作成したCloud Storageのバケットにアップロードします。

image.png

PythonスクリプトをFunctionsにデプロイする

バケット内のZipファイル gcalendar-fetcher.zip をソースとする関数を定義します。トリガーには、Pub/Sub に作成したトピック test-getting-gcal-events トピックを指定します。実行する関数には main関数 を指定します。

image.png

また、環境変数は こちらに定義した変数 を与えます。

image.png

6. 実行して結果を確認してみる

Cloud Scheduler に作成したタスクが実行済の場合は結果欄に「成功」が出ていると思います。まだスケジュールが走っていない場合は、実行ボタンを押下し発火させた結果を同様に確認します。

image.png

また、Function にデプロイしたスクリプトが、Pub/Sub メッセージングを介して実行されていることも確認します。

image.png

いずれも成功なら、CalDAVサーバに登録されたはずのカレンダー情報を閲覧してみます。radicale から ical をダウンロードして中身を確認してみましょう。icalフォーマットのデータが得られます。

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//PYVOBJECT//NONSGML Version 1//EN
X-WR-CALDESC;VALUE=TEXT:test
X-WR-CALNAME;VALUE=TEXT:test
BEGIN:VEVENT
UID:xxxxxxxxxxxxxxxxxxx@google.com
DTSTART:20190913T013000Z
DTEND:20190913T084500Z
DTSTAMP:20190726T050838Z
LAST-MODIFIED:20190726T050856Z
STATUS:CONFIRMED
SUMMARY:展示会にいく
TRANSP:OPAQUE
URL:https://www.google.com/calendar/event?eid=XXXXXXXXXXXXXXXXXXXXXXXX
END:VEVENT
BEGIN:VEVENT
UID:yyyyyyyyyyyyyyyyyyyyyyyyyy@google.com
DTSTART:20191004T040000Z
...
END:VEVENT
END:VCALENDAR

ThunderbirdのLightning拡張でネットワークカレンダーとして見る方法もあります。
image.png
環境変数 CALDAV_SERVER_URL に与えたURLが、ネットワークカレンダーの場所に相当します。
image.png
image.png

よく採れてます、使えそうですね。
空き時間調整くんとか、あなた会議長杉くんとかを作ってみるつもりです。

追記

生のクレデンシャルファイルをデプロイソースに含めて保管しておくのが怖いので、クレデンシャルを暗号化して取り扱うコード修正を加えてみました。Before/After形式の続き記事の体裁で書いたのでどうぞ。

8
5
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
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?