株式会社ネットワールドのエンジニアがお届けする技術情報ブログです。
各製品のエキスパートたちが旬なトピックをご紹介します。

GitとCI/CDに関する知識ゼロのSEが、GitLab.comの監査イベントをAmazon S3に出力する話

皆様こんにちは。SEの小池と申します。

前回のブログでは、GitLab.comの監査イベントをPipeDreamを用いてCloudWatch Logsに出力する方法をご紹介いたしました。
で、前回のブログの内容を社内関係者に確認してもらったところ、以下のコメントをもらいました。

S3に保存するのかCloudWatch Logsを使用するのかも悩ましいところですね。 (上司より)

そりゃそうですよね・・・。ごもっともです。
AWSのサービスでログ保管先と言えば、まず検討すべきはS3です。

社内関係者 (上司) からごもっともなコメントを頂戴したので、今回はGitLabの Audit event streaming 機能を使って監査イベントをAmazon S3に出力する方法を考えました。

本記事の対象の方

  • GitLab.comの監査イベントをAmazon S3に保存したいと思っていらっしゃる方。

今回のブログのゴール

このブログのゴールはこちらです。


今回のゴール
  • GitLab.comの監査イベントをAmazon S3に出力する。

このブログをお読みいただくにあたっての事前ご連絡事項

  • 本記事はSaaS版 GitLab.com (Enterprise Edition 15.8.0-pre) における仕様をベースに記載しております。それ以外のエディションやバージョンではこの記事に記載の通りではない可能性がございます。
  • 本記事のGitLab.comのGUIは日本語にローカライズした状態で掲載しております。それ以外の言語をご利用の方は適宜読み替えてください。
  • 本記事では3rdパーティ製のローコード統合プラットフォームであるPipeDreamを使用しています。PipeDreamは2023/01/12時点の仕様 (v2) で記載しております。
  • 本記事ではAudit Event Streaming機能を使ってGitLab.comの監査イベント取得の実装手順を記載しておりますが、この実装方法はSaaS版 GitLab.comのみが対象であり、Self-Managed版 (オンプレミス版) は対象外です。

GitLabのAudit Events (監査イベント) の概要

GitLabのAudit Events (監査イベント) では、グループやプロジェクトの削除や公開範囲 (visibility) の変更等、重要なアクションを追跡・閲覧することが可能です。

本機能はティア Premium 以上のSaaS版 (GitLab.com) 又は ティア Premium 以上のSelf-Managed版 (オンプレミス版) で利用可能です。
参考:Audit events | GitLab

GitLabのAudit Events (監査イベント) の概要については前回のブログ (こちら) の「GitLabのAudit Events (監査イベント) の概要」に記載しておりますので、よろしければご参照ください。

GitLabのAudit Event Streamingの概要

Audit Event Streamingは、最上位 (ルート) グループのストリーミング先を設定することで、最上位 (ルート) グループ、サブグループ、およびプロジェクトに関するすべてのAudit Events (監査イベント) をJSON形式で受信できるAPIストリーミング機能です。

本機能はティア Ultimate 以上のSaaS版 (GitLab.com) 又は ティア Ultimate 以上のSelf-Managed版 (オンプレミス版) で利用可能です。
参考:Audit event streaming | GitLab

GitLabのAudit event streamingの概要については前回のブログ (こちら) の「GitLabのAudit Event Streamingの概要」に記載しておりますので、よろしければご参照ください。

このブログで実装する処理の概要

GitLab.comの Audit Event Streaming 機能を使って、監査イベントをAmazon S3に取得していきます。

本ブログで実装する処理の流れは以下の図の通りです。

このブログで紹介する方法を実装するには以下を全て満たす必要があります。

本ブログで紹介する実装方法の前提
  • GitLab.comを利用している。
  • ティアUltimateが適用された最上位 (ルート) グループが存在する。

また、このブログで紹介する方法では、GitLab.com以外に以下の外部サービスを利用します。

GitLab.com以外で利用する外部サービス
  • Amazon Web Service - S3
  • PipeDream

