🌊

Bindplane を活用した Google SecOps ログ収集ガイド

に公開

こんにちは、クラウドエースの松島です。
本記事では、Bindplane を利用した Google SecOps へのログ収集について解説します。

Google SecOps とは

Google SecOps は Google が提供する SIEM / SOAR 製品です。
詳細は下記の記事をご参照ください。

https://zenn.dev/cloud_ace/articles/google-secops-overview

Bindplaneについて

Bindplane とは

Bindplane は、様々な環境からログやテレメトリデータを収集・転送するために利用される製品です。
開発元は Bindplane 社で、オープンソースの OpenTelemetry Collector をベースに構築されています。

従来のログ収集エージェントと異なり、Bindplane は単にデータを転送するだけではなく、収集したデータを正規化したり、不要な情報を取り除いたりといった処理を加えることも可能です。

※なお、Bindplane Agent は現在は BDOT Collector と呼ばれたり、Server は Bindplane OP とも記載があったりと一部名称に揺れがあるようですが、この記事では Bindplane Agent と Bindplane Server の記載で統一します。

Google SecOps における Bindplane

Google SecOps においては、主にオンプレミス環境や他のクラウドサービス上のサーバーや各種機器類からログを転送する際に利用します。

従来のオンプレミスなどからのログ収集には Forwarder が利用されていましたが、現時点では Bindplane が Forwarder に替わる新しいログ転送の手段として提供されています。

Bindplane は本来有償の製品ですが、Google SecOps の利用者は SecOps のエディションに応じて有償の Bindplane ライセンスを無償で利用することが可能です。
詳細な情報は下記を参照ください。

https://cloud.google.com/chronicle/docs/ingestion/use-bindplane-agent?hl=ja#difference_between_bindplane_google_edition_and_bindplane_enterprise_google_edition

エージェント単体でもログ転送コンポーネントとして機能しますが、Bindplane Server を利用することで下記のドキュメントの記載のように遠隔での設定変更や状態確認が可能となり運用上の恩恵が大きいため、Bindplane Server をセットで利用することをお薦めします。

https://cloud.google.com/chronicle/docs/ingestion/use-bindplane-agent?hl=ja#bp-console

Bindplane Server と Bindplane Agent

Bindplane は Server と Agent の二つから構成されます。

bindplane-architecture

それぞれ以下のような役割です。

  • Bindplane Agent
    • ログ転送を行うエージェント
  • Bindplane Server
    • Bindplane Agent を集中管理する役割を担う
    • 下図のようなアーキテクチャになっており、データストアとして PostgreSQL と Prometheus を利用する

Bindplane Server

Bindplaneでログを集めてみよう

それでは、Bindplane を利用した以下のようなログ収集アーキテクチャを実際に組んでみたいと思います。

sample-architecture

  • Google Cloud 上に GKE と CloudSQL を立て、そこで Bindplane Server を動かす
    • せっかくなので Bindplane Server は高可用性構成にしてみます
  • Linux サーバーの各種ログを Bindplane Agent で SecOps 送信する
  • Agent を Bindplane Server から管理する

※なお、本記事は Bindplane に焦点を当てたものであるため、Google Cloud や k8s、PostgreSQL など Bindplane 以外部分の詳細な操作手順や説明は割愛しておりますのでご了承ください。

1. Bindplane Server の構築

Google Cloud 上の GKE に Bindplane Server を立ててみます。
基本的に以下のガイドに従ってインストールを進めます。
https://bindplane.com/docs/getting-started/quickstart-guide

1-1. Google Cloud 側の設定

Google Cloud 上に Cloud SQL と GKE を中心に以下のリソースを構築します。

  • GKE
  • Cloud SQL
  • PubSub Topic
  • グローバルIPアドレス

以下の Terraform を使います。

Terraform
locals {
  project_id     = "<プロジェクトID>"
  default_region = "asia-northeast1"
}

resource "google_compute_network" "main_vpc" {
  name                    = "main-vpc"
  auto_create_subnetworks = false
  project                 = local.project_id
}

resource "google_compute_subnetwork" "main_subnet" {
  name          = "main-subnet"
  ip_cidr_range = "192.168.0.0/16"
  region        = local.default_region
  network       = google_compute_network.main_vpc.id
  project       = local.project_id
}

