AUTOMATION NOTE — 184

GWS SOC2 監査証跡を自動生成する設計方針

Google Workspace(GWS)の Admin SDK Reports API を使うと、ユーザー管理に関する監査イベントをプログラムから定期的に取得できます。この記事では、SOC2 Type II の CC コントロール項目と GWS 監査ログの対応関係を整理し、外部監査人に提出できる Google Workspace SOC2 監査レポートを自動生成するためのポリシー設計を解説します。

この記事を読んだほうが良い人

  • SOC2 Type II の取得に向けて動き始めており、外部監査人から「アカウント管理の証跡を出してほしい」と言われた情シス担当者
  • GWS を標準環境として使っており、どのログが監査証跡として使えるか整理できていない方
  • 管理コンソールからの手動 CSV エクスポートを毎月繰り返しており、自動化を検討している方

SOC2 Type II のアカウント管理証跡として何が求められるか

SOC2(Service Organization Control 2)は、米国公認会計士協会(AICPA)が定めたセキュリティ報告フレームワークです。Type I と Type II の違いは「証明する対象」にあります。

  • Type I:ある特定時点において、コントロールが適切に設計されていることを証明する
  • Type II:通常 6〜12 か月の審査期間を通じて、コントロールが継続的に機能していたことを証明する

Type I は「設計の妥当性」、Type II は「運用の継続性」を審査対象にします。Type II では、コントロールが紙の上に存在するだけでなく、審査期間の全期間にわたって実際に機能していたかどうかが問われます。

Type II 審査で監査人が実際に確認する作業は、具体的には次のようなものです。審査期間中に新規アカウントが作成されているとき、「それぞれの作成に対応する承認申請書が存在するか」を突き合わせます。退職者については、「退職日と実際のアカウント停止日の差が SLA(例: 5 営業日以内)に収まっているか」を確認します。管理者権限の付与については、「スーパー管理者ロールが正当な申請なしに付与されていないか」を確認します。この「何が起きたか」を記録した左辺として機能するのが GWS 監査ログです。

アカウント管理に関連する主な SOC2 コントロールは CC6(論理的アクセスコントロール)系に集中しています。監査人から頻繁に求められる項目は次の 3 つです。

  • CC6.1:論理的アクセスコントロールの実施(誰がシステムにアクセスできるかを管理しているか)
  • CC6.2:新規ユーザーの登録とアクセス付与のプロセス(申請・承認フローが存在するか)
  • CC6.3:アクセスの変更・削除プロセス(退職者や異動者のアカウント停止・削除が速やかに行われているか)

これらに加えて CC8.1(変更管理)と CC9.2(ベンダー管理)が求められるケースもあります。外部 SaaS との OAuth 連携を多数持つ組織では、サードパーティアプリへのアクセストークン管理が CC9.2 の証跡対象になることがあります。

GWS 監査ログと SOC2 CC コントロールはどう対応するか

Reports API で取得できるアプリケーション別のログと SOC2 CC コントロールの対応関係を整理します。以下のイベント例は代表的なものです。正確なイベント名・パラメータ名は Admin SDK の公式リファレンスで確認してください。

SOC2 コントロール GWS ログの種別(applicationName) 主なイベント例
CC6.1(アクセス管理の実施) admin ユーザー作成・ロール付与・グループ追加
CC6.2(新規ユーザー登録プロセス) admin ユーザー作成・組織ユニット(OU)変更
CC6.3(アクセス削除・変更) admin ユーザー停止・削除・ロール剥奪
CC6.3(OAuth トークン管理) token トークン発行・失効
CC8.1(変更管理) admin 管理コンソールのセキュリティ設定変更
CC9.2(ベンダー管理) token サードパーティアプリへのアクセス許可・取り消し

admin ログが最も重要な単一ソースです。ユーザーの作成から停止・削除まで、アカウントライフサイクル全体が admin applicationName に集約されています。代表的なイベント名として、ユーザー作成は CREATE_USER、ユーザー停止は SUSPEND_USER、管理者ロール付与は ASSIGN_ROLE のような形式で記録されます(正確な文字列は公式リファレンスで確認)。

token ログは、サードパーティアプリへの OAuth 接続証跡が必要なときに補助的に使います。承認なしでインストールされた外部アプリの検知にも役立ちます。

login ログはユーザーのサインイン成功・失敗履歴を記録します。CC6.1 の「不正なアクセスが無いか」という観点で補完的に活用できます。ただし SOC2 で主軸となるのはあくまで admin ログです。