このブログに記載した設定を実装することで外部サービスで課金が発生する可能性が有ります。
2023/01/12現在、本ブログの内容を実装するにあたりPipeDreamはFreeプランで問題ありません。
ただし、PipeDreamのFreeプランは月10,000回の呼び出ししかできません。
監査イベントが多数発生する環境での実装は、あらかじめ一か月に発生する監査イベントの数を確認してから実装することをお勧めいたします。

Step1: Amazon S3のバケットの準備

Amazon S3のバケットを作成します。
作成するバケットの各種設定は全て任意です。
このブログでは以下の表の通り作成致します。表に記載のない項目は任意です。

表1. Amazon S3のバケットの設定
設定項目 設定値
バケット名 gitlabcom-auditeventstreaming-blog
リージョン アジアパシフィック (東京) ap-northeast-1
オブジェクト所有者 ACL 無効
このバケットのブロックパブリックアクセス設定 [パブリックアクセスをすべて ブロック] にチェックを入れる。
デフォルトの暗号化 任意。
このブログの実装では [Amazon S3 マネージドキー (SSE-S3)] に指定しました。

Step2: AWS IAMユーザーの準備

PipeDreamからAWS Lambdaのファンクションを実行する際に、アクセスキーIDシークレットアクセスキーを使用します。
このアクションに必要な権限を保有するIAMユーザーのアクセスキーIDとシークレットアクセスキーをご準備ください。

このブログではAWS管理ポリシーである AWSLambda_FullAccess をアタッチしたユーザーを用意しています。
このポリシーは必要最小限の権限ではないため、実際に本ブログで紹介する方法を実装する場合は、必要最小限の権限をご確認いただけますようお願い申し上げます。

Step3: PipeDreamのワークフロー作成 (前半)

PipeDreamのアカウントを以下のURLであらかじめ作成したうえで、続きの手順を実施してください。
参考:Connect APIs, Remarkably Fast - Pipedream

最初にGitLab.comのAudit Eventsを取得するステップを作成します。

PipeDreamのTOP画面で、[Workflows] > [New +] をクリックします。

ステップの検索ボックスで gitlab 等と入力すると GitLab が候補に表示されるので、それをクリックします。

再び検索ボックスで audit 等と入力すると New Audit Event (Instant) というステップが表示されるので、それをクリックします。

Gitlab Account欄の [Connect a Gitlab account] をクリックします。

別ウィンドウでGitLab.comのサインイン画面が表示されるので、Audit Eventsを取得する予定のグループに権限 Owner を所有するアカウントでサインインします。

PipeDreamを承認して、アカウントを使用することへの確認メッセージが表示されます。
[Authorize] をクリックします。

再度、Gitlab Account欄の [Connect a Gitlab account] をクリックします。

表示が [Select a Gitlab account...] に変わるので、それをクリックします。
すると、プルダウンに先ほど GitLab.com にサインインしたアカウントが表示されるので、それを選択します。

Group ID欄の [Select an option...] をクリックすると、先ほどのGitLab.comのアカウントが所属する最上位 (ルート) グループの一覧が表示されます。
Audit Eventsを取得したい最上位 (ルート) のグループ名をクリックします。
なお、この際指定した最上位 (ルート) グループにUltimateライセンスが適用されていない場合は、後続の手順に進むことができません。

[Create source] をクリックします。

そのまましばらく待つと、テストイベントが生成されます。
[Select event...] をクリックし、生成されたテスト用イベントをクリックします。

[Exports] タブでテスト用のイベントの詳細が表示されることを確認します。

この画面はそのまま残し、別タブなどでAWSのLambda関数の作成をします。

Step4: AWS Lambdaの関数作成

AWS Lambdaで、PipeDreamから受け取ったJSON形式の監査イベントをAmazon S3に1イベント1ファイルで出力する関数を作成します。

バケットのフォルダー構成は、yyyy/MM/dd とします。
なお、このブログでは監査イベント作成日時を世界標準時としております。日本時間にしたい場合は、Lambda関数の中で処理を追加してください。

Step.3とは別タブもしくは別ウィンドウでAWSのコンソールにサインインし、任意のリージョンのLambdaのメニューから [関数] > [関数の作成] をクリックします。
このブログでは例として アジアパシフィック (東京) ap-northeast-1 で作成します。

[一から作成] を選択し、以下の表の通り設定します。