# Cloud NAT 用のグローバル IP アドレスを作成
resource "google_compute_address" "nat_ip" {
  name         = "nat-ip"
  region       = local.default_region
  project      = local.project_id
  address_type = "EXTERNAL"
  description  = "External IP address for Cloud NAT"
}

# Cloud Router を作成
resource "google_compute_router" "main_router" {
  name    = "main-router"
  region  = local.default_region
  network = google_compute_network.main_vpc.id
  project = local.project_id
}

# Cloud NAT を作成
resource "google_compute_router_nat" "main_nat" {
  name                               = "main-nat"
  router                            = google_compute_router.main_router.name
  region                            = local.default_region
  project                           = local.project_id
  nat_ip_allocate_option            = "MANUAL_ONLY"
  nat_ips                           = [google_compute_address.nat_ip.self_link]
  source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"

  log_config {
    enable = true
    filter = "ERRORS_ONLY"
  }
}

# GKE 用のサービスアカウントを作成
resource "google_service_account" "gke_service_account" {
  account_id   = "gke-service-account"
  display_name = "GKE Service Account"
  project      = local.project_id
}

# サービスアカウントにメトリクス書き込み権限を付与
resource "google_project_iam_member" "gke_metrics_writer" {
  project = local.project_id
  role    = "roles/monitoring.metricWriter"
  member  = "serviceAccount:${google_service_account.gke_service_account.email}"
}

# サービスアカウントにログ書き込み権限を付与
resource "google_project_iam_member" "gke_log_writer" {
  project = local.project_id
  role    = "roles/logging.logWriter"
  member  = "serviceAccount:${google_service_account.gke_service_account.email}"
}

# GKE Autopilot クラスターを作成
resource "google_container_cluster" "main_cluster" {
  name     = "main-cluster"
  location = local.default_region
  project  = local.project_id

  # Autopilot モードを有効化
  enable_autopilot = true

  # DNS ベースのコントロールプレーンを有効化
  dns_config {
    cluster_dns       = "CLOUD_DNS"
    cluster_dns_scope = "VPC_SCOPE"
  }

  # ネットワーク設定
  network    = google_compute_network.main_vpc.name
  subnetwork = google_compute_subnetwork.main_subnet.name

  # サービスアカウントを設定
  cluster_autoscaling {
    auto_provisioning_defaults {
      service_account = google_service_account.gke_service_account.email
      oauth_scopes = [
        "https://www.googleapis.com/auth/cloud-platform"
      ]
    }
  }

  # プライベートクラスター設定(オプション)
  private_cluster_config {
    enable_private_nodes    = true
    enable_private_endpoint = false
    # master_ipv4_cidr_block  = "172.16.0.0/28"
  }

  control_plane_endpoints_config {
    dns_endpoint_config {
      allow_external_traffic = true
    }
  }

  # リソース削除時の保護
  deletion_protection = false

  gateway_api_config {
    channel = "CHANNEL_STANDARD"
  }
}

# Pub/Subトピック bindplane を作成
resource "google_pubsub_topic" "bindplane" {
  name    = "bindplane"
  project = local.project_id
}

# Bindplane 用の Workload Identity を設定
resource "google_project_iam_member" "bindplane" {
  project = local.project_id
  role    = "roles/pubsub.admin"
  member  = "principal://iam.googleapis.com/projects/<プロジェクト番号>/locations/global/workloadIdentityPools/<プロジェクト ID>.svc.id.goog/subject/ns/bindplane/sa/bindplane"
}

# BindPlane 用のグローバル IP アドレスを作成
resource "google_compute_global_address" "bindplane_global_ip" {
  name         = "bindplane-global-ip"
  project      = local.project_id
  address_type = "EXTERNAL"
  description  = "Global IP address for BindPlane"
}