なお、Google Vault(GWS のメール・Chat・ドライブコンテンツを保全・エクスポートする機能)は、メール本文や会話の証跡を提出する場合に有効です。アカウント操作の証跡(誰がいつアカウントを作成・停止したか)については、Reports API のログが一次ソースになります。Vault とは用途が異なる点に注意してください。

取れるログと取れないログの境界線(GWS 監査ログ コンプライアンス証跡の射程)

GWS 監査ログで証跡として出せるものと出せないものを把握しておくことが、監査人との事前合意に欠かせません。監査開始後に「このデータは取れない」と判明すると対応が難しくなるため、設計段階で整理しておきます。

取れるもの(証跡として使用可)

  • ユーザーアカウントの作成・停止・削除イベント(日時・実行した管理者のメールアドレス付き)
  • 管理者ロールの付与・剥奪イベント(スーパー管理者・カスタムロール含む)
  • Google グループへのメンバー追加・削除イベント
  • 管理コンソールでの組織設定変更(OU 作成・移動、セキュリティポリシー変更など)
  • OAuth トークンの発行・失効(サードパーティアプリ連携の証跡)

取れないもの(設計時に注意が必要)

  • アカウント作成の「承認者」情報。GWS 単体では申請承認フローを持たないため、Jira・Asana・Google Forms 等の申請システムのログと突き合わせる設計が別途必要
  • MFA(多要素認証)の個別ユーザーの登録・変更履歴。管理者が MFA を強制しているかどうかはポリシーとして確認できるが、個別ユーザーの認証方法変更ログは標準の Reports API では直接取れない。なお Directory API ではユーザーごとの MFA 登録状態(2SV 登録済みかどうか)を参照できるため、定期的なスナップショットを別途取得する補完設計が有効
  • Reports API のログ保持期間を超えた履歴(正確な保持期間は公式ヘルプを参照。月次でデータを外部に書き出し、長期保持する設計が前提になる)
  • 物理的アクセスログ(データセンターへの入退室等)。SOC2 の物理コントロール項目は Google 自身の SOC レポートで補完する

承認者情報が取れない問題の現実的な対処

特に「承認者情報が取れない」点は頻繁に問題になります。監査人から「このアカウント作成は誰が承認したのか」と聞かれたとき、GWS のログには実行した管理者のメールアドレスしか残りません。対処方法は 2 つあります。

1 つ目は、申請フロー(Google Forms + Sheets / Jira / ServiceNow 等)の申請チケット番号を GWS ログの横列に手動または自動で紐付ける方法です。「2025-04-01 に作成された user@example.com は申請番号 REQ-1234 に対応する」という形で対応表を維持します。

2 つ目は、申請時にアカウント作成を GAS で自動化し、申請フォームの承認日時・承認者をスクリプト内でログに書き出す方法です。この場合、GAS が実行した管理者として作成イベントが記録されるため、申請記録と突き合わせやすくなります。

もう一つ見落としがちなのがログの保持期間です。SOC2 Type II の審査期間は通常 6〜12 か月に及びますが、Reports API が参照できるログ範囲には上限があります。月次で自動収集してスプレッドシートに書き出す設計は、審査開始より前から動かしておくことが重要です。審査が始まってからログ収集を始めても、過去分は取り戻せません。

GAS で SOC2 監査ログを月次自動集計する方法

月次で証跡レポートを自動生成するために、GAS(Google Apps Script)と Admin SDK Reports API を組み合わせます。設計上の重要な判断は「コードをどう書くか」より先に「どのイベントを・何の目的で・どのサイクルで取り出すかを定義すること」にあります。

以下は GAS から Reports API の admin ログを取得し、スプレッドシートに書き出す概念サンプルコードです。GAS プロジェクトの設定で Advanced Services の「Admin SDK Reports API」を有効化してから使用してください。

/**
 * 月次 Admin 監査ログ収集スクリプト(SOC2 CC6.1 / CC6.2 / CC6.3 対応)
 * 高度なサービス「Admin SDK Reports API」を有効化してから利用すること
 */
function collectMonthlyAdminLog() {
  var SHEET_NAME = 'SOC2_CC6_' + Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMM');
  var ss    = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName(SHEET_NAME) || ss.insertSheet(SHEET_NAME);

  // 対象期間: 前月の 1 日〜末日
  var now       = new Date();
  var startTime = new Date(now.getFullYear(), now.getMonth() - 1, 1); // 前月 1 日
  var endTime   = new Date(now.getFullYear(), now.getMonth(), 1);     // 当月 1 日 0:00 = 前月全体を包含

  var pageToken;
  var rows = [];

  do {
    var options = {
      startTime:  startTime.toISOString(),
      endTime:    endTime.toISOString(),
      maxResults: 1000
    };
    if (pageToken) options.pageToken = pageToken;

    var response = AdminReports.Activities.list('all', 'admin', options);
    (response.items || []).forEach(function(item) {
      // タイムスタンプを UTC→JST に変換して出力
      var jst = Utilities.formatDate(new Date(item.id.time), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss');

      (item.events || []).forEach(function(ev) {
        rows.push([
          jst,                             // タイムスタンプ (JST)
          item.actor.email || '',          // 操作した管理者のメールアドレス
          ev.name || '',                   // イベント名(CREATE_USER 等)
          JSON.stringify(ev.parameters || []) // パラメータ詳細 (JSON)
        ]);
      });
    });
    pageToken = response.nextPageToken;
  } while (pageToken);

  // ヘッダー + データを書き込み
  if (sheet.getLastRow() === 0) {
    sheet.appendRow(['タイムスタンプ(JST)', '実行者(管理者)', 'イベント名', 'パラメータ(JSON)']);
  }
  rows.forEach(function(row) { sheet.appendRow(row); });
  Logger.log('収集件数: ' + rows.length + ' 件');
}

このサンプルでのポイントは 4 点です。

  • 'all' をユーザーキーに指定することで、全管理者の操作ログが対象になる
  • applicationName'admin' を指定することで、管理コンソール操作のログだけに絞り込める
  • タイムスタンプは Utilities.formatDate を使って JST に変換し、監査人と時刻認識がズレない状態で提出できる
  • シート名に年月(yyyyMM)を付与することで、毎月のログが別シートに蓄積され、過去レポートが上書きされない

GAS のタイムドリガーから「月次タイマー」を設定すれば、毎月自動でデータが蓄積されます。実行タイミングは「翌月 1 日の早朝」に設定するのが確実です。月末(31 日)に設定すると 28 日しかない月にスキップされるため注意が必要です。

また maxResults: 1000 の設定だけでは、活動量の多い組織では 1 回のリクエストでデータが切れます。pageToken を使ったページネーション処理(上記サンプルの do ... while ループ)が必須です。

Admin SDK Reports API の詳細な活用方法については「Admin SDK Reports APIでGAS・AppSheetの利用実態を可視化する」も参照してください。

Vault エクスポート・外部監査エビデンスの保持設計

収集したログをどれだけの期間保持するかが、審査の通過に直結します。

証跡の保持期間:目安は 24 か月

SOC2 審査が年 1 回のサイクルだとすると、前年分の証跡を遡って求められることがあります。スプレッドシートに蓄積したデータは少なくとも 24 か月分を保持するポリシーを設定しておくのが安全です。実際の要件は監査法人と事前に確認してください。

月次ファイルのアーカイブ設計の一例は次の通りです。「当月を含む直近 24 か月分をアクティブスプレッドシートとして保持し、25 か月以降のシートは _archive フォルダへ移動する」という運用が管理しやすいです。Google Drive のフォルダ構造は 監査証跡/YYYY/MM/ のように年月で階層化しておくと、監査人からの特定月のデータ請求に素早く対応できます。

データ量が増えた場合や将来 SIEM ツールと連携する予定がある場合は、BigQuery への定期エクスポートも選択肢になります。ただし BigQuery 連携の構築・維持にはコストと追加の設計工数がかかるため、組織規模と審査頻度を考慮して判断してください。

Google Vault の活用判断

Google Vault はメール・Chat・ドライブのコンテンツを長期保全・エクスポートする機能で、Reports API の監査ログとは性質が異なります。GWS の全プランで利用できるわけではなく、対応プラン以外では Vault アドオンの契約が必要になる場合があります。

Vault が有効に機能するのは、「退職者が送受信したメール一覧を監査人に提出したい」「特定のチャット会話を証拠として保全したい」といったコンテンツ保全のユースケースです。アカウント操作ログ(誰が作成・停止したか)は Reports API で取得するものであり、Vault で取得するものではありません。この使い分けを事前に監査人に説明しておくと、「なぜ 2 つのソースを使うのか」という質問に答えやすくなります。

退職者データの保全を含む総合的なオフボーディング設計については「情シスが設計するGoogle Workspace退職者対応:Admin SDKとVaultの実装パターンと落とし穴」を参照してください。

外部監査人への提出フォーマットをどう設計するか

蓄積したログをそのまま CSV で渡しても、監査人にとっては読みにくい場合があります。SOC2 証跡として受け取ってもらいやすくするためのフォーマット設計の方針を整理します。

必要な列の設計

監査人が確認したいのは「誰が・いつ・何を・なぜ変更したか」です。Reports API から取得できるのは前 3 要素(誰が / いつ / 何を)で、「なぜ(承認根拠)」は別途申請チケット番号や承認記録を追記する必要があります。推奨する列構成は以下の通りです。

列名 内容 ソース
タイムスタンプ(JST) イベント発生日時(日本標準時) Reports API
実行者 操作した管理者のメールアドレス Reports API
対象ユーザー 操作対象ユーザーのメールアドレス Reports API パラメータ
イベント種別 ユーザー作成・停止等のイベント名 Reports API
申請番号 変更申請との紐付け 社内システム(手動入力)
備考 退職日・入社日等の文脈情報(任意) 社内 HR

タイムスタンプは UTC ではなく JST に変換して提出します。監査人が「このアカウント停止は退職日と同日ですか?」と確認する際、UTC のままだと日本時間との 9 時間差で日付が変わる場合があり、混乱の原因になります。

コントロール別にタブを分ける

提出シートのタブを CC6.1 / CC6.2 / CC6.3 別に分けると、監査人が確認しやすくなります。全イベントを 1 シートにまとめて渡すより、コントロールごとにフィルタ済みのシートを提供する方が審査がスムーズに進みます。

CC6.3(アクセス削除)のシートには、退職予定日と実際のアカウント停止日の差(日数)を計算した列を追加することをお勧めします。スプレッドシートなら =NETWORKDAYS(退職予定日セル, 停止日セル)-1 のような関数で営業日数を自動計算できます。「退職後 N 営業日以内に停止されているか」を監査人がひと目で確認できるようになり、コントロールの有効性を示すデータとして機能します。

サンプルデータ形式のイメージ

CC6.3 タブの 1 行はたとえば次のようになります。

タイムスタンプ(JST) 実行者 対象ユーザー イベント種別 申請番号 備考
2025/03/31 17:23:45 admin@example.com yamada@example.com SUSPEND_USER REQ-0231 退職日 3/31、当日停止

このような行が審査期間の全退職者分揃っていれば、監査人は「退職者管理が正常に機能していた」と判断できます。

まとめ:自動化の前に固める 3 つの設計判断

GWS の監査ログを SOC2 証跡として機能させるには、GAS の実装よりも先に 3 つの設計判断を固める必要があります。

1. 何のログをどこに蓄積するか

admin ログが最優先です。token ログは OAuth 管理の証跡が必要なときに追加します。蓄積先はスプレッドシートで当面は十分ですが、24 か月以上の長期保持が必要なら BigQuery へのエクスポートも選択肢に入ります。コスト・運用負荷・監査人の使いやすさを比較して選んでください。

2. 提出サイクルと SOP をセットで設計する

月次収集・審査前整形・24 か月保持という 3 層の運用ルールを文書化しないと、担当者交代のタイミングで継続できなくなります。GAS のコードを書いて終わりではなく、「誰が・いつ・どう確認するか」まで SOP に落とすことが SOC2 対応の本質です。SOP 自体が CC6.1 の証跡として機能する点も意識してください。

また、審査期間が始まる前にログ収集を稼働させることが大前提です。「SOC2 取得を目指す」と決めた時点でログ収集を開始し、最低 6 か月分の連続したデータが蓄積された段階で審査に入るスケジュールが安全です。

3. 承認フローは GWS の外で証明する

GWS 単体では「誰が承認してアカウントを作成したか」は記録されません。社内の申請チケット(Jira / Asana / Google Forms 等)と GWS ログを突き合わせる仕組みを別途設計することで、CC6.2(新規登録の承認プロセス)を証明できます。GWS ログ+申請記録の 2 ソースを組み合わせることが現実的な構成です。

GWS の監査ログは SOC2 対応に活用できるポテンシャルを十分に持っています。「ログが存在する」だけでは証跡として機能しません。定期的な収集・整形・保持・承認フローとの連携という 4 要素を設計してはじめて、外部監査人が納得できるエビデンスとして使えます。GAS での自動収集は設計が固まれば 1〜2 時間で実装できるシンプルな仕組みです。設計判断に時間をかけ、実装はシンプルに済ませるのがこの領域のバランスのとれた進め方です。

コーポレートITのご相談はお気軽に

この記事で書いたような業務改善・自動化の設計から実装まで、DRASENASではコーポレートITの現場に寄り添った支援を行っています。 「まず相談だけ」でも大歓迎です。DRASENAS 公式サイトからお気軽にどうぞ。

CONTACT

御社の IT 部門、ここにあります。

「ITのことはあまりわからない」── そのような状態からで、まったく問題ございません。まずはお気軽にご相談ください。

一社ずつ、一から。