表2. AWS Lambdaの関数の設定
設定項目 設定値
関数名 任意の文字列を指定。
(このブログでは例としてGitLabcom-AuditEventStreaming-S3とします。)
ランタイム Python 3.9
アーキテクチャ x86_64
アクセス権限 基本的な Lambda アクセス権限で新しいロールを作成
(後ほどS3に対する権限を追加します。)

[関数の作成] をクリックします。

サンプルコードを削除し、以下のコードを貼り付けます。

import jso
import boto3

s3 = boto3.resource('s3')

def lambda_handler(event, context):

  # イベントが作成された年月日取得 (世界標準時) 
  create_time = event["trigger"]["event"]["created_at"]
  create_year = (create_time[:4])
  create_month = (create_time[5:7])
  create_day = (create_time[8:10])

  # bucket, key, bodyの指定
  context_id = event["trigger"]["context"]["id"]
  event_id = event["trigger"]["event"]["id"]
  event_entity_type = event["trigger"]["event"]["entity_type"]
  event_event_type = event["trigger"]["event"]["event_type"]
  bucket = 'your_bucket_name'     # バケット名 
  key = '%s/%s/%s/%s_%s_%s_%s.json' % (create_year, create_month, create_day, create_time, event_id, event_entity_type, event_event_type)
  body = json.dumps(event)

  # Audit Eventsをjsonファイルで出力  
  obj = s3.Object(bucket,key)
  obj.put(Body=body)
  
  return

監査イベント作成日時のタイムゾーン
Audit Event Streaming機能で取得したイベントの作成日時は世界標準時になっています。
このブログでは世界標準時のまま後続の処理を進めますが、もし、日本標準時に変換する必要があれば、Lambda関数の中にその処理を追加してください。

貼り付けたコードの19行目 bucket = 'your_bucket_name' の値を、事前に作成したバケット名に変更します。このブログの場合は bucket = 'gitlabcom-auditeventstreaming-blog'となります。

[Deploy] をクリックします。

S3に関するアクセス権を追加します。
[設定] > [アクセス権限] > 実行ロールの [編集] をクリックします。

[既存のロール] のプルダウンの下に、[View the <このLambda作成時に自動作成されたロール名> role] と表示されているので、このリンクをクリックします。

別タブでIAMのメニューが開きます。
[許可] タブ > [許可を追加] > [ポリシーをアタッチ] をクリックします。

[その他の許可ポリシー] 欄の検索ボックスに "AmazonS3FullAccess" 等と入力すると AmazonS3FullAccess が表示されるので、これにチェックを入れます。

S3へPUTするのに必要な権限
今回は現在使用しているロールに [AmazonS3FullAccess] をアタッチしますが、これはこのLambda関数の処理内容を考慮した最小権限ではありません。
実際に実装なさる場合は必要な最小権限のみを付与するようにしてください。

[ポリシーをアタッチ] をクリックします。

IAMロールを編集していたタブを閉じ、Lambdaのアクセス権限をしていたタブに戻ってください。
先ほど既存のロールにS3に関する権限を付与したので、ここではロールの変更などは不要です。
[キャンセル] で閉じます。

Lambda関数の [設定] > [アクセス権限] の画面に自動で戻りますので、[F5] キーなどでブラウザを更新します。

[設定] > [アクセス権限] > [リソースの概要] のプルダウンに、「Amazon S3」という表示があることを確認します。

AWSのLambda関数の作成は以上です。

Step5: PipeDreamのワークフロー作成 (後半)

PipeDreamのワークフローにAWS Lambdaの関数を実行する処理を作成します。

Step3で使っていたPipeDreamのワークフロー編集画面で作業します。
Step3で作成したGitLab.comのAudit Eventsを取得するステップの下に表示されている [Continue] をクリックします。

検索ボックスに aws 等と入力すると候補に AWS と表示されるので、それをクリックします。

続けて検索ボックスに lambda 等と入力すると候補に Lambda - Invoke Function と表示されるので、それをクリックします。

AWS Account欄の [Connect an AWS account] をクリックします。

事前に作成していたAWS IAMユーザーの、アクセスキーID、シークレットアクセスキーを設定します。
ニックネームは任意で指定します。
[SAVE] をクリックします。

以下の表のとおり設定します。

表3. Lambda実行ステップの設定値
設定項目 設定値
AWS Region 前の手順で作成したLmbda関数があるリージョン。
(このブログの場合はAsia Pacific (Tokyo) - `ap-northeast-1`。)
Function Name 前の手順で作成したLambda関数の名前。
(このブログの場合はGitLabcom-AuditEventStreaming-S3。)

Optional Fields欄の [+ Event Data] をクリックします。

Event data欄が表示されるので、そこにGitLab.comのAudit event streaming経由で取得したAudit Eventsのデータを指定します。
[Enter a custom expression] タブを開き、[steps{1}] をクリックします。

Event data欄に {{steps}} と指定されたことを確認します。

[Test] をクリックします。

結果に "Success" と表示されることを確認します。

S3のバケットにAudit Eventsが記載されたjsonファイルが作成されたことを確認します。
今回のブログに載せたコードの通りLambda関数を作成している場合、フォルダー構成とファイル名は//バケット名/年(4桁)/月(2桁)/日(2桁)/<イベント作成日>_<イベントID>_<エンティティ>_<メッセージ>.jsonで生成されます。

ワークフローはこれで完成です!
[Deploy] をクリックしてワークフローをデプロイします。

おまけ: Lambdaエラー発生時の処理

Lambda関数が失敗した際の処理や通知などを任意に設定してください。
(なお、PipeDreamのワークフローが失敗した場合、そのワークフローの所有者にメールで通知が行くようにデフォルトで設定されています。)

下図はLambda関数失敗時だけAmazon SNS トピックのメールアドレスに通知が行くように設定しています。

動作確認

実際にGitLab.comで監査イベントが発生するアクションを実施して、その監査イベントがAmazon S3に出力されることを確認します。

GitLabの監査イベントはインスタンスレベル・グループレベル・プロジェクトレベルが存在しますが、このパイプラインで取得できる監査イベントは、対象の最上位 (ルート) グループ 及び その配下に含まれるすべてのサブグループ 及び プロジェクトで発生した監査イベントです。
したがって動作確認では、グループレベルの監査イベントとプロジェクトレベルの監査イベントの両方を試験的に発生させ、それらの両方がAmazon S3の該当バケットに出力されることをご確認いただくことをお勧めいたします。

監査イベントで出力されるイベントはGitLab Docsに一覧があります。
グループレベルの監査イベントはこちら、プロジェクトレベルの監査イベントはこちらをご参照ください。

例として、こちらは対象の最上位 (ルート) グループ配下にあるプロジェクトからzip形式でリポジトリをダウンロードした際に発生する監査イベントです。

今回のブログに記載したまま実装すると、Amazon S3には//バケット名/年(4桁)/月(2桁)/日(2桁)/<イベント作成日>_<イベントID>_Project_repository_download_operation.jsonでjsonファイルが生成されます。

最後に

この度はGitもCI/CDもよくわかっていないど素人SEによるGitLab検証ブログをお読みいただき、誠にありがとうございます。
このブログの目標は以下のとおりでしたが、皆さまはいかがでしたでしょうか。


今回のゴール
  • GitLab.comの監査イベントをAmazon S3に出力する。

今回はAudit Event Streaming機能を用いた監査ログ取得ブログ第2弾でした。
Audit Event Streaming機能が優秀なのと、PipeDreamの使い勝手が良いため、Lambda初心者の筆者でもあっさり実装することができました。

GitLab.comの監査イベントを自動取得して長期保管する必要がある場合は、今回のようにAudit Event Streaming機能とAPIを組み合わせて取得する方法をご検討いただければと存じます。

この記事がGitLabを触り始めた方の一助となれば幸いにございます。


GitLabに関するお問い合わせは、以下のフォームからお願い致します。
GitLab製品 お問い合わせ

今までのGitLabの検証ブログはこちらです。
GitLab カテゴリーの記事一覧 - ネットワールド らぼ

GitLab操作デモ動画 (基本編) を作ってみました。(音声の録音は自宅でiPhoneのボイスメモ使うという超低クオリティですが…。)
つたない内容ではありますが、ご興味がおありでしたら是非ご視聴いただければと存じます。

www.youtube.com