# Cloud SQL PostgreSQL インスタンスを作成
resource "google_sql_database_instance" "main_postgres" {
  name             = "main-postgres-instance"
  database_version = "POSTGRES_17"
  region           = local.default_region
  project          = local.project_id


  # 最小構成の設定
  settings {
    edition           = "ENTERPRISE"
    tier              = "db-f1-micro" # 最小CPU・メモリ構成
    # activation_policy = "NEVER"

    # ストレージ設定(HDD、最小サイズ)
    disk_type = "PD_HDD"
    disk_size = 10 # GB(最小サイズ)

    # 高可用性を無効化
    availability_type = "ZONAL"

    # VPCネットワークに接続
    ip_configuration {
      ipv4_enabled    = false
      private_network = google_compute_network.main_vpc.id
    }

    # バックアップ設定
    backup_configuration {
      enabled = false
    }
  }

  # 削除保護を無効化
  deletion_protection = false
}

# Cloud SQL 用の Private Service Access(Service Networking)を VPC に構成
resource "google_compute_global_address" "private_ip_address" {
  name          = "sql-private-ip"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 16
  network       = google_compute_network.main_vpc.id
  project       = local.project_id
}

resource "google_service_networking_connection" "private_vpc_connection" {
  network                 = google_compute_network.main_vpc.id
  service                 = "servicenetworking.googleapis.com"
  reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}

このコードで構成するものは大半が一般なリソースになりますが 、Bindplane 特有の考慮事項が下記の通りいくつかあります。

  • PubSub
    • 高可用性のため複数 Pod で Bindplane Server を構成する場合、PubSubを利用します。このための PubSub Topic を作成しておきます
  • Workload identity 用の権限
    • PubSub サブスクリプションの管理は自動的に行われるため、Workload Identity を利用して Bindplane 用の Kubernetes ServiceAccount に PubSub 管理者権限を付与しておきます

適用できたら、IP アドレスと Bindplane Server に外部からアクセスするための FQDN を DNS に登録しておきます。

1-2. Bindplane Server 導入の下準備

Bindplane Server を立ち上げるにあたって、1-1 に続いていくつか下準備を行います

  • ライセンスキーの取得
  • PostgreSQL のセットアップ

ライセンスキーの取得
こちらのページ からライセンスキーを申し込むことができます。
今回は Google Edition のライセンスキーを申し込みます。

bindplane-apply-licence

メールでライセンスキーが届きます。

licence-key

PostgreSQL のセットアップ
こちらのドキュメントに記載のSQL を使って、以下の設定を行います。

  • Database「bindplane」の作成
  • Bindplane 用のユーザー / パスワード
  • Bindplane 用のユーザーに Database「bindplane」への権限付与

1-3. Bindplane Server 立ち上げ

Bindplane Server は Helm Chart が公開されているので、すぐに立ち上げることが可能です。(bindplane Helm の情報はこちら)

この Helm パッケージには Ingress も含まれているのですが、TLS 証明書はついていないので、証明書を手動で追加します。(詳細はこちら)

この設定を行うため、こちらページを参考に以下のファイルを用意します。

values.yaml (Helm Chart 用)
config:
  # An Enterprise license is required for
  # Bindplane when using PostgreSQL and an event bus.
  license: '入手したライセンスキー'

  # These options should be configured by
  # the user.
  username: '<管理者ユーザー名>'
  password: '<管理者パスワード>'
  sessions_secret: '<任意の文字列>'
  server_url: "https://<FQDN>" # これを入れないとエージェントたちが Bindplane Server と正常に通信できない

replicas: 2

# Eventbus is required when operating Bindplane
# using a distributed architecture.
eventbus:
  type: 'pubsub'
  pubsub:
    projectid: '<Google Cloud プロジェクト ID>'
    topic: 'bindplane'

# Postgres is deployed outside of this chart
# shared by all Bindplane pods.
backend:
  type: postgres
  postgres:
    host: '10.205.0.3'
    port: 5432
    database: 'bindplane'
    username: 'bindplane'
    password: '<パスワード>'

resources:
  # Allow cpu bursting.
  # Request fixed amount of memory, 1Gb.
  requests:
    cpu: '500m'
    memory: '1024Mi'
  limits:
    memory: '1024Mi'

transform_agent:
  replicas: 2

# Ingress 用の設定を追加
ingress:
  enable: true
  class: "gce"
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "bindplane-global-ip"
    networking.gke.io/managed-certificates: bindplane
  host: <FQDN>

certificate.yaml (Ingress 用 TLS 証明書)
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: bindplane
  namespace: bindplane
spec:
  domains:
    - <FQDN>

準備ができたら適用します。

kubectl create ns bindplane

kubectl apply -f certificate.yaml

helm repo add "bindplane" \
    "https://observiq.github.io/bindplane-op-helm"

helm repo update

helm upgrade \
    --values="values.yaml" \
    --namespace=bindplane \
    --create-namespace \
    --install \
    bindplane \
    bindplane/bindplane

しばらくして Google Cloud のコンソール画面から次のように k8s 上の各種リソースと Google Cloud 上の LB が問題ない状態になっていれば成功です。

workloads.png
lb.png

1-4. UI の動作確認

ブラウザから設定した FQDN にアクセスします。
values.yaml で設定したユーザー ID、パスワードでログインします。

login.png

Bindplane 上で使う組織の名称を入力します。
後で変更できるため、任意の値を入力します。

bindplane-server-ui1.png

ここまでで Bindplane Server の構築は完了です。

bindplane-server-ui3.png

2. 各サーバーへのエージェント導入

続いて ログを収集する Bindplane Agent の導入を行っていきます。

Google SecOps の公式ページに Bindplane Agent の導入方法が載っていますが、こちらは単にエージェントをインストールするだけのコマンドになっており、Bindplane Server を意識したものになっていません。(ログを Google SecOps に送る部分だけであればこれで十分です)

一方 Bindplane 側の公式ドキュメントには Google SecOps との連携用のドキュメントがあり、こちらは Bindplane Server の存在を前提にしたものになっているため、こちらをベースに設定を行なっていきます。

https://bindplane.com/docs/how-to-guides/google-secops-bindplane-quick-start#configure-your-bindplane-organization

2-1. Bindplane Server に ログ送付先となる Google SecOps の情報を登録する

まず、ログを送付する先となる Google SecOps の情報を Bindplane Server に登録します。
上記のドキュメントの「Configure the SecOps Destination」を参考に設定していきます。

Bindplane UI にアクセスし、上の LIBRARY タブを選択、一番下の Destinations から Add Destination をクリック、Google SecOps を選択します。

set-destination.png

次のように設定し、Save します。

項目 設定値
Protocol gRPC を選択
Endpoint Google SecOps インスタンスの所在地に合わせてこちらのリンクの値から選択。東京リージョンの場合は添付画像のようになる。
Authentication Method jsonを選択
Credentials Google SecOps の 「SIEM Settings > Collection Agents」画面から「Ingestion Authentication File」をダウンロードし、中身の json を丸ごとコピーしてペーストする
Fallback Log Type Log Type が指定されていない場合のデフォルトのログタイプを指定します。ここでは Syslog 一般を表す NIX_SYSTEM を指定します
Customer ID Google SecOps の 「SIEM Settings > Profile」画面から Customer ID を確認して入力

2-2. Linux からログを収集する

Bindplane Agent のインストール
まず、対象の Linux サーバに Bindplane Agent をインストールします。
Bindplane UI にアクセスし、上の Agent タブを選択後、右上の Install Agent をクリックします。

install-agent1.png

続いて表示された画面で Linux を選択します。
Agent Type は 2025/07 時点では BDOT 1.0 が安定版のようなので、こちらを選択します。

install-agent2.png

次の画面では Agent のインストールスクリプトが表示されますので、これをサーバで実行すれば Agent がインストールされます。
下の画像の赤枠部分について、Bindplane Server 立ち上げ時に server_url で指定した FQDN になっていることを確認してください。
例えば、server_url に test.example.com を指定し、この FQDN で Ingress を公開している場合であれば、赤枠部分は「wss://test.example.com/v1/opamp」と値が表示されることになります。

install-agent3.png

このスクリプトをサーバで実行し、インストールが成功すると Bindplane の UI 上に Agent が表示されます。

install-agent4.png

ログ収集設定
エージェントをサーバに導入した後、ログ収集の設定を行います。
この設定を Bindplane UI から遠隔で実施してみます。

Agent の一覧画面から先ほどのエージェントを選択し、Configuration タブで Create Configuration をクリックします。

set-log-collector1.png

今回は次のように設定します

set-log-collector2.png

ログソースを選ぶ画面では File 形式を選択し、今回は Syslog 関連のファイルを収集することにします。

set-log-collector3.png

次のように設定します。

項目 設定値
Short Description 適当な説明を記載
File Path 収集したいログファイルを指定
Advanced > Start At beginning

set-log-collector4-1.png

set-log-collector4-2.png

送付先を設定する画面では先ほど設定した Google SecOps を送付先に設定します。

set-log-collector5.png

set-log-collector6.png

Save をクリックして設定を保存します。

set-log-collector7.png

以下のような画面になるので、Add Agent から先ほど登録した Linux サーバを追加します。

set-log-collector8.png

set-log-collector9.png

Start Rollout をクリックするとエージェントに設定が反映されます。

set-log-collector10.png

なお、設定を変える場合も同じように Configuration を変更 => Start Rollout の順で操作すれば遠隔で設定変更を行うことができます。

成功すれば Google SecOps でログを確認することができます。

また、Bindplane UI からエージェントの状態や直近のログの内容を確認することも可能です。
monitoring1.png

monitoring2.png

今回は使用していませんが、ソースの設定次第で別のサーバから送られた Syslog を転送することなども可能です。
用途に合わせて適切なソースを選択して設定を行うようにしてください。

2-3. Log Type を設定する

ここまでの操作でエージェントがファイルからログを読み取って SecOps に送信できるようになりました。
しかし、現在の状態だと Destination で指定した Fallback Log Type がログタイプに指定されており、全て Syslog として解釈される状態になっています。
このままでは Fallback Log Type 以外のログタイプを指定したい場合に困ってしまいます。
ということでここでは、auditd を題材に、任意のログタイプを指定する操作を紹介します。

まず、先ほど使ったサーバにこちらを参考に auditd を導入します。
その後、Bindplane UI から、先ほど設定した Configuration に以下の設定を追加します。

  • 先ほど設定した File タイプのソースと同じ設定で、File Path を 「/var/log/audit/audit.log」に設定したもの

下の画像のようになっていれば OK です。

set-logtype1.png
set-logtype2.png

ここからプロセッサを追加し、ログタイプを設定します。
プロセッサはログ転送の際、フォーマットの変更などの加工を行う機能です。

下図の赤枠部分をクリックします。

set-logtype3.png

Add processor から Google SecOps Standardization を選択、Log Type に auditd を設定して Save します。

set-logtype4.png
set-logtype5.png

なお、namespace や ラベルなど、他の SecOps 取り込み用のパラメータもここで設定することができます。
また、今回はソースを通常の Syslog と auditd とで分ける方法を取りましたが、一つのソースにしてプロセッサの Condition を使って auditd のログファイル名の場合のみログタイプを設定するような方法も取ることができます。

設定が完了すると、先ほどクリックした箇所に設定されたプロセッサ数(①)が見えるようになります。

set-logtype6.png

Start Rollout を実行して設定をエージェントに反映させます。

すると先ほどまでログタイプに NIX_SYSTEM が指定されていたところ、AUDITD が設定された状態で SecOps に取り込まれるようになります。

set-logtype7.png

運用のポイント

実際に商用環境で運用するにあたり、考慮した方が良さそうなポイントをあげてみます。

Bindplane Agent の死活監視

Google Cloud の機能である Cloud Monitoring を利用して、Bindplane Agent のログ取り込みの状況に応じたアラートを設定することができます。
商用環境では Agent の状態は常に把握しておきたいものかと思いますので、下記ドキュメントを参考に設定してみてください。

https://bindplane.com/docs/how-to-guides/secops-silent-host-monitoring

Gateway と高可用性

Bindplane Agent は別の Bindplane Agent からのログを中継することが可能で、これを Bindplane Gateway と呼びます。
送付側のエージェントの宛先を Bindplane Gateway に、Gateway 側のソースを Bindplane Gateway に指定することで構成でき、UI 上では次の画像のように Gateway も含めたログ転送のトポロジを把握できるようになります。

gateway.png

Google SecOps への 送付の場合、サービスアカウント キーを各所にばら撒くのが気になる場合など、この構成を使うことで Gateway にだけ認証情報を持たせるような構成を取るようなユースケースが考えられます。

一方で、Gateway は様々なソースからログを集約することになるため、冗長構成など、高可用性の確保が必須となりますので、下記ドキュメントを参考に検討するのが良いでしょう。

https://bindplane.com/docs/going-to-production/agent/configure-ha-opentelemetry-collectors

スケーリングについて

Bindplane Server 及び Agent、いずれも負荷に応じたスケーリングを考える必要があります。

Bindplane Server、Agent それぞれ公式にスケーリングの目安が公表されているので、こちらを参考に構成を検討してください。

https://bindplane.com/docs/advanced-setup/installation/prerequisites

https://bindplane.com/docs/going-to-production/agent/sizing-and-scaling

また、Cloud SQL や Prometheus のデータ容量も気にする必要があります。
注意点は一般的な Cloud SQL や GKE 上の StatefulSet の扱いと同じであるためここでは詳細は記載しませんが、拡張手順の準備や監視などは行うべきでしょう。

ユーザー管理について

Bindplane Server では OIDC による SSO を設定することが可能です。

https://bindplane.com/docs/advanced-setup/configuration/oidc

社内に Entra ID や Google アカウントなどが存在していることが多いと思いますので、これらによる SSO を設定することをお勧めします。

Project の分割

Bindplane Server で Project という単位で論理的に設定を分けることが可能になっています。
複数の環境から取り込む場合は、適切に Project を分割するなど、管理しやすいように工夫するのが良いと考えられます。

Bindplane Cloudについて

本記事では自前で Bindplane Server を構築しましたが、クラウド版という選択肢もあります。
データの所在や金額などに折り合いがつくようであれば、クラウド版を選択することで運用負荷を下げることができますので、必要に応じて検討してみてください。

初期セットアップ時の各種クレデンシャルの扱いについて

今回のハンズオンで Helm パッケージに与えた values.yaml には DB や WebUI の管理者のパスワードなどの秘匿情報が含まれていました。
が、一般的にはこれらの値は設定ファイル等に誰もが見えるように記載すべきではありません。

Bindplane の Helm チャートは、ライセンスキー、DB や WebUI の認証情報を k8s Secret から取得できるように構成されていますので、商用環境で構築する際はこちらを利用するようにしてください。

参考:マニフェストの該当部分

特に Google Cloud で構築する場合は、Secret Manager を External Secrets Operator と組み合わせて利用することができますので、以下の記事を参考に検討してみてください。

https://zenn.dev/cloud_ace/articles/gke-secret-manager

構成情報の管理

今回はコマンドでインストールを行いましたが、Kubernetes を利用するのであれば、helmパッケージのバージョンや values.yaml を Git 等で管理するのが良いと考えられます。
ArgoCD を使った GitOps など、ツールを組み合わせて効率化できるとなお良いと思います。

参考情報

  • Google の方による記事

https://medium.com/@thatsiemguy/observiq-bindplane-the-otel-agent-and-google-secops-e6ab00bdb580

  • Bindplane の方によるデモ

https://www.youtube.com/watch?v=vLh0e18E5E0

  • helm で設定可能なパラメータ

https://github.com/observIQ/bindplane-op-helm/blob/main/charts/bindplane/values.yaml

  • SecOps x Bindplaneのベストプラクティス集

https://bindplane.com/docs/how-to-guides/using-google-secops-with-bindplane#use-gateway-collectors

  • Google Cloud に VM で高可用性構成で Bindplane Server を構築するためのドキュメント

https://bindplane.com/docs/how-to-guides/multi-node-architecture-on-google-cloud#configure-remote-prometheus

おわりに

Bindplane Server の導入により、従来の Forwarder を利用した方法や、Bindplane Agent を単体で利用する場合に比べ、Google SecOps におけるログ収集機構全体の品質を向上させられることがお分かりいただけたかと思います。
ぜひ Google SecOps を運用される際は導入を検討してみてください。

クラウドエースでは Google SecOps の導入・構築支援を行っていますので、ご興味のある方はぜひ当社までご連絡ください!

Discussion