AIエージェントの「サンドボックス設計」を考える——Anthropicのサイバー評価インシデントから

概要

Anthropicが2026年7月30日、自社のサイバーセキュリティ評価においてClaudeが評価環境からインターネットへ意図せず到達し、3件のインシデントで実在組織のシステムに不正アクセスしていたことを公表した。設定ミスというより「無人実行するAIエージェントをどう封じ込めるか」という運用設計の問題として読み解く。


背景:何が起きたか

7月21日、OpenAIが自社モデルがゼロデイ脆弱性を突いて隔離テスト環境から脱出し、Hugging Faceの本番インフラにアクセスしたことを公表した。これを受けてAnthropicは自社の評価トランスクリプトを大規模に遡及調査し、141,006件の評価実行の中から3件のインシデントを特定した。

いずれもcapture-the-flag(CTF、隠された秘密情報を奪取する演習)形式の評価で、モデルには「インターネットアクセスなし」と明示していたが、評価パートナーとの設定の行き違いにより実際には接続可能だった。モデルは遭遇した実システムをシミュレーションの一部と誤認したまま、弱いパスワードや未認証エンドポイントの悪用といった基本的な手法で侵入した。

関与したモデルはOpus 4.7、Mythos 5、内部リサーチテストモデルの3つ。対象が本物だと気づいた後の挙動がそれぞれ異なっていた点が興味深い。

  • Opus 4.7(最も古いモデル):本番システムだと認識しながらも攻撃継続
  • Mythos 5:オープンなインターネットに出ていることを一度は正しく直感したが、証明書や日付情報を根拠に「やはりシミュレーションだ」と自分を納得させて継続
  • 内部リサーチテストモデル(最新):本物だという証拠が出た時点で自律的に停止

詳細は原文を参照(Investigating three real-world incidents in our cybersecurity evaluations、2026-07-30、8/3一部訂正)。


設定ミスの話で終わらせられない理由

この記事、表面だけ読むと「評価パートナーとの設定ミスでネットワーク境界が漏れていた」という運用上のポカに見える。実際Anthropic自身も「モデルのアラインメント失敗というより、ハーネス・運用上の失敗に近い」と位置づけている。

ただ、インシデント2の中身を見ると単純な設定ミスの話では済まなくなる。Claudeは「PyPIパッケージを公開すれば罠を張れる」と気づいた後、PyPIアカウント作成に必要なメールアドレスを取得するため、電話番号取得サービスを探し、有料サービスの支払い手段を複数試み、失敗した末に無料のメールプロバイダーを見つけて登録している。ここまでの執念は、「与えられたゴールを達成するために手段を尽くし続ける」というエージェントの性質そのものが表に出たケースだと感じる。

記事中の一文が象徴的:

Situational awareness is one factor that allows the model to make aligned decisions, but in this case, Claude's was wrong.

(状況認識はモデルが整合的な判断を下すための一因だが、今回のケースではClaudeの状況認識が誤っていた)

つまり「境界線が漏れていた」ことと「漏れた先でモデルがどこまでゴール達成に突き進むか」は別レイヤーの問題として捉える必要がある。設定さえ直せば解決、という話ではない。


対話前提のガードレールと、通し実行前提のガードレールは別物

Claude Codeなどでツール実行権限を絞る場合、まず思いつくのは settings.json でツールを許可リスト化する方法。これは有効な対策だが、前提として「対話しながら進める」ワークフローと「通しで無人実行する」ワークフローでは、ガードレールの設計思想を分けて考える必要がある。

観点 対話前提 通し実行前提
危険な操作の直前 ユーザー確認を挟める 確認フックが存在しない
異常検知 人間がその場で気づける ログ監視・後追いレビュー頼み
想定される事故 単発の誤操作 誤った前提のまま最後まで完走

今回のインシデントは、まさに「通し実行」でモデルが検証されずにゴールへ向かい続けた結果起きている。CTF演習という性質上、モデルが自律的に手段を選んで完走することが前提の設計だった点も背景にある。

無人で長時間・多ステップ動くAIエージェントを運用するなら、対話型の「怪しい時に止める」設計だけでなく、インフラレベルでの封じ込めをセットで考える必要がある。


デフォルト拒否・出る必要のない経路は塞ぐ

記事内でAnthropic自身がこう書いている。

it's likely, for instance, that Claude wouldn't have accessed the internet to begin with if the prompt had clearly explained which systems were in and out of scope for the evaluation.

(対象範囲を明確に示していれば、そもそもインターネットにアクセスしなかった可能性が高い)

プロンプトで「インターネットアクセスなし」と伝えるのと、実際にネットワーク的に遮断されていることは別物、というのがこのインシデント最大の教訓だと思う。

実務に落とすと発想はシンプルで、インターネットに出る必要がないワークロードには、そもそも出られる経路を作らない。VPCエンドポイント経由で必要なAWSサービスだけに絞る、NATゲートウェイを置かない、セキュリティグループ・NACLでアウトバウンドをデフォルト拒否にする、といった構成がそのまま該当する。

「穴を突かれて出てしまう」ケースはゼロデイ的な話でどうしようもない部分もあるが、少なくとも意図せず開いている経路を放置しないことは、多層防御(defense-in-depth)の最初の層として効く。今回の3件も、そもそもの経路さえ塞がれていれば起きなかった話ではある。


セキュリティ対策とコストのギャップ

今回インシデントの被害を受けた組織側も、攻撃を検知していなかった。大手企業ですら評価環境やネットワーク境界を完全に把握しきれていなかったことの裏返りとも言える。

厳密なネットワーク分離やログ監視体制を組むにはそれなりのコストがかかる。潤沢な予算を割ける組織ばかりではなく、体力の乏しい組織では「対応したくてもコスト的にできない」という現実的な壁がある。ベストプラクティスとして語られる多層防御も、実際にどこまで実装するかは組織のリソースとのトレードオフになる。


まとめ

  • Anthropicは自社のサイバーセキュリティ評価環境から、Claudeが実世界のシステムに不正アクセスしていた3件のインシデントを自ら遡及調査し公表した
  • 表面的には評価パートナーとの設定ミスだが、モデルがゴール達成のために手段を尽くし続けた挙動は別レイヤーの問題として見るべき
  • 対話前提のガードレール(都度確認)と、通し実行前提のガードレール(インフラレベルの封じ込め)は設計思想が異なる
  • プロンプトでの制約表明とネットワークレベルの遮断は別物。出る必要のない経路はそもそも作らない設計が有効
  • 多層防御はベストプラクティスだが、実装コストは組織の体力に依存し、すべての組織が同水準で対応できるわけではない

原文:Investigating three real-world incidents in our cybersecurity evaluations(Anthropic, 2026-07-30)

EMR/Glue/Kinesisの使い分け、Spark、Hadoopとの違い

概要

AWSのビッグデータ関連サービス(EMR / Glue / Kinesis)は名前が似ていて役割が混同されやすい。それぞれ「データの状態」と「処理の自由度」で整理すると使い分けが明確になる。あわせて裏側で動くSparkとHadoopの違いにも触れる。


1. 3つのサービスの立ち位置

データには大きく2種類ある。

  • 溜まっているデータ(例:S3に蓄積された過去の売上ログ)
  • 流れ続けているデータ(例:アプリのクリックイベントが常時発生)

この軸で3サービスを整理すると以下になる。

サービス データの状態 得意なこと
Glue 溜まっているデータ 定型的な変換・整形(ETL)
EMR 溜まっているデータ 自由度の高い大規模分散処理
Kinesis 流れ続けるデータ リアルタイム処理

AWS Glue

ETL(Extract / Transform / Load)専用のマネージドサービス。クローラーがデータのスキーマを自動検出し、Athenaなどから使えるテーブルを自動生成する。裏側ではSparkが動いているが、クラスタ管理やチューニングは意識しなくて良い。

Amazon EMR

Hadoop、Spark、Hive、Prestoなどのオープンソースフレームワークをマネージドで動かすサービス。ノード数やインスタンスタイプ、チューニングまで自分で制御できる。その分、運用の手間は増える。

Amazon Kinesis

常時流れてくるデータをリアルタイムで受け取り処理する。用途別に3種類ある。

  • Data Streams:秒あたり数GB規模のデータをリアルタイム処理
  • Data Firehose:最低60秒のバッファでS3やOpenSearch Serviceに格納
  • Data Analytics:SQLなど使い慣れた言語でストリーミングデータを抽出・検索

重要: GlueとEMRは「バッチ処理」、Kinesisは「ストリーミング処理」という点が決定的な違いになる。


2. GlueとEMRの使い分け

GlueもEMRも裏側はSparkで動いており、技術的にはGlueは「EMRの上澄みを使いやすくラップしたもの」に近い。

# ❌ とりあえずEMRでクラスタを立てて簡単なETLをやる
# → クラスタ設定・スケーリング・監視まで自前で管理する必要があり、シンプルな変換処理には過剰

# ✅ 定型的な変換・整形はGlueに任せる
# → クローラーでスキーマ自動検出、サーバーレスでコード量も少ない

自由度と運用の手間はトレードオフの関係にある。

  • 面倒なことを任せたい・定型処理で十分 → Glue
  • 細かく制御したい・複雑な処理をしたい → EMR

Athenaとの関係

Athenaは「S3上のデータにSQLを投げるだけの検索サービス」で、ETLエンジンでも分散処理エンジンでもない。Glueのクローラーがテーブル定義を作り、Athenaがそのテーブルに対してSQLを実行する、という役割分担になる。


3. Apache Sparkとは

大量データを複数サーバーに分散させ、同時並行で処理する分散処理エンジン。1台のマシンで処理しきれないデータを、複数マシンに分割して処理し、結果を集約する仕組みを提供する。

特徴

  • メモリ上で処理するため高速(後述のHadoopのMapReduceと比較して顕著)
  • Spark SQL、MLlib(機械学習)、Spark Streaming、グラフ処理など幅広い用途に対応
  • Python(PySpark)、Scala、Java、SQLなど複数言語に対応

EMR・GlueはいずれもSparkを「裏側のエンジン」として使っている。EMRはそのエンジンを積んだ車体をフルカスタムできるサービス、Glueは同じエンジンを積んだ乗りやすい車、というイメージになる。


4. HadoopとSparkの違い

項目 Hadoop(MapReduce) Spark
処理方式 ディスクベース メモリベース
速度 遅い(都度ディスクI/O発生) 速い(メモリ上で処理を完結)
得意分野 障害耐性重視、超大規模データ 反復計算(機械学習・グラフ処理など)
弱点 反復処理で極端に遅くなる メモリに乗らないデータではI/Oが増え恩恵が薄れる
# Hadoop(MapReduce)のイメージ
# 処理のたびにメモ帳に書いて引き出しにしまう → 確実だが出し入れが遅い

# Sparkのイメージ
# 机の上に広げっぱなしで作業する → 速いが机(メモリ)が狭いと厳しい

現在はSparkが主流だが、Hadoopの構成要素であるHDFS(分散ファイルシステム)は今でもデータ保存の土台として広く使われている。「HDFSに保存し、処理エンジンとしてSparkを使う」という組み合わせが実態に近く、EMRはこの構成をそのまま実現できる。


5. ユースケースで見る使い分け

AWS Glue

  • データレイクの整備(複数システムのログ・トランザクションデータをS3に集約し、Athena/Redshift Spectrumから検索可能にする)
  • DWHへのロード(業務DB→S3→Glue ETL→Redshiftという定型パイプライン)
  • 定期バッチのスキーマ変換(CSV→Parquet変換、カラム名の正規化、重複排除など)

「毎日決まった時間に、決まった変換をする」定型ジョブが中心になる。

Amazon EMR

  • 大規模な機械学習の前処理(数百GB〜TB級のログから特徴量を作る、Sparkの分散処理をカスタムしたい場合)
  • Hiveでの大規模データ分析基盤(既存のHadoopエコシステムの資産を引き継いで動かす場合)
  • 一時的な大規模バッチ処理(月末の全量再計算など、必要な時だけクラスタを立てて処理後に落とす)
  • Presto/Trinoでのアドホック分析(複雑なクエリを自由に投げたい環境)

Glueでは対応しきれない「自由度・カスタマイズ性」が必要な場面で使われる。

Amazon Kinesis

  • リアルタイムダッシュボード(ECサイトのアクセス状況、ゲームのプレイログを秒単位で可視化)
  • 不正検知・異常検知(決済や不正ログインのリアルタイム検知)
  • IoTセンサーデータの収集(工場設備や車両からのセンサーデータをFirehose経由でS3やRedshiftに流す)
  • ログの集約パイプライン(アプリケーションログをKinesisで受けてFirehose経由でS3/OpenSearch Serviceに格納し、監視基盤として使う)

「今すぐ反応したい」「常時発生するイベントを取りこぼしたくない」場面で使われる。

Spark(EMR/Glue問わず)

  • 大規模データの集計・変換(ETLの中核処理)
  • 機械学習パイプライン(MLlibでの学習・推論)
  • グラフ分析(つながり分析、レコメンド)
  • ストリーミング処理(Structured Streamingでの準リアルタイム処理)

まとめ

  • Glue:溜まったデータの定型ETL。サーバーレスでクローラーによるスキーマ自動検出が強み
  • EMR:溜まったデータに対する自由度の高い分散処理。クラスタ設定を自分で制御する分、運用コストが増える
  • Kinesis:流れ続けるデータのリアルタイム処理。Data Streams / Firehose / Data Analyticsで役割が分かれる
  • Spark:GlueやEMRの裏側で動く分散処理エンジン本体。メモリベースで高速
  • Hadoop(MapReduce)はディスクベースで低速だが、HDFSは今も分散ファイルシステムとして現役

長期アクセスキーを捨てる:GitHub Actions × AWS OIDC認証の全体像

概要

GitHub ActionsからAWSを操作する際、長期的なアクセスキーをSecretsに保存する方式には漏洩リスクがある。OIDC(OpenID Connect)を使うと、実行のたびに短命な一時クレデンシャルを発行する方式に切り替えられる。この記事ではGitHub ActionsがAWSリソースを操作するまでの認証・認可の流れを、JWTの構造から一時クレデンシャル発行、実際のAPI呼び出しまで順に整理する。


1. 従来方式の課題

従来はAWSのアクセスキーID・シークレットアクセスキーをGitHubのSecretsにそのまま登録し、ワークフロー内で読み込んでAWSにログインする方式が一般的だった。

重要: この方式の鍵には有効期限がない、またはあっても長期間のため、漏洩すると第三者に長期間使われ続けるリスクがある。

OIDCを使う方式では、鍵を保存せず、実行時に都度AWSから一時クレデンシャルを発行してもらう。


2. OIDCプロバイダーとは何か

OIDCプロバイダーとは「証明書(トークン)を発行する主体」のこと。今回のケースではGitHub自身がOIDCプロバイダーであり、実体は token.actions.githubusercontent.com という発行窓口。

AWS側でterraformで作成する aws_iam_openid_connect_provider は、GitHubというOIDCプロバイダーを「信頼リストに追加する」ための登録情報であり、プロバイダー本体ではない。

用語 実体 場所
OIDCプロバイダー GitHubの証明書発行窓口 GitHub側
aws_iam_openid_connect_provider GitHubを信頼するという登録簿 AWS側

3. IAMロールの2種類のポリシー

IAMロールには役割の異なる2種類のポリシーがアタッチされる。

  • 信頼ポリシー(trust policy / assume_role_policy):誰がこのロールを使えるかを決める
  • 許可ポリシー(permission policy):ロールを使った後、何をしていいかを決める

今回の「GitHubのvisk-org/sample-appリポジトリ、production環境だけ許可する」という条件は信頼ポリシー側に書かれ、「ECRへのpush」「ECSサービス更新」といった内容は許可ポリシー側に書かれる。


4. JWTの構造

GitHubが発行するトークンはJWT(JSON Web Token)形式で、次の3部構成になっている。

ヘッダー.本文.署名
  • ヘッダー・本文:Base64エンコードされているだけで暗号化ではない。鍵なしで誰でもデコードできる。本文には sub(subject)や aud(audience)といった情報がそのまま入っている
  • 署名:GitHubの秘密鍵を使って本文から計算した値。検証には公開鍵が必要
sub: repo:visk-org/sample-app:environment:production
aud: sts.amazonaws.com

sub は「これは誰の証明書か」、aud は「この証明書は誰宛てに発行されたか」を示す。

重要: 本文部分の可読性(Base64)と署名部分の検証(公開鍵暗号)は別の仕組み。「JWT全体が暗号化されている」わけではない。


5. 実行時のフロー

sequenceDiagram
    participant Runner as GitHub Actions<br>ランナー
    participant GH as GitHub<br>OIDCプロバイダー
    participant STS as AWS STS
    participant IAM as IAMロール<br>信頼/許可ポリシー
    participant AWS as AWSリソース<br>ECR/ECS等

    Runner->>GH: トークンをリクエスト
    GH-->>Runner: JWTを発行(署名済み・短命)

    Runner->>STS: AssumeRoleWithWebIdentity
    STS->>GH: 公開鍵を取得(jwks)
    GH-->>STS: 公開鍵を返却
    STS->>STS: 署名検証
    STS->>IAM: OIDCプロバイダーの信頼リスト確認
    STS->>IAM: 信頼ポリシーの条件チェック

    alt 条件を満たす
        STS-->>Runner: 一時クレデンシャル発行
        Runner->>AWS: 一時クレデンシャルでAPI呼び出し
        AWS->>IAM: 許可ポリシーで権限評価
        IAM-->>AWS: 許可/拒否
        AWS-->>Runner: 実行結果を返却
    else 条件を満たさない
        STS-->>Runner: AssumeRoleWithWebIdentity失敗
    end

GitHub Actionsのワークフローが動くと、以下の順に処理が進む。

  1. ランナーがGitHubにトークンをリクエストaws-actions/configure-aws-credentials などのアクションが動くと、実行コンテキスト(リポジトリ・environment等)の情報を要求する
  2. GitHubがJWTを署名して発行:数分で失効する短命トークン
  3. ランナーがAWS STSに AssumeRoleWithWebIdentity を呼ぶ:JWTを証拠にロールのAssumeを要求する
  4. STSがJWTを検証
    • 署名検証:GitHubの公開鍵置き場(token.actions.githubusercontent.com/.well-known/jwks)から公開鍵を取得し、署名を数学的に検証
    • 信頼関係の検証:そのOIDCプロバイダーがAWS側で信頼リストに登録済みか確認
  5. IAMロールの信頼ポリシーの条件チェック:JWT本文の audsts.amazonaws.com と完全一致するか(StringEquals)、subrepo:{repo}:environment:{environment} のパターンに一致するか(StringLike)を確認
  6. 条件を満たせば一時クレデンシャルを発行:アクセスキー・シークレットキー・セッショントークンが発行される
  7. 一時クレデンシャルでAWS APIを呼ぶ:ECRへのpushやECSのサービス更新が実際に行われる。ここで許可されるかどうかは、ロールにアタッチされた許可ポリシーの範囲で決まる

信頼ポリシーの条件部分はterraformで次のようなイメージになる。

{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::xxxx:oidc-provider/token.actions.githubusercontent.com"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
    },
    "StringLike": {
      "token.actions.githubusercontent.com:sub": "repo:visk-org/sample-app:environment:production"
    }
  }
}

6. 認証と認可の切り分け

流れ全体を「認証(Authentication)」と「認可(Authorization)」で切り分けると次のようになる。

ステップ 種別 内容
GitHubがJWT発行 認証の材料作り GitHubが「このジョブは本物」と自己証明
STSがJWT検証 認証 AWSが発行元の正当性を検証(OIDCプロバイダー登録が効く)
sub/aud条件チェック 認可の入口 このロールをAssumeできるのはこのrepo/environmentだけ、という制限
許可ポリシー評価 認可 実際のAWS操作(ECR/ECS等)ができるかの制限

「OIDCプロバイダーの登録」は発行元GitHubを信頼するための設定、「IAMロールの信頼ポリシー」はどのリポジトリ・environmentからのリクエストだけ許可するかの認可条件、という役割分担になっている。


まとめ

  • 長期アクセスキーをSecretsに保存する方式は漏洩時のリスクが大きく、OIDCによる一時クレデンシャル方式へ切り替えるとこのリスクを避けられる
  • OIDCプロバイダーはGitHub自身が持つ証明書発行機能を指し、AWS側の aws_iam_openid_connect_provider はそれを信頼リストに登録する情報
  • IAMロールには「誰が使えるか」を決める信頼ポリシーと「何をしていいか」を決める許可ポリシーの2種類がある
  • JWTは本文(Base64エンコードのみ)と署名(公開鍵暗号で検証)からなり、sub/aud は本文にそのまま書かれている
  • 実行時の流れは「JWT発行 → STSへ提出 → 署名検証 → 信頼関係確認 → sub/aud条件チェック → 一時クレデンシャル発行 → 許可ポリシー評価」の順で進む

GCP マネージドサービス全体像:AWS エンジニア向けガイド

概要

GCP はサーバレス中心の構成を実現するため、複数のマネージドサービスを組み合わせる設計になっている。AWS の経験があれば、ほぼ同じ概念で理解できる。本記事では、GCP の主要マネージドサービス 8 つを AWS との対応関係で整理し、それぞれの役割と繋がり方を体系化する。


背景:なぜ複数のマネージドサービスが必要か

GCP でサーバレス構成を組む際、単一のサービスでは対応できない多様なユースケースが存在する。

  • 定期実行が必要 → Cloud Scheduler
  • 重い処理を非同期で実行 → Batch
  • 軽い関数を素早く実行 → Cloud Run / Functions
  • 大規模データ分析 → BigQuery
  • 非同期メッセージング → Pub/Sub
  • イベント駆動 → Eventarc
  • 認証情報管理 → Secret Manager

これらを組み合わせることで、「フルマネージド・スケーラブル・保守が少ない」インフラが実現される。


サービス一覧と AWS 対応表

GCP 役割 AWS 対応
Workflow オーケストレーション(全体の指揮者) Step Functions
Batch 長時間の重い処理実行 AWS Batch
Cloud Run / Functions 軽い関数実行(コンテナ / 言語限定) Fargate / Lambda
BigQuery データウェアハウス・大規模分析 Redshift / Athena
Cloud Storage(GCS) オブジェクトストレージ S3
Pub/Sub メッセージング・イベント駆動 SNS / SQS
Cloud Scheduler / Eventarc スケジュール実行・イベント起動 EventBridge
Secret Manager 認証情報管理 Secrets Manager

各サービスの詳細

1. Workflow(オーケストレーション)

何をするのか

複数の GCP サービスを順番に、もしくは条件分岐させながら実行するオーケストレーションサービス。

Step Functions と同じ概念で、YAML で定義する。

steps:
  - step1:
      call: googleapis.bigquery.v2.jobs.query
      # BigQuery クエリを実行
  - step2:
      call: googleapis.batch.v1.projects.locations.jobs.create
      # Batch ジョブを投げる
  - parallel_step:
      parallel:
        branches:
          - branch1: # 並列実行その 1
              steps: [...]
          - branch2: # 並列実行その 2
              steps: [...]

特徴

  • 直列・並列・条件分岐が可能
  • GCP サービスへのネイティブな API コール
  • ステップ間でデータをパスできる
  • リトライ・エラーハンドリングも YAML で定義

メリット・制約

項目 説明
メリット Step Functions と同じく、複雑なフロー制御をコードではなく宣言的に定義できる
制約 YAML の学習コスト(Step Functions は JSON)

2. Batch(重い処理実行)

何をするのか

長時間かかる重い処理をサーバレスで実行するサービス。

  • 最大実行時間:数時間~数日(事実上無制限)
  • Docker コンテナで処理を定義
  • GCP が自動にスケーリング

Cloud Run / Functions との違い

項目 Cloud Run / Functions Batch
実行時間 最大 60 分 数時間~数日
起動時間 秒単位 数分かかる場合あり
用途 API リクエスト、軽い処理 画像バッチ処理、データ変換、ML 学習
スケーリング リクエストベース バッチジョブベース

具体例

1000 個の動画ファイルをすべて圧縮してストレージに保存する場合、Batch に「このコンテナイメージを 1000 ファイルに対して並列実行」と指示すれば、GCP が自動に 100 並列・200 並列などでスケーリング。

Workflow との繋がり

Workflow の YAML でこう書く:

- submit_batch:
    call: googleapis.batch.v1.projects.locations.jobs.create
    args:
      # Batch ジョブを投げる
    result: job_result
- wait_batch:
    call: googleapis.batch.v1.projects.locations.jobs.get
    # 完了を待つ

3. Cloud Run / Cloud Functions(軽い関数実行)

何をするのか

軽い・短命な処理をサーバレスで素早く実行するサービス。

Cloud Functions vs Cloud Run

項目 Cloud Functions Cloud Run
形式 関数(Python・Node.js・Go など) Docker コンテナ
制限 言語限定 好きな言語・ライブラリ OK
用途 シンプルなロジック API サーバ、複雑な処理
実行時間 最大 60 分 最大 60 分

イメージ

  • Cloud Functions = AWS Lambda(言語限定、シンプル)
  • Cloud Run = Lambda + コンテナの自由度(Fargate に近いが、「リクエスト来たら起動 → 処理 → 終了」という短命さを保つ)

具体例

  • Cloud Functions:Pub/Sub メッセージを受け取って、DB に 1 行挿入
  • Cloud Run:HTTP リクエストを受けて、複雑なビジネスロジックを実行して JSON を返す

AWS でのポジション

AWS では「直接対応するサービスがない」。強いて言うなら: - Lambda の「シンプルさ」 - Fargate の「コンテナの自由度」 - 両者の「リクエスト駆動」を混ぜたもの


4. BigQuery(データウェアハウス・分析)

何をするのか

大規模なデータを保存して、SQL で素早く分析するデータウェアハウス。

特徴

  • TB 単位のデータを数秒で検索・分析
  • SQL(標準 SQL)で複雑な JOIN・GROUP BY が可能
  • 自動スケーリング(データ量が増えても同じ速度)
  • 他の GCP サービスとの統合が簡単

AWS との比較

項目 BigQuery AWS
DWH 本格的 BigQuery Redshift
データレイク検索 BigQuery(+ GCS) Athena(+ S3)

Athena との違い

  • Athena:S3 上のファイル(CSV・Parquet)に直接 SQL を投げる
  • BigQuery:テーブル形式でデータを管理して、そこから SQL で分析

BigQuery のデータは物理的には GCS に保存されているが、ユーザーからは「BigQuery のテーブル」として見える(GCS と一体化)。

課金ポイント

  • 読み取り課金:クエリ実行時に「読んだバイト数」で課金
  • ストレージ課金:保存してるデータ量で課金
  • 実行時間では課金されない(AWS Redshift との大きな違い)

5. Cloud Storage(GCS)

何をするのか

ファイルを保存するオブジェクトストレージ。

AWS 対応

GCP AWS
Cloud Storage S3

ほぼ同じサービス。役割も機能も大して違わない。

あなたの構成での役割

  • BigQuery の出力(Parquet・CSV で保存)
  • クエリファイル・設定ファイルの置き場
  • アプリケーションログ・実行ログの保存

つまり「ダンプデータ置き場」「ログ置き場」。

課金ポイント

  • ストレージ容量
  • ネットワーク(アウトバウンド)

S3 と同じロジック。


6. Pub/Sub(メッセージング)

何をするのか

非同期メッセージング。Publisher(送信者)が Topic にメッセージを投げて、Subscriber(購読者)が受け取る。

イメージ:「掲示板」

複数の Publisher が Topic に「メッセージ」を投げる
  ↓
Topic を購読している複数の Subscriber が全員そのメッセージを受け取る

つまり「複数の送信元・複数の受信者が同じ Topic を使う」。

具体例

Topic: "batch-completed"

Publisher 1: Batch ジョブ A が終了 → メッセージ投げる
Publisher 2: Batch ジョブ B が終了 → メッセージ投げる

Subscriber 1: Cloud Run が受け取って Slack に通知
Subscriber 2: Cloud Run が受け取ってログに記録
Subscriber 3: BigQuery に結果を流す

すべての Subscriber が同じメッセージを受け取る。

AWS との比較

GCP AWS
Pub/Sub SNS / SQS(を混ぜたような感じ)

あなたの構成での役割

Pub/Sub … メッセージング。Slack 通知の起点にもなる。

各種処理が終わったら Pub/Sub にメッセージを投げて、Pub/Sub から Cloud Run / Functions が受け取って Slack に通知する。


7. Cloud Scheduler / Eventarc(実行トリガー)

Cloud Scheduler:定時実行

毎日特定の時間に何かを実行するサービス。

schedule: "0 8 * * *"  # 毎日 8:00

cron 形式で定義。

Eventarc:イベント駆動

GCP サービスのイベントを検知して、自動に次の処理を起動するサービス。

GCS に ファイルがアップロードされた
  → Eventarc が「アップロードイベント」を検知
  → Cloud Run を自動に起動

AWS との比較

GCP AWS
Cloud Scheduler / Eventarc EventBridge

EventBridge の「スケジュール機能」と「イベント機能」を別サービスに分けている。

あなたの構成での用途

  • Cloud Scheduler:「毎日 8:00 に Workflow を起動」
  • Eventarc:「ファイルアップロード時に Workflow を起動」など

8. Secret Manager(認証情報管理)

何をするのか

API キー・パスワード・トークンなどの認証情報を安全に暗号化して保管するサービス。

Twitter・Instagram・Threads などのプラットフォーム API キー
  ↓
Secret Manager に暗号化して保管
  ↓
Cloud Run が「このキーを取得」と問い合わせ
  ↓
Cloud Run が API キーを使ってプラットフォームを操作

特徴

  • 暗号化保管
  • アクセス制御(IAM)
  • キーローテーション対応

AWS との比較

GCP AWS
Secret Manager Secrets Manager

ほぼ同じサービス。

あなたの構成での役割

Secret Manager … 各 PF の認証情報を保管(キーローテーションあり)。

複数のプラットフォーム API キーを一元管理して、定期的にローテーション。


全体フロー:サービス間の繋がり方

典型的なサーバレスパイプラインのイメージ:

1. Cloud Scheduler / Eventarc
   ↓ トリガー
2. Workflow
   ↓ 指揮
3. BigQuery(データ取得)
   ↓ 
4. Cloud Run / Functions(前処理・フィルタリング)
   ↓
5. Batch(重い処理を並列実行)
   ↓
6. GCS(処理結果を保存)
   ↓
7. Pub/Sub(完了メッセージを投げる)
   ↓
8. Cloud Run(メッセージ受信 → Slack 通知)

Secret Manager は全体を通じて「各種認証情報を提供する」という役割。


実務への応用

Platform Engineer / SRE の観点

GCP のマネージドサービスは AWS よりも「概念が統一されている」という特徴がある。

  • Workflow = Step Functions(直感的)
  • Batch = AWS Batch(容量を意識しない)
  • Cloud Run = Lambda + コンテナの柔軟性

という組み合わせで、AWS よりもシンプルに「書く → デプロイ → スケール」のサイクルが回る。

転職時に「GCP の経験はありますか?」と聞かれたときは「AWS と同じ概念で、サービス名が違うだけ」という説明が有効。

学習ロードマップ

  1. まず Workflow と Step Functions を比較して理解する
  2. 次に「重い処理」「軽い処理」のサービス選別を学ぶ
  3. BigQuery と Athena の差を実務で体感する
  4. Pub/Sub と SNS/SQS の非同期メッセージングを深掘りする

まとめ

  • GCP のマネージドサービスは、AWS と 1:1 で対応する(ほぼ)
  • Workflow = Step Functions:複数サービスのオーケストレーション
  • Batch = AWS Batch:長時間の重い処理
  • Cloud Run / Functions = Lambda / Fargate:軽い関数実行
  • BigQuery = Redshift / Athena:データ分析
  • GCS = S3:オブジェクトストレージ
  • Pub/Sub = SNS / SQS:メッセージング
  • Cloud Scheduler / Eventarc = EventBridge:スケジュール・イベント駆動
  • Secret Manager = Secrets Manager:認証情報管理
  • AWS 経験があれば、GCP は「概念は同じ、呼び方と細かい設定が違う」くらいで理解できる

AWS ALB で HTTPS を構築する:DNS・CNAME・ACM 証明書の仕組み

概要

AWS で ALB(Application Load Balancer)を HTTPS 対応させるには、DNS・CNAME・ACM 証明書の3つが連携する。これらは独立した概念ではなく、「ドメイン所有権を確認 → 証明書を発行 → 暗号化通信を実現」という流れの中で機能する。本記事では、これら3つの要素がどう繋がるのか、実装レベルで整理していく。


1. DNS とは何か

DNS(Domain Name System)は「ドメイン名を管理するサービス」。

要素 説明
DNS ドメイン名を管理するシステム全体
DNS サーバー ドメイン情報を保持するサーバー(例:お名前.com)
DNS 名 AWS が ALB に付ける通称名(例:alb-123abc.ap-northeast-1.elb.amazonaws.com)

ユーザーがブラウザで example.com にアクセスすると、DNS が「このドメインはどこにあるか」という質問に答える。お名前.com の DNS サーバーが「ALB の DNS 名」を返すことで、ユーザーのリクエストが ALB に到達する仕組みになっている。


2. CNAME レコードとは何か

CNAME(Canonical Name)は DNS に書く「1行の指示」で、「このドメイン名をあのドメイン名に繋ぐ」という意味を持つ。

CNAME の2つの役割

役割1:ALB への接続を指定

名前:api
タイプ:CNAME
値:alb-123abc.ap-northeast-1.elb.amazonaws.com

この設定により、api.example.com にアクセスしたユーザーは ALB に到達する。

役割2:ACM の所有権確認(検証用)

名前:_acm-validations.api
タイプ:CNAME
値:_abc123xyz.acm-validations.aws.

AWS(ACM)がドメイン所有権を確認する際、この検証用 CNAME をお名前.com に追加させる。CNAME が追加できた = DNS を管理している人 = 本当の所有者という論理で検証する仕組みになっている。

CNAME と CNAME レコードの違い

用語 説明
CNAME AWS が生成する「2つの値(名前と指し先)」
CNAME レコード それをお名前.com の DNS に登録した「状態」

AWS が CNAME を生成しても、お名前.com に登録されるまでは実態がない。お名前.com で実際に登録することで「CNAME レコード」として有効化され、お名前.com の DNS サーバーに記録される仕組みになっている。


3. ACM 証明書とは何か

ACM(AWS Certificate Manager)証明書は「このドメインは本物で、安全です」という AWS の公式な証。HTTPS 通信を暗号化し、ユーザーのブラウザが「本物のサイト」と判断するために必要になる。

証明書の発行フロー

ステップ1:あなたが Terraform で ACM にリクエスト
  「api.example.com の証明書をください」

ステップ2:AWS(ACM)が CNAME を自動生成
  左:_acm-validations.api.example.com.
  右:_abc123xyz.acm-validations.aws.

ステップ3:あなたが お名前.com に CNAME を手動登録

ステップ4:AWS が お名前.com の DNS を問い合わせ
  「_acm-validations.api.example.com ありますか?」

ステップ5:お名前.com の DNS サーバーが応答
  「あります」

ステップ6:AWS が確認完了
  「このドメインは本当の所有者のものだ」
  → 証明書を発行

重要: 証明書発行は AWS が「設定」として記録するもの。実際にユーザーがアクセスした時に、ALB が証明書をユーザーのブラウザに提示して初めて機能する。


4. 3つの要素が連携する流れ

DNS・CNAME・ACM 証明書は独立した3つのレイヤーで機能していく。

【設定フェーズ】Terraform で準備

1. ACM に証明書をリクエスト(Terraform)
2. AWS が CNAME を生成
3. CNAME を お名前.com に登録(手動)
4. AWS が所有権を確認して証明書を発行
5. ALB に証明書を紐付け(Terraform)

この段階では、DNS・CNAME・証明書はすべて「準備状態」。実際のユーザーアクセスはまだ起きていない状況になっている。

【通信フェーズ】実際のユーザーアクセス

ユーザー:ブラウザで https://api.example.com にアクセス

  ↓

DNS の役割:
  お名前.com の DNS サーバーが回答
  「api.example.com は alb-123abc.ap-northeast-1.elb.amazonaws.com だよ」

  ↓

ALB の役割:
  リクエストを受け取って、証明書を提示

  ↓

ユーザーのブラウザ:
  「この証明書は AWS(ACM)が署名してる」
  「ドメイン名が一致してる」
  「有効期限は切れていない」
  → 本物のサイトと判断

  ↓

ACM 証明書の役割:
  ブラウザと ALB 間の通信を暗号化

  ↓

通信を継続:
  ALB がパスを見て、ECS など実サーバーに振り分け

5. Prod での実装フロー

Prod 環境で HTTPS 対応させる場合の具体的な流れ。

フェーズ1:準備(手動)

1. Slack でお名前.com のログイン情報をもらう
2. お名前.com でサブドメイン api.example.com を追加

フェーズ2:Terraform で基盤構築

1. セキュリティグループにポート 443(HTTPS)のインバウンド許可を追加
2. ALB に https リスナーを追加
3. Terraform の variables に以下を定義:
   subdomain_name = "api"
   root_domain    = "example.com"

フェーズ3:Terraform で ACM 証明書をリクエスト

cd aws/prd/acm-dns
terragrunt apply

AWS(ACM)が CNAME を自動生成する。AWS コンソールで確認可能。

フェーズ4:CNAME を お名前.com に手動登録

1. AWS コンソール(ACM 証明書詳細ページ)で CNAME をコピー
2. お名前.com にログイン
3. DNS 管理画面で CNAME レコードを追加
   - 名前:_acm-validations.api
   - タイプ:CNAME
   - 値:(AWS がくれた値をペースト)
4. 保存

フェーズ5:証明書検証待機

AWS が お名前.com の DNS を確認
↓
お名前.com に CNAME が登録されていることを検出
↓
所有権確認完了
↓
ACM が自動で証明書を発行(5-10分程度)

AWS コンソール(ACM 画面)で「発行済み」ステータスを確認したら、証明書 ARN をメモ。

例:arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxx

フェーズ6:ALB に証明書を紐付け(Terraform)

# aws/prd/alb/terragrunt.hcl に追加
inputs = {
  acm_certificate_arn = "arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxx"
}

Terraform を実行。

cd aws/prd/alb
terragrunt apply

ALB が HTTPS:443 で動作開始。

フェーズ7:動作確認

curl -v https://api.example.com/health

ステータスコード 200 が返れば HTTPS 通信が成功している。


6. お名前.com と Route 53 の選択肢

HTTPS 対応時、DNS 管理を「お名前.com で続ける」か「Route 53 に移管する」かという選択肢がある。

観点 お名前.com Route 53
CNAME 設定 手動(毎回お名前.com の画面で操作) Terraform で自動化可能
複数環境管理 dev/stg/prd で手作業が増える 同じ Terraform コードで管理
コスト DNS 管理料金:無料 Hosted Zone:$0.50/月 + クエリ費用
学習コスト 低い(GUI 操作) 高い(Terraform / Infrastructure as Code)

Platform Engineer として複数環境を管理する場合は、Route 53 への一元化を検討する価値がある。一方、単一ドメインで手作業に問題がなければ、お名前.com で十分な環境もある。

Prod 構築時に「どちらで進めるか」を意識的に選択するのが重要。


まとめ

  • DNS はドメイン名を管理するシステム。お名前.com の DNS サーバーが「api.example.com → ALB の DNS 名」という対応表を保持する
  • CNAME は DNS に書く「1行の指示」で、「このドメインをあのドメインに繋ぐ」という意味。検証用 CNAME をお名前.com に登録することで、所有権確認が成立する
  • ACM 証明書は AWS が発行する「本物のサイト証明」で、HTTPS 通信の暗号化を担当。実際のユーザーアクセス時に初めて機能する
  • 設定フェーズ(Terraform + 手動)と通信フェーズ(ユーザーアクセス)は分かれている
  • Prod 実装では「CNAME を お名前.com に手動登録する」が唯一の手動作業。それ以外は Terraform で自動化可能
  • DNS 管理を お名前.com で続けるか Route 53 に移管するかは、運用ポリシーに応じて選択

BigQuery入門 — サーバーレスDWHの概念からPub/Subまで

概要

GCPのBigQueryをAWSエンジニア視点で整理する。DWHとは何か・AWSサービスとの対比・クエリの書き方・コスト設計・Pub/Subとの連携まで一気通貫でまとめる。


1. BigQueryとは

フルマネージドなサーバーレスDWH(データウェアハウス)。クラスタのプロビジョニングは不要で、SQLを投げるだけでテラバイト〜ペタバイト規模のデータを高速に分析できる。

主な特徴:

特徴 説明
サーバーレス インフラ管理不要。クエリを投げるだけ
カラム型ストレージ Dremel技術ベース。数十億行を数秒で処理
ストレージ/コンピュート分離 保存と処理が独立。柔軟にスケール
標準SQL対応 ANSI SQLほぼ完全サポート
BigQuery ML SQLだけでMLモデルのトレーニング・推論が可能

2. 用語整理

ANSI SQLとは

ANSIが標準化したSQLの仕様。MySQLやPostgreSQLで書いてきたSQLがほぼそのまま使える、という意味。BigQueryはこれに準拠しているため、方言を覚え直す必要がほとんどない。

ウィンドウ関数(ROW_NUMBER(), LAG() など)もそのまま動く。

DWH(データウェアハウス)とは

分析専用に設計された大規模データの保管・集計基盤。日常業務のトランザクションDBとは役割が根本的に異なる。

トランザクションDB(OLTP) DWH(OLAP)
代表例 MySQL / PostgreSQL / Aurora BigQuery / Redshift / Snowflake
操作 1件ずつ書く・読む・更新する 大量データをまとめて集計する
最適化対象 レイテンシ スループット
テーブル設計 正規化 非正規化・カラム型
ユースケース ECサイトの注文処理 月次売上集計・行動分析

本番DBに直接アドホッククエリを投げると負荷がかかる。DWHにデータを集めて分析するのが基本設計。


3. AWSとの比較

AWSエンジニアにとって一番わかりやすい対比がこれ。

BigQuery Athena Redshift
カテゴリ サーバーレスDWH S3クエリエンジン フルDWH
管理コスト ほぼゼロ ほぼゼロ クラスタ管理が必要
データ保存先 BigQueryストレージ(独自) S3 Redshiftストレージ or S3
クエリ速度 ペタバイト級でも高速 S3依存でやや遅い 高速(設計次第)
料金モデル スキャン量課金 or フラット スキャン量課金 クラスタ時間課金
ML統合 BigQuery ML SageMakerと連携 Redshift ML

使い分けの目安:

  • Athena → S3のデータをとりあえずSQLで叩きたい、コスト最小化したいとき
  • Redshift → AWSネイティブで本格DWHを構築したいとき
  • BigQuery → 管理ゼロ・スケール無限でアナリティクスに集中したいとき

Redshiftのクラスタとは

Redshiftは複数サーバー(ノード)を束ねたクラスタ構成でDWHを動かす。

┌─────────────────────────────┐
│         Redshift クラスタ    │
│                             │
│  [リーダーノード]            │  ← SQLの受付・クエリ計画
│       ↓                     │
│  [コンピュートノード × N台]  │  ← データ保存・並列処理
└─────────────────────────────┘

ノード数・ノードタイプを自分で選んで起動する必要があり、起動中は使っていなくても課金される。BigQueryはこの管理が完全に不要。


4. クエリの書き方

基本クエリ

-- プロジェクト.データセット.テーブル の形式でアクセス
SELECT
  user_id,
  COUNT(*) AS event_count,
  DATE(event_timestamp) AS event_date
FROM `my-project.analytics.events`
WHERE DATE(event_timestamp) = '2026-05-22'
GROUP BY user_id, event_date
ORDER BY event_count DESC
LIMIT 100;

パーティションテーブル(コスト削減に必須)

-- ❌ パーティションなし → フルスキャンで高コスト
SELECT * FROM `my-project.analytics.events`;

-- ✅ パーティション分割テーブルを作る
CREATE TABLE `my-project.analytics.events`
PARTITION BY DATE(event_timestamp)
AS SELECT * FROM source_table;

-- ✅ クエリ時にパーティションフィルタを使う → スキャン量が激減
SELECT * FROM `my-project.analytics.events`
WHERE DATE(event_timestamp) BETWEEN '2026-05-01' AND '2026-05-22';

パーティション指定があると、Googleがスキャン範囲を絞ってくれる。コスト直結なので必須の設計。


5. コスト構造

オンデマンド(デフォルト)

項目 料金
クエリ(スキャン量) $6.25 / TB
ストレージ(アクティブ) $0.023 / GB / 月
ストレージ(長期:90日無更新) $0.016 / GB / 月

最初の1TB/月は無料。スキャン量がそのままコストになるため、テーブル設計でいかに絞るかが鍵。

フラットレート(Capacity Commitment)

スロット数(処理能力)を月次・年次で予約契約。大量クエリを日常的に実行する場合はこちらが安い。最近はBigQuery Editions(Standard / Enterprise / Enterprise Plus)という新モデルに移行中。

コスト最適化のポイント

  • パーティション分割 → 日付等でスキャン範囲を絞る
  • クラスタリング → 特定カラムでソートしてスキャン量削減
  • SELECT * を避ける → カラム型なので必要カラムだけ取得
  • マテリアライズドビュー → 集計済み結果をキャッシュ

6. Pub/Subとの連携

Pub/Sub(パブリッシュ/サブスクライブ)とは

メッセージを「送る側」と「受け取る側」を非同期で繋ぐメッセージングサービス。

Publisher(送信側)  →  Topic  →  Subscription A  →  Subscriber A
                              →  Subscription B  →  Subscriber B
  • Publisher → メッセージを送る側。誰が受け取るか知らなくていい
  • Topic → メッセージの種類・チャンネル
  • Subscription → 各Subscriberの郵便受け(Queue的にメッセージを溜める)
  • Subscriber → 自分のペースで処理する

QueueとPub/Subの違い

Queue(SQS) Pub/Sub(SNS)
受信者 1つ(競合消費) 複数(全員に届く)
用途 タスクを1回だけ処理させる イベントを複数システムに通知

AWSで言うと、Pub/Sub ≒ SNS + SQS がひとつになったもの

郵便局の例え

差出人(Publisher)
  → 郵便局(Topic)
      └─ 郵便受けA(Subscription A)→ 住人A(Subscriber A)
      └─ 郵便受けB(Subscription B)→ 住人B(Subscriber B)

ただし普通の郵便と違い、全Subscriberに同じメッセージが届く(回覧板に近い)。

BigQueryとのリアルタイムパイプライン

アプリ → Pub/Sub → Dataflow(整形) → BigQuery

1. アプリがユーザー行動イベントをPub/Subに投げる(リアルタイム)
2. Dataflowがメッセージを受け取り整形
3. BigQueryにストリーミングINSERT

バッチ(夜間にGCSからまとめてロード)より鮮度の高いデータが必要なときの典型構成。


まとめ

  • BigQuery はサーバーレスDWH。インフラ管理ゼロで大規模データ分析ができる
  • DWH は本番DBとは別に作る分析専用基盤。OLTPとOLAPは役割が根本的に違う
  • AWSとの対比 ではRedshift(クラスタ管理あり)より管理コストが低く、Athenaよりクエリ性能が高い
  • コストの肝 はスキャン量。パーティション・クラスタリング・SELECT * 回避が必須
  • Pub/Sub はSNS+SQSが一体化したメッセージングサービス。リアルタイムパイプラインでBigQueryとよく組み合わせる

アプリケーション脆弱性対応の自動化を整理する(4)運用統合とKPI設計

はじめに

前回はアプリケーション脆弱性対応の優先度付けと修正フェーズを扱った。RBVMの考え方、Auto-mergeの設計、デグレリスクへの多層防御まで踏み込んだ。

ここまでで「個別フェーズで何をするか」は揃った。第4回はそれらを横断的に支える基盤の話になる。検出・優先度付け・修正がそれぞれ動いていても、結果がバラバラの場所に保存され、ツールごとに違うフォーマットで出力され、誰がどう使うかも整理されていないと、運用は破綻する。

主なテーマは2つ。

  • 運用統合:SARIF / SBOM / Policy as Code / SOAR でツール間を繋ぐ
  • KPI設計:MTTR / Backlog / Auto-merge率 で改善ループを回す

用語の確認は第1回を参照。


本記事の前提:規模感

本記事で扱う運用統合とKPI設計は、ある程度の規模を持つ組織を想定している。具体的にはエンジニア100人以上、リポジトリ100以上の規模で必要になる仕組み。

エンジニア数別に必要な対応レベルを整理すると以下のようになる。

エンジニア数 リポジトリ数の目安 推奨アプローチ
〜30人 〜30 人の連携で十分。誰かが気づいて Slackで周知 → 各チーム確認、で回る
30〜100人 30〜100 ハイブリッド。SBOM導入とSlack通知自動化で価値が出始める
100人以上 100+ 自動化が主。本記事の内容がほぼ全部必要になる

「人の連携で対応している組織がどこから自動化に投資すべきか」の判断基準は、Log4Shell のような大規模CVEが出たときの影響範囲特定にかかる時間。これが1日を超えるなら、SBOM導入の費用対効果が出始める閾値と考えてよい。

従業員数ではなくエンジニア数で判断するのがポイント。営業や経理の人数はリポジトリ管理には影響しない。


SARIF:スキャン結果の標準フォーマット

SARIF(Static Analysis Results Interchange Format) は、セキュリティスキャン結果を標準化するためのJSONベースのフォーマット。OASISという標準化団体が策定している。

なぜ必要か

検出フェーズで複数ツールを使うと、出力フォーマットがバラバラになる。

  • Trivy → 独自のJSON
  • Semgrep → 独自のJSON
  • Snyk → 独自のJSON
  • ZAP → 独自のXML / JSON

これを各ツールごとに別のダッシュボードで見ていると、「全体として今いくつ脆弱性があるのか」が分からなくなる。

主要なセキュリティツールはSARIF出力に対応しており、GitHubのCode ScanningもSARIFを入力として受け取る。

[Trivy] ─┐
[Semgrep] ─┼─ SARIF ─→ [GitHub Code Scanning] / [中央ダッシュボード]
[Snyk] ─┤
[CodeQL] ─┘

これで「どのツールで検出されたか」を意識せずに「今このリポジトリの脆弱性は何件、どの深刻度か」を一元的に把握できる。

SARIFの中身

{
  "runs": [{
    "tool": {
      "driver": { "name": "trivy", "version": "0.50.0" }
    },
    "results": [{
      "ruleId": "CVE-2024-12345",
      "level": "error",
      "message": { "text": "lodash <4.17.21 has prototype pollution" },
      "locations": [{
        "physicalLocation": {
          "artifactLocation": { "uri": "package-lock.json" }
        }
      }]
    }]
  }]
}

ツールに依存しない構造になっているのが特徴。


SBOM:ソフトウェア部品表

SBOM(Software Bill of Materials) は、アプリケーションが使っているコンポーネント(依存ライブラリ、OSパッケージ等)の完全なリスト。

なぜ必要か

新しいCVEが公開されたとき、最も重要な問いはこれ。

「このCVEは、うちの会社のどのサービスに影響するのか?」

これに即答できないと、対応のスタートラインに立てない。SBOMがあると以下のフローが可能になる。

1. CVE公開(例:log4j 2.14のRCE)
2. SBOM横断検索:「log4j 2.14 を使っているサービス一覧」
3. ヒットしたサービスのオーナーに自動通知
4. 該当しないサービスは対応不要と即判断

これを SBOM なしでやろうとすると、各リポジトリの package.json を1つずつ grep する羽目になる。Log4Shell(2021年)のとき、各社で「うちの製品で log4j 使ってる?」を即答できず初動が48時間遅れた事例が多数あった。この経験から SBOM 保管が標準プラクティスになった。

標準フォーマット

フォーマット 提供元 特徴
CycloneDX OWASP セキュリティ志向、依存関係グラフが明示的
SPDX Linux Foundation ライセンス管理志向、法務系で多い

すべてのビルドで SBOM を生成し、アーティファクトとともに保管するのが推奨される。

生成・運用ツール

  • Syft:Anchore製、コンテナイメージ・ソースコードからSBOM生成
  • Trivy:SBOM生成にも対応
  • CycloneDX CLI:公式ツール
  • GitHub Dependency Graph:GitHubがリポジトリから自動生成

署名と検証

サプライチェーン攻撃(誰かが偽のアーティファクトをすり替える攻撃)への対策として、SBOM やアーティファクトに暗号署名を付けるのが推奨される。

  • Sigstore / Cosign:アーティファクトへの署名
  • in-toto:ビルドプロセスの provenance(来歴)証明

これらを使うと「このSBOMが間違いなく自社のCIで作られたものである」を暗号的に証明できる。


Policy as Code:ルールをコードで管理する

Policy as Code は、セキュリティルール・運用ルールをコードとして書き、Git管理し、CIで強制するアプローチ。

何をコード化するか

  • ゲートポリシー:「Critical脆弱性があれば main へのマージをブロック」
  • SLA:「Criticalは24時間以内、Highは7日以内」
  • 資産メタデータ:「このサービスはinternet-facing、データ機密度はhigh」
  • 自動マージルール:「dev依存のpatchは自動マージ、本番依存のmajorは人間レビュー」

なぜコード化するか

ドキュメント(Confluence等)に書かれたルールは:

  • 更新されない
  • 自動システムから参照できない
  • 例外運用が増えると形骸化する

コードに書かれたルールは:

  • Git履歴で変更追跡できる
  • PRレビューを通じて変更にガバナンスが効く
  • CIから直接参照できるので、ルールと実態が乖離しない

代表的なツール

  • OPA(Open Policy Agent):汎用ポリシーエンジン、Rego言語で書く
  • Conftest:OPAをCIで使いやすくしたもの
  • Sentinel:HashiCorp製、Terraform Cloudと統合
  • Checkov:IaC向けポリシーエンジン

OPA によるゲート設定の例

package security.gate

deny[msg] {
  vuln := input.vulnerabilities[_]
  vuln.severity == "CRITICAL"
  vuln.cisa_kev == true
  msg := sprintf("CRITICAL CVE in KEV: %s. Merge blocked.", [vuln.id])
}

deny[msg] {
  vuln := input.vulnerabilities[_]
  vuln.cvss >= 9.0
  vuln.reachable == true
  msg := sprintf("Reachable critical vulnerability: %s", [vuln.id])
}

このポリシーをCIで評価し、deny がヒットするとマージがブロックされる。


ソフトゲート vs ハードゲート

ゲートの設計には温度感がある。全部ハードゲートにすると開発が止まり、全部ソフトゲートにすると形骸化する。

ゲートの種類 動作 使いどころ
ソフトゲート 警告を出すが開発を止めない PR時のSAST findings、minor脆弱性
ハードゲート マージ・デプロイをブロック Critical CVE + KEV、シークレット混入

よくある失敗パターン

全部ハードゲート化

「セキュリティ重視」の名目で全findingsをブロックすると、開発者がツール自体を回避し始める(コミットメッセージで [skip ci] を多用、ローカルでスキャンを無効化)。結果として誰も使わなくなる。

全部ソフトゲート化

警告だけ出して止めないと、警告は背景ノイズになる。Critical脆弱性の警告も見過ごされる。

現実解:少数の明確なルールから始める

「CVSS >= 9 かつ既知の悪用がある場合はブロック」のような少数の明確で自動化可能なルールから始める。False Positive 率が下がってから少しずつハードゲートを増やす。前回 Bitbucket + pnpm の文脈で扱った「まずソフトゲートで導入し、運用を見て段階的にハードゲートに昇格」と同じ思想。


SOAR:通知とチケット連携の自動化

検出 → 優先度付け → ゲート判定まで自動化したら、最後は「誰に通知して、誰がチケット起票するか」の自動化。

SOAR(Security Orchestration, Automation, and Response) は、これらのワークフロー自動化プラットフォームの総称。

自動化フローの典型例

脆弱性検出
  ↓
優先度付けロジック実行(CVSS + KEV + Reachability)
  ↓
P0と判定
  ↓
[SOAR Playbook 起動]
  ├─ Jiraチケット自動作成(オーナーをアサイン)
  ├─ Slackで該当チームに通知
  ├─ PagerDutyでオンコール起動(営業時間外なら)
  ├─ Confluenceにインシデント記録
  └─ SLA タイマー開始(24時間)
  ↓
24時間経過で未対応
  ↓
エスカレーション(マネージャに通知)

代表的なツール

  • PagerDuty:オンコール管理 + 通知
  • Jira Service Management:チケット起票
  • Splunk SOAR(旧 Phantom):本格的SOARプラットフォーム
  • Tines:ノーコードSOAR
  • GitHub Actions / Bitbucket Pipelines:軽量な統合なら十分実用

軽量版の実装例

業務レベルで本格SOARは大袈裟なケースも多い。Bitbucket Pipelines + Slack Webhook で十分作れる。

- step:
    name: Notify on critical vulnerability
    script:
      - CRITICAL_COUNT=$(jq '.metadata.vulnerabilities.critical' audit.json)
      - |
        if [ "$CRITICAL_COUNT" -gt 0 ]; then
          curl -X POST $SLACK_WEBHOOK \
            -d "{\"text\": \"🚨 Critical vulnerability in PR #${BITBUCKET_PR_ID}\"}"
        fi

統合された全体アーキテクチャ

ここまでの1〜4回の内容を統合した全体像。

[1. 資産インベントリ]
  ├─ リポジトリ一覧(YAML/JSON)
  ├─ SBOM(CycloneDX)
  └─ 資産メタデータ(criticality, owner, sla)
       ↓
[2. 検出]
  ├─ SAST、DAST、SCA、IaC、Secret スキャン
  └─ 結果をSARIFに正規化
       ↓
[3. 優先度付け]
  ├─ CVSS + EPSS + KEV
  ├─ Reachability 分析
  └─ 資産メタデータと突合
       ↓
[4. 修正]
  ├─ Dependabot/Renovateで自動PR
  ├─ Auto-mergeポリシー
  └─ AI修正生成(Claude Code Security 等)
       ↓
[5. 運用統合]
  ├─ Policy as Code(OPA等)でゲート
  ├─ SOAR でチケット起票・通知
  └─ メトリクスダッシュボード
       ↓
[6. 継続改善ループ]

各レイヤーが疎結合(SARIFやSBOMという標準フォーマットで繋がっている)になっているので、1つのツールを別のツールに差し替えても全体は動き続ける。これがベンダロックインを避けつつ、組織の成熟度に応じて段階的に高度化できる設計のキモ。


KPI 設計

ここまでの基盤を作っても、「うまくいっているか」を判断する基準がないと改善が回らない。投資対効果も説明できない。

なぜ KPI が重要か

KPI設計には2つの目的がある。

目的1:自動化の効果測定

「Dependabotを入れた」「Renovateに移行した」だけでは効果は分からない。MTTR が短縮されたか、Backlog が減ったか、を数字で示せて初めて投資が正当化できる。

目的2:ボトルネックの特定

「検出は多いけど修正が追いつかない」のか「そもそも検出漏れがある」のかで、次に投資すべき場所が変わる。フェーズ別にKPIを置くと、どこに問題があるかが見える化される。

量ではなく結果を測定する」がポイント。検出件数を増やすのは簡単だが、それは結果ではない。

主要 KPI

速度系

指標 何を測るか 目安
MTTR(Critical) Critical脆弱性の平均修正時間 7日以内
MTTR(High) High脆弱性の平均修正時間 30日以内
MTTR(Medium) Medium脆弱性の平均修正時間 90日以内
MTTD 脆弱性公開から検出までの時間 24時間以内

MTTR が自動化の効果が最も鮮明に出る指標。手動運用だと Critical で30日以上かかることが多いが、自動化が機能すれば7日以内に収まる。

量系

指標 何を測るか
Backlog Trend 未対応脆弱性の総数の増減傾向
新規検出数 / 修正数 「入ってくる量 vs 出ていく量」のバランス
Critical Backlog 未対応Critical脆弱性の数(最重要)

Backlog が増えているか、横ばいか、減っているかは、運用が機能しているかの一番分かりやすい判断材料。

自動化率系

指標 何を測るか 目安
Auto-merge率 依存関係更新PRのうち自動マージされた割合 70%以上
修正率(PRチェック経由) PR時に修正された割合 vs 後追いで対応された割合 高いほどよい
False Positive率 「修正不要」と判定された割合 30%以下

PRチェック経由で修正される割合が高いと、「開発者が文脈を覚えているうちに直している」状態。後追いだと「別のエンジニアが、忘れた頃に直す」状態で、コストが何倍にもなる。

カバレッジ系

指標 何を測るか 目安
リポジトリカバレッジ率 スキャン対象になっているリポジトリ比率 100%
SBOMカバレッジ率 SBOMが生成されているサービス比率 100%

カバレッジは「やっていない領域がある = 攻撃者の入口がある」ということなので、100%が目標になる。

KPI の階層化

すべての指標を全員が見るわけではない。役割別に見るべき指標が違う

役割 主に見る指標
開発者 自リポジトリの未対応脆弱性、自PRの検出
セキュリティチーム リポジトリ別MTTR、ツール別False Positive率
マネージャー / 経営層 全社MTTR推移、ROI、コンプライアンス準拠率

経営層向けは「CVE 100件が50件になりました」では響かない。「インシデント発生確率が30%低下、推定回避損失○億円」のビジネス言語に翻訳する必要がある。

段階的な目標値の引き上げ

最初から「Critical 7日以内」を目標にすると失敗する。段階的にハードルを上げるのが現実的。

フェーズ1(導入直後): Critical 30日以内、High 90日以内
フェーズ2(半年後): Critical 14日以内、High 60日以内
フェーズ3(1年後): Critical 7日以内、High 30日以内
フェーズ4(成熟期): Critical 3日以内、High 14日以内

組織の成熟度を見ながらSLAを引き上げていく。初期から厳しい目標を立てると、未達続きでチームが疲弊する。

Goodhart's Law への注意

"When a measure becomes a target, it ceases to be a good measure" (指標が目標になると、それは良い指標ではなくなる)

例:MTTR を縮めることだけが評価されると、「適当に Close するインセンティブ」が生まれる。「修正したことにする」「False Positiveとしてマークする」が増え、実態は悪化していくのに数字だけ良くなる。

これを防ぐには:

  • 複数指標を組み合わせて見る(MTTRだけでなくインシデント数も追う)
  • 抜き打ちで監査(Closeされた findings の品質チェック)
  • インセンティブ設計(チームの評価とMTTRを直結させすぎない)

継続改善ループ

KPIは見るだけでは意味がない。改善サイクルに組み込んで初めて機能する。月次レビューの典型的アジェンダ:

  1. 前月のKPI確認:目標達成状況
  2. 悪化した指標の根本原因分析:なぜMTTRが伸びたか?
  3. トップN件のドリルダウン:MTTRが長かったCritical脆弱性を個別に振り返る
  4. 次月のアクション:新しいゲートルール追加、ツール導入、運用フロー改善
  5. 目標値の見直し:成熟度に応じてSLAを段階的に厳しくする

次回予告

第5回(最終回)は実装と段階設計を扱う。

  • 最小構成で押さえるべき3要素
  • 5段階の具体的な拡張ロードマップ
  • Bitbucket Pipelines + pnpm の実装コード例
  • non-blocking SCA の設計(既存PRと脆弱性修正を分離する運用)
  • 通知設計の落とし穴:二重通知を避ける

これまでの理論を、現場で実際に動かすところまで持っていく回になる。


まとめ

  • 運用統合の鍵は標準フォーマット(SARIF / SBOM)による疎結合化
  • SBOM があれば新規CVE公開時の影響範囲を即座に特定できる。Log4Shell の教訓
  • Policy as Code でセキュリティルールを Git 管理する
  • ソフトゲートとハードゲートを使い分ける。少数の明確なルールから始める
  • SOAR でチケット起票・通知を自動化。軽量版は Bitbucket Pipelines + Slack で十分
  • KPI は MTTR / Backlog / Auto-merge率を中心に、量ではなく結果を測定する
  • 役割別に見るべき指標を分ける。経営層にはビジネス言語に翻訳する
  • Goodhart's Law に注意。指標が目標になると劣化する
  • 段階的に目標値を引き上げる。最初から厳しいSLAは未達続きで疲弊する

参考文献