【BigQuery】ドライブ監査ログをエクスポートしてみた(前編)
はじめに
Googleドライブの監査ログをBigQueryに出力する機会があったので
その過程で調査した内容の備忘録になります。
ちなみにGoogleドライブの監査ログを利用するには、以下の3つの方法があります。
1. Google管理コンソールのレポート機能[1]
2. Reports API経由でのログ取得[2]
3. BigQueryへのExport機能[3]
上記の1と2はBusinessエディションで利用できますが
3はEnterpriseエディションである必要があります。
そのため、なかなか手の出せない企業が多いように思います。
本投稿はBigQueryへのExport機能で実施するとどんな感じになるのかを
まとめてみました。
今回のやりたきこと
まず、やりたかったことは以下の3点になります。
- BigQuery Export機能の設定
- ドライブ監査ログのスキーマ定義情報の確認
- VPC Service Controlsを有効化した場合の設定
今回の前編では上記1と2を紹介し、後編で3について紹介します。
2については、Reports APIで取得した場合との差分を確認しました。
対象イベントは、監査業務でよく利用する下記4つのイベントとしています。
# | イベント名 | 説明 |
---|---|---|
1 | view | ドライブ内のファイルの参照操作 |
2 | download | ドライブ内のファイルのダウンロード操作 |
3 | ドライブ内のファイルの印刷操作 | |
4 | upload | ドライブへのファイルのアップロード操作 |
実行環境
Product | version |
---|---|
Google Workspace | Enterprise Edition |
BigQuery | 2021年12月1日時点 |
【構成図】
【補足】
・ Google WorkspceとBigQueryは同じ組織に所属しています。
・ BigQuery Export機能を有効化するとactivityとusageの2つのテーブルが作成されます。
実施手順
- Google Cloudのプロジェクト作成
- BigQuery Exportの有効化
- BigQueryのスキーマ確認
- BigQueryのテーブル参照
【補足】
・ 本手順は、Google Workspaceの特権管理者ロールで作業しています。
・ Google Cloudのプロジェクト課金が有効化されていることを前提としています。
1. Google Cloudのプロジェクト作成
- Google Cloudのコンソールにログインします。
- [IAMと管理] > [プロジェクトを作成]に移動します。
- Google Workspaceの組織が指定されている状態で新しいプロジェクトを作成します。
- [ビッグデータ] > [BigQuery]を開き、作成したプロジェクトができていることを確認します。
- プロジェクトがあればOKです。
2. BigQuery Exportの有効化
- 次は、Google Workspaceの管理コンソールにログインします。
- Enterpriseエディションの場合、[レポート] > [BigQuery Export]があります。
- ❶にチェックを入れます。
- ❷にプロジェクトID、❸には新たに作成するデータセット名を入力して、[保存]します。
- 新たにデータセット (今回はtest_dataset01) ができていれば完了です。
【補足】
・ Google Workspaceと同一組織内のBigQueryにしか指定できません。
・ 出力先のBigQuery データセットは1つしか指定できません。
・ 出力先のロケーションは米国(デフォルト) もしくは 欧州連合しか指定できません。
3. BigQueryのスキーマ確認
- 監査ログが出力されるには1日〜数日かかる場合があります。(規則性まで把握できていません)
- ログが出力されると2つのテーブルが作成されます。(監査ログはactivityに出力されます)
-
この時点で以下の2点が想定外でした。
・ 時刻フィールド (time_usec
)がTIMESTAMP型ではなくINTEGER型だった。
・ 送信元IPアドレスフィールド (ip_address
)がSTRING型ではなくBYTES型だった。 -
サービス固有のフィールドはサービスごとに親フィールド(RECORD型)が作成されます。
- ドライブ監査ログ (
drive
フィールド配下) のスキーマ定義は以下となっていました。
# | フィールド名 | 種類 | モード |
---|---|---|---|
01 | doc_id | STRING | NULLABLE |
02 | target_user | STRING | NULLABLE |
03 | old_value | STRING | NULLABLE |
04 | new_value | STRING | NULLABLE |
05 | doc_type | STRING | NULLABLE |
06 | doc_title | STRING | NULLABLE |
07 | primary_event | BOOLEAN | NULLABLE |
08 | target_domain | STRING | NULLABLE |
09 | source_folder_title | STRING | NULLABLE |
10 | source_folder_id | STRING | NULLABLE |
11 | destination_folder_title | STRING | NULLABLE |
12 | destination_folder_id | STRING | NULLABLE |
13 | owner | STRING | NULLABLE |
14 | dlp_info | STRING | NULLABLE |
15 | owner_is_team_drive | BOOLEAN | NULLABLE |
16 | owner_is_shared_drive | BOOLEAN | NULLABLE |
17 | old_visibility | STRING | NULLABLE |
18 | visibility | STRING | NULLABLE |
19 | visibility_change | STRING | NULLABLE |
20 | removed_role | STRING | NULLABLE |
21 | added_role | STRING | NULLABLE |
22 | membership_change_type | STRING | NULLABLE |
23 | target | STRING | NULLABLE |
24 | team_drive_id | STRING | NULLABLE |
25 | shared_drive_id | STRING | NULLABLE |
26 | originating_app_id | STRING | NULLABLE |
27 | team_drive_settings_change_type | STRING | NULLABLE |
28 | shared_drive_settings_change_type | STRING | NULLABLE |
29 | old_settings_state | STRING | NULLABLE |
30 | new_settings_state | STRING | NULLABLE |
31 | usage_billing_entity_id | INTEGER | NULLABLE |
32 | usage_billing_metric_container.usage_billing_metric_id | STRING | NULLABLE |
33 | usage_billing_metric_container.integer_application_metric | INTEGER | NULLABLE |
34 | billable | BOOLEAN | NULLABLE |
35 | sheets_import_range_recipient_doc | STRING | NULLABLE |
36 | category_name | STRING | NULLABLE |
37 | attribute_id | STRING | NULLABLE |
38 | old_attribute_value | STRING | NULLABLE |
39 | new_attribute_value | STRING | NULLABLE |
40 | old_publish_visibility | STRING | NULLABLE |
41 | new_publish_visibility | STRING | NULLABLE |
42 | actor_is_collaborator_account | BOOLEAN | NULLABLE |
43 | label | STRING | NULLABLE |
44 | field_id | STRING | NULLABLE |
45 | old_field_value | STRING | NULLABLE |
46 | new_field_value | STRING | NULLABLE |
47 | is_encrypted | BOOLEAN | NULLABLE |
48 | storage_entity_id | INTEGER | NULLABLE |
49 | storage_usage_in_bytes | INTEGER | NULLABLE |
50 | label_title | STRING | NULLABLE |
51 | reason | STRING | NULLABLE |
52 | field | STRING | NULLABLE |
53 | old_value_id | STRING | NULLABLE |
54 | new_value_id | STRING | NULLABLE |
- テーブルのパーティショニングは取り込み日で実施されています。
項目 | 値 |
---|---|
テーブルタイプ | 分割 |
分割基準 | DAY |
フィールドで分割 | _PARTITIONTIME |
パーティションの有効期限 | 60日 |
パーティションフィルタ | 省略可 |
- デフォルトでは60日でデータが消えてしまいます。
- 期限を変えたい場合は以下コマンドで設定変更してください。
bq update --time_partitioning_expiration 7776000 composed-arbor-332218:test_dataset01.activity
4. BigQueryのテーブル参照
- 先にも記載したよく利用する4つのイベントに絞ってテーブルを参照してみます。
SELECT
TIMESTAMP_MICROS(time_usec) AS timestamp,
email,
org_unit_name_path,
ip_address,
event_type,
event_name,
record_type,
drive.doc_id,
drive.doc_type,
drive.doc_title,
drive.primary_event,
drive.owner,
drive.owner_is_team_drive,
drive.owner_is_shared_drive
FROM
`composed-arbor-332218.test_dataset01.activity`
WHERE
record_type = "drive"
AND event_name IN ("view", "download", "print", "upload")
ORDER BY
1
- 以下、SQL実行結果になります。
行 | timestamp | org_unit_name_path | ip_address | event_type | event_name | record_type | drive.doc_id | drive.doc_type | drive.doc_title | drive.primary_event | drive.owner | drive.owner_is_team_drive | drive.owner_is_shared_drive | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2021-11-29 05:24:54.254 UTC | hibino@test.com | test.com | MTc1LjE3Ny40NC4yMcj= | access | view | drive | 14VOBRruaEcKl6NBACdejdZXeI42AhlwWTmohtUl3g1M | document | test_file01 | true | hibino@test.com | false | false |
2 | 2021-11-29 05:25:00.442 UTC | hibino@test.com | test.com | MTc1LjE3Ny40NC4yMcj= | access | download | drive | 14VOBRruaEcKl6NBACdejdZXeI42AhlwWTmohtUl3g1M | document | test_file01 | true | hibino@test.com | false | false |
3 | 2021-11-29 05:25:57.421 UTC | hibino@test.com | test.com | MTc1LjE3Ny40NC4yMcj= | access | drive | 14VOBRruaEcKl6NBACdejdZXeI42AhlwWTmohtUl3g1M | document | test_file01 | true | hibino@test.com | false | false | |
4 | 2021-11-29 05:26:04.430 UTC | hibino@test.com | test.com | MTc1LjE3Ny40NC4yMcj= | access | upload | drive | 14VOBRruaEcKl6NBACdejdZXeI42AhlwWTmohtUl3g1M | document | test_file01 | true | hibino@test.com | false | false |
【補足】
・ 値が含まれないフィールドはSELECT句で除外しています。
・ 時刻はUNIXTIME(マイクロ秒)からISO8601に変換した上で表示しています。
まとめ
さて、いかがでしたでしょうか?
全イベントで差分比較した訳ではないので、詳細を見ていくと違いがあるかもしれませんが
基本的にはReports APIで取得していた監査ログは確認できるのではないでしょうか?
ip_address
フィールドを文字列で表示するため
NET.IP_TO_STRING[4]で変換しようと思ったんですが、以下のエラーとなりました。
14バイトになっている原因までは追えなかったので、こちらは追加検証にしようと思います。
後編では、VPC Service Controlsで制御した状態で
BigQueryにExportできるようにするための設定について紹介します^^
Discussion
既に解決済みかもしれませんが、情報共有兼ねてコメントいたします。
同じエラーに遭遇し、色々調べてみましたが、以下のように
SAFE_CAST
でStringにキャストしてあげることで、自分の環境では元のIPアドレスの取得に成功しました。