数学 - TECH PLAY - TECH PLAY

TECH PLAY

数学

イベント

マガジン

技術ブログ

 この記事を読んでいただきありがとうございます。アジャイルグループに所属する、藤井智弘です。  第6〜8回はスクラムのイベントの話でした。今回から、見積りと予測の話に入ります。イベントの回と同じく、「本音の疑問→アンチパターン→勘違いの根っこ→処方」の順で読み解いていきます。 質問 #  ストーリーポイントで見積りをしていますが、上司から「で、それは何人日なの?」と毎回聞かれます。答えに窮して、結局「1ポイント=0.5人日」のような対応表を作ってしまいました。これでは相対見積りの意味がない気がしますし、どうせ換算するなら最初から人日で出せばいいのでは、と思ったりもします。  どう答えるのが正解だったのでしょうか? 回答 #  表現の違いこそあれ、ご質問のテーマ(ポイントと人日)は、ほんとによく訊かれます。3つの観点でこの質問を考えてみましょう。 上司が必要としているのは、本当に「人日」なのか 換算表を作ったのは、そんなに悪いことだったのか 人日で答えないなら、いったい何で答えればいいのか  上から順に答えます。 上司が本当に必要としているのは、たいてい人日ではなく、「いつ終わるの?(あるいは、間に合うの?)」「いくらかかるの?」です。人日はそれらを導き出す手段として訊かれているにすぎません。 換算表を作ったこと自体は責められません(だって訊かれているんですから)。ただし、「1ポイントは〇〇に相当」と固定した瞬間に、いくつかの歯車が——後に述べるように——逆回転を始めます。「最初から人日で」という気持ちはもっともで、見積りの場で全員が人日に直しているなら、そのほうが正直です。ただ、そうなった原因はポイントではなく、換算表のほうにあります。 答えるべきは、ポイントの換算値よりも、 リリース予測とコストの見通し です。実績のベロシティと残りのバックログから「◯月上旬〜◯月下旬に完了見込み」と幅つきで答えられれば、社内の上司のニーズはたいてい満たされます(ただし、発注側の稟議に人日が要る場合は別ですが、それは処方で扱います)。  質問の字面を追わず、その質問の裏にある「相手がほんとに知りたいこと」に答える——これに尽きます。話の軸は二つ、「上司の質問を翻訳すること」と「外側に出す数字と、内側の計画の道具を分けること」です。 「ポイントは人日に換算してはいけません」と教わって、引っかかりませんでしたか? #  研修や現場で、「ストーリーポイントは相対値です」「人日に換算してはいけません」と指導されたことのある方は多いと思います。そのとき、こんな疑問を持ちませんでしたか? 予算も稟議も人日で回っている。換算しなければ、話が通らないではないか 結局、見積りの場で全員が頭の中で人日に直している。だったら最初から人日でよいのでは 相対値のままで、上司は何を判断できるのか  どれも正当な疑問です。先に答えを書くと、 鍵は「1ポイント=◯人日」から導出される数値とベロシティは、似て非なる数字だ という一点にあります。換算値は「この項目は3人日」と、 項目の原価を語る数字 です。ベロシティは「このチームは1スプリントに25ポイント片づく」と、 チームの流量を語る数字 です。計画に要るのは後者で、前者を計画の場に持ち込むと、項目ごとの帳尻合わせが始まります。  予算や稟議が人日で回っているなら、人日につなぐ必要はあります。ただし、つなぐのは項目ではなく合計です。残りの合計ポイントをベロシティで割って期間を出し、期間にチームの月額を掛けて金額を出す。このやり方なら、個々の項目に人日を貼らずに済みます。  上司が判断したいのは、相対値そのものではなく「いつ終わるか」「いくらかかるか」です。上司に渡すべきは、 ポイントという材料ではなく、そこから導いた見通しのほう です。  とはいえ、これだけでは言葉足らずでしょう。先に換算要求がどんな姿になりがちかを並べ、そのうえで一つずつ答えます。 人日換算のアンチパターン #  換算を巡っては、いくつかのアンチパターンがあります。心当たりのあるものがあれば、そこから読んでください。 その1:対応表型 ——最も多い型です。「1ポイント=0.5人日」のような固定の対応表を作り、ポイントを掛け算して人日に直して報告する。冒頭の質問が、まさにこれです。作った直後は平和ですが、見積りの場で全員が人日に逆算を始め、「これはあれの2倍くらい」という比較の速さが失われていきます。 その2:成績表型 ——ポイントが「あの人は今月何ポイント消化した」という個人の生産性指標や、「Aチームは毎スプリント30ポイント、Bチームは15ポイント。Bは生産性が半分か」というチーム間の比較に転用された型です。見積りは自己防衛の道具になり、大きめに見積もる誘惑、簡単な項目を選ぶ誘惑が生まれ、数字は膨らみ、予測の道具としては死にます。測定基準が目標になると、それは良い測定基準ではなくなる——経済学者チャールズ・グッドハートの名にちなむ「グッドハートの法則」として知られる現象です。そもそもポイントはチーム内の相対値であり、チームAの5とチームBの5には何の互換性もありません。換算表は、その事実を覆い隠します。 その3:値切り型 ——発注側や管理部門が、人日に直した数字を見て「この画面が3人日? 前は2人日でできたでしょう」と個々の項目を値切りにかかる型です。ポイントの内訳が人日の内訳に化けた瞬間、見積りは予測ではなく交渉の材料になります。第3回で見た、見積の内訳が保証の文言に流れ込む構図と同じです。 その4:沈黙型 ——「換算しない」という教えを守り、上司の質問に「ポイントは相対値なので人日には直せません」とだけ答えて、会話が終わる型です。正しいことを言っていますが、上司が本当に知りたかった「いつ・いくら」には何も答えていません。教えを守ったつもりで、翻訳を放棄しています。 四つの型に共通する前提 #  四つの型に共通する前提があります。 ポイントは工数の別名だ という前提です。この前提に立つと、換算表を作るのは当然であり、個人やチームの比較に使えるはずであり、内訳を値切れるはずであり、逆に「換算できないなら何の役にも立たない」という結論まで、すべて自然に導かれます。どの型も、この前提を疑わなかった先に現れます。  ここまでを踏まえて、先ほどの疑問に一つずつ答えます。  まず、 換算しなければ話が通らないのではないか 。その通りです。組織の予算策定や稟議、外部への報告は人日・人月で回っており、その言語に接続しないと話は通りません。これは現実で、否定しても始まりません。しかも、ポイントから人日への換算は数学的に可能です。スプリントで使った人日を、そのスプリントで完成したポイントで割れば、「1ポイント=◯人日」は単純な算数で出ます。多くの現場の換算表は、実際にこうして実績から作られています。出どころは正しい。  それでも、換算値とベロシティは同じものではありません。違いは、数字が何を主張しているかにあります。ベロシティは「このチームは1スプリントに◯ポイント片づく」という、チームというシステムの 流量 です。会議も割り込みも待ち時間も含んだ、 事後の観測値であり、その期間内に開発した個々の項目については何も主張しません 。合計についてだけ語ります。換算値は そのベロシティを一つの定数として固定し、チームの人数とスプリント長を加味して、「この項目は3人日」と項目に関連付けた属性値に変えたもの です。つまり、項目の 原価 を語る数字に変わっています。同じ実績から出ていても、片方はチームの流量、片方は項目の原価。ここが分かれ目です。  項目の原価になった瞬間、項目ごとに値切る、3人日の項目に5日かかった人を責める、項目単位で再見積りを求める、が「正当な使い方」になります。見積もる側はそれを見越してポイントを膨らませ、ポイントは成績指標に変わる。先ほどの四つの型は、どれもここから生まれています。 流量のままなら、これらは最初から成り立ちません 。  では、これから作るものの見通しは、どうやって人日・人月の言語に接続するのか。項目に掛けるのではなく、合計で割ります。残りのバックログの合計ポイントを実績のベロシティで割れば、残りのスプリント数が出ます。それが「いつ終わるか」です。そのスプリント数にチームの月額を掛ければ、「いくらかかるか」が出ます。ベロシティは動く観測値なので、幅(20〜30)のまま扱え、予測も幅になり、 ずれは「予測の更新」として次の計画に戻ってきます 。もし換算値を見積りの段階で項目に掛けると、計画はその時点で確定し、 同じずれが「遅れ」として現れます 。  人日・人月の言語と合計値とを接続する形なら、チーム内の見積りはポイントを使うというスタイルを守れたまま、チームの外の人々が期待する見通しを実績値に基づいて提示することができます。実績そのものを問われたときは、もっと単純で、「このチームは、この3ヶ月で人件費◯円を使い、◯◯を届けた」と、項目ごとの換算を経ずに言えます。  もっとも、正直なところ、換算値を毎スプリント毎に見直しをかけ、項目単位に見るのをやめ合計にしか使わないなら、項目に掛けても合計で割っても出てくる数字は同じです。違いは計算結果ではなく、数字の意味と、それが招く運用にあります。この話は、ベロシティを扱う回の末尾で、もう少し丁寧に扱います。  次に、 頭の中で人日に直しているなら、最初から人日でよいのではないか 。その状態なら、確かにそうです。相対見積りの利点は、「これはあれの2倍くらい」という比較が、 絶対値の見積りより速く、チームの合意として出せる ことにあります。見積りの場で全員が人日に逆算しているなら、その利点はもう失われていて、時間で見積もるほうが正直です。ただしそれは、ポイントが無意味だからではなく、対応表がポイントを人日の別名に変えてしまったからです。対応表をやめれば、比較の速さは戻ります。  そして、 相対値のままで、上司は何を判断できるのか 。相対値そのものは判断に使えません。上司が判断に使うのは、相対値とベロシティの実績から導いた「いつ終わるか」「いくらかかるか」です。ポイントは上司に見せる数字ではなく、 その見通しを作るための、チーム内部の材料 です。上司に渡すべきは材料ではなく、見通しのほうです。   「工数の別名」という前提はどこから来るのか 。私たちの多くは、見積りとは工数を積み上げるものだと教わってきました。機能ごとに人日を見積もり、合計して期間と金額を出す。この文化の中でストーリーポイントに出会うと、それを「人日の新しい単位」として理解するのは自然な反応です。怠慢の話ではありません。ただ、単位の置き換えではなく、道具の置き換えだということが、研修ではなかなか伝わりません。  翻って、ストーリーポイントとは何か。道具である前に、何を測った数かを言っておきます。ポイントは、作るものの 大きさ ——量と複雑さと不確実性を合わせたもの——を、そのチームの目盛りで表した相対値です。工数が「人が投入する時間」という投入側の量であるのに対し、大きさは作る対象の側の量です。ただし、大きさそのものに絶対値はないので、「これはあれの2倍くらい」という比で表します。比が使えるのは、同じ二つの項目にかかる工数は作る人によって変わっても(Aさんなら1日と2日、Bさんなら3日と6日)、2倍という比は変わりにくいからです。だから比だけを持つ。そして目盛りはチーム固有なので、チームの外に持ち出すと意味を失います。  そのうえで、本来のストーリーポイントは何のための道具か。アジャイルの計画づくりは、経験主義の上に立っています。見積りを事前に確定させるのではなく、実績を透明にし、予測と実績のずれを検査し、計画を適応させる。ストーリーポイントは、この「実績から予測する」ための道具です。   見積り ——ポイントは、項目同士の大きさの比較を、速くチームの合意として出すためのもの。絶対値ではないので、個人の作業のスピードや日々の割り込みに左右されにくく、合意が壊れにくい。   実績 ——スプリントごとに完成したポイントの合計(ベロシティ)が、チームの実績。これが、ポイントを期間に換える唯一の根拠です。   予測 ——残りのポイントを実績のベロシティで割れば、残りのスプリント数が出る。実績にはばらつきがあるので、予測は幅になります。幅は、実績が貯まるほど頼れるようになり、ばらつきの原因を減らすほど狭まります(ばらつきの扱いは、ベロシティを扱う回で)。  ここまで来れば、対応表型の問題点は明らかです。「1ポイント=0.5人日」が問題なのは、根拠がないからではなく、チームの流量だった実績を項目の原価に変え、しかも根拠だった実績が変わっても表が変わらないからです。変えるべきは、「項目ごとにポイントを人日に直す」から「合計ポイントと実績のベロシティで見通しを出し、チームの外の言語にはその見通しで接続する」へ、です。この置き換えが、本稿の処方のすべての前提です。 処方 #  ここからは具体策ですが、どれも道具にすぎません。見積りと予測の技法は有識者がさまざまに提案してくれていて、どれを選んでもかまいません。もっとも、「換算表を捨てた」と宣言しただけなら、沈黙型と変わりません。試したあとは、上司との会話が「何人日?」から「いつ? いくら?」に変わったかで、効いたかどうかを見てください。 まず、直近数スプリントのベロシティと、残りのポイントを並べる  直す前に、いまの状態を一枚にします。直近5〜8スプリントのベロシティ(最悪値と最良値)と、残りのバックログの合計ポイントを一枚に並べてください。実績が3スプリント分もあれば、粗くても幅は出せます(頼れる幅になるには5スプリントほど要りますが、その話は次回に)。この一枚があるだけで、「何人日?」への答えは「換算できません」ではなく「今の実績だと、◯〜◯スプリントです」に変わります。以降の処方は、この一枚から始まります。 「いつ終わるか」にはリリース予測で答える  直近数スプリントのベロシティの幅と、残りのバックログの合計ポイントから、完了時期を幅で示します。「残220ポイント、ベロシティは20〜30なので、8〜11スプリント、つまり◯月〜◯月です」。単一の日付ではなく幅で答えるのがポイントです。上司が金額で聞くなら、幅をそのまま金額に変えます。「最良と最悪の差は3スプリント、つまりチーム月額の1.5ヶ月分が今の見通しの振れ幅です」。この幅を最良値・最悪値の2本の線でバーンダウンチャート上に表現する「レンジドバーンダウン」(PMI Disciplined Agileで紹介されている、幅つきのバーンダウン表現)というプラクティスもあります。幅の広さ自体が不確実性の正直な表現であり、スプリントを重ねるほど幅は狭まっていきます。この「予測が徐々に精緻になる」体験を上司と共有できると、対話の質が変わります。  そしてこの転換は、答える側だけでは完結しません。開発者は幅と根拠を毎回同じ形式で示し、尋ねる上司の側は「何人日?」の代わりに「いつ? いくら?」で問い直してみる。双方がこの形に慣れたとき、換算表は要らなくなります。 「いくらかかるか」にはチームの運営費で答える  アジャイルなチームのコストは、タスクの積み上げではなく「このチームを何ヶ月走らせるか」で決まります。更改案件のように成果物のまとまりで予算を組む場面の「器」は、第4・5回の方式(ユースケースの本数×規模に深さの初期設定を重ねて量を出し、実測で期間と金額に換える)で作れます。一方、継続的に走るチームの費用の考え方は単純です。チームの月額(人件費+経費)×期間。この計算に人日換算は不要です。むしろ「固定されたチームが期間内に価値を最大化する」というアジャイルの資金モデルを説明する好機です。 それでも換算が要るなら、用途を限定する  稟議や契約でどうしても人日が必要な場面はあります。その場合は、過去の実績(このチームは四半期で人件費◯円を使い、◯◯を届けた)から算出した概算値を、チームの外に出す用途に限って用意し、チーム内の見積り・計画には持ち込まない、と線を引いてください。実績から出した換算値そのものは、この用途に限り、実績が更新されるたびに引き直すなら、問題ありません。「外向けの通貨」と「内側の計画の道具」の分離です。第3回で「予算の器」と「保証の範囲」を切り離す話をしましたが、これも同じ構図です。原則はひとつです。チームの外に出す換算値は実績から、チームの中の計画は予測で。どちらも同じ記録から導き、算出根拠を文書に残す。こうしておけば、外に出す数字と中で使う数字の出どころが違うのではないか、という疑いは生じません。この線引きを上司と合意できるかが勝負どころで、換算表の副作用(インフレ、ノルマ化、チーム間比較)を先に説明しておくと通りやすくなります。 発展: ポイントをやめる道もある  PBIを十分小さく均一に分割できるようになると、ポイントを振らずに「個数」で予測する方法(スループットベースの予測)が成立します。見積りの議論時間はほぼゼロになり、「何人日?」への答えは「毎スプリント平均◯個完成しています」に変わります。成熟したチームの選択肢として、頭の片隅に置いてください。 なぜこの質問は30年繰り返されるのか #  ストーリーポイントは「チーム内部の計画の道具」として生まれましたが、組織の会計・稟議・契約は今も人日/人月の言語で動いています。この2つの言語の境界に立って通訳をする人——本来はPOやマネージャーの仕事です——が明示的に任命されないため、境界の摩擦は毎回、見積もった開発者本人に降ってきます。そして開発者は善意で換算表を作り、数年後に同じ副作用に悩む。この繰り返しです。  背景には、続くコスト削減のプレッシャーもあります。経営層にとってアジャイルが「早くて安い」という文脈で期待されているほど、「で、いくら安くなったのか」を人日で確かめたくなる。換算要求は、その期待の裏返しでもあります。だからこそ、幅つきの完了予測とチーム運営費という「別の答え方」で、期待の中身そのものを組み替えていく価値があるのです。  換算表を求められたら、それは翻訳者が不在だというサインです。表を作る前に、翻訳の仕事を誰が引き受けるかを話し合ってください。確かめるべきは、上司との会話が「何人日?」から「いつ? いくら?」に変わったかどうか、ということです。それがこのチームの見積りが予測の道具として働いているかの計器です。 次回: 「ベロシティが安定しません。計画に使っていいの?」
本ブログは 2026 年 10 月 14 日に公開された AWS Blog “ Penetration testing every deployment with AWS Continuum ” を翻訳したものです。 静的解析 (SAST)、ソフトウェア構成分析 (SCA)、動的スキャナー (DAST) など、CI/CD パイプラインに組み込めるセキュリティツールの多くは、パターンやシグネチャに基づいて 潜在的な 問題にフラグを立てます。フラグが立てられたパターンは調査すべき箇所を示しますが、実際に悪用可能かどうかを確認するのはペネトレーションテストの役割です。従来、この確認は、デプロイのたびではなく、スケジュールに沿って定期的に実施される、パイプラインとは別枠の診断によって行われてきました。そのため、診断と診断の間に行われたデプロイは、確認が済まないまま本番環境に到達していました。 AWS Continuum for penetration testing (旧称 AWS Security Agent) は、AI エージェントを使用して、実行中のアプリケーションに存在する悪用可能な脆弱性を検出し、確認するサービスです。この記事では、このサービスをパイプラインのデプロイ後ゲートとして組み込む方法を説明します。このゲートは、 直前にデプロイした変更に自動的にスコープを限定した ペネトレーションテストを実行し、検出結果の重要度が指定したしきい値以上の場合は、本番環境への昇格をブロックできます。各実行では、アプリケーション全体ではなく、前回ゲートを通過して以降の変更のみをテストするため、デプロイのたびに実行できるほど高速かつ経済的です。この記事では、主要な 4 つの CI/CD プラットフォーム (GitHub Actions、GitLab CI/CD、Bitbucket Pipelines、Azure DevOps Pipelines) に適用できるこのパターンの概要を説明したうえで、GitHub Actions を使用した具体的な例を紹介します。 この記事を読み終えるころには、変更をステージング環境にデプロイし、デプロイした変更に対してスコープを限定したペネトレーションテストを実行して、ゲートを通過した場合にのみ変更を本番環境に昇格させるパイプラインが完成します。 次の図は、エンドツーエンドのフローを示しています。CI/CD パイプラインがステージング環境にデプロイすると、ペネトレーションテストゲートのステップが OpenID Connect (OIDC) を使用して AWS アカウントに対して認証し、Continuum for penetration testing を呼び出します。Continuum for penetration testing は、ステージング環境に対してスコープを限定したテストを実行します。ゲートは結果を待ってパイプラインに報告し、結果に応じて本番環境への昇格をブロックします。テストはすべて AWS アカウント内のサーバー側で実行されるため、CI/CD ランナー上でペネトレーションテストのロジックが実行されることはありません。 図 1: パイプラインゲートのアーキテクチャ: CI/CD パイプラインがステージング環境にデプロイし、ペネトレーションテストゲートが OIDC で認証して Continuum for penetration testing を呼び出します。Continuum for penetration testing は、本番環境への昇格可否を左右するスコープ判定を返します。 変更にスコープを限定することが重要な理由 ゲートをデプロイのたびに実行できるのは、各テストのスコープを直前にデプロイした変更に限定しているためです。Continuum for penetration testing はコミット範囲を決定し ( head はゲートの対象となるコミット、 base はゲートが前回通過を認めたコミットです)、変更された部分のみをテストします。アプリケーション全体ではなく変更をテストすることで、デプロイごとのペネトレーションテストを、四半期ごとの定期作業ではなくパイプラインに組み込めるほど短時間かつ低コストで実行できます。 各実行では、3 つのスコープ判定のいずれかが返されます。具体的には、 in scope (スコープ内: 変更によってアタックサーフェスが変化しており、検出結果がしきい値に基づいて評価されます)、 scoped out (テスト不要: 変更はスコープ内ですが、セキュリティに関係する変更がないため、パイプラインは通過します)、 scope conflict (スコープの競合: 変更が設定済みのスコープ外にあるためテストされておらず、これをブロック対象にするかどうかを選択できます) です。Continuum for penetration testing コンソールでは、各実行の [Scoping] タブに判定結果とコミット範囲が記録されます。そのため、ゲートがブロックした場合は、その理由を正確に確認できます。コミット範囲の計算方法と検証方法の詳しい仕組みについては、「 How the pipeline integration scopes the test 」を参照してください。 ゲートは、パターンマッチではなく、Continuum for penetration testing が悪用可能であると検証した検出結果に基づいてブロックします。そのため、パイプラインが赤 (失敗) になった場合の意味は明確です。つまり、変更に再現可能な脆弱性が存在し、昇格前に修正が必要だということです。 ゲートのセットアップ ゲートのセットアップは 3 つのステップで完了します。ペネトレーションテストの設定、パイプラインが引き受け可能な AWS Identity and Access Management (IAM) ロールの作成、パイプラインへのゲートステップの追加です。 開始する前に、IAM OIDC ID プロバイダーと IAM ロールの両方を作成するアクセス許可を持つ AWS アカウントと、ペネトレーションテストから到達可能なステージング環境を用意してください。 ステップ 1: ペネトレーションテストを設定する 「 Before you start 」の説明に従って、1 回限りのセットアップを完了します。具体的には、ターゲットドメインを検証し、Agent Space でペネトレーションテストを作成し、CI/CD モードを有効にして、リポジトリを接続します。Agent Space ID (as-…) とペネトレーションテスト ID (pt-…) は、ステップ 3 でゲートステップに渡すため、控えておいてください。パイプラインがテストするのは、このペネトレーションテストで設定された対象です。そのため、ゲートがカバーする範囲は、このペネトレーションテストのターゲットとスコープによって決まります。 ステップ 2: IAM ロールを作成する 認証には、保存したキーではなく OIDC フェデレーションを使用します。CI/CD プロバイダーがパイプラインを識別する有効期間の短いトークンを発行し、事前に作成した IAM ロールをパイプラインが引き受ける際に、 AWS Security Token Service (AWS STS) がそのトークンを一時的な認証情報と交換します。長期間有効な AWS アクセスキーを CI/CD 変数として保存する必要がないため、パイプラインから漏えいすることが最も多い認証情報をなくすことができます。 ゲートのセキュリティは、IAM ロールの 2 つのポリシーに依存します。 信頼ポリシー (どのパイプラインがロールを引き受けられるか) と アクセス許可ポリシー (ロールを引き受けた後にパイプラインが実行できる操作) です。正確なポリシー JSON、プロバイダー固有の OIDC URL と audience の値、各 CI/CD プラットフォームの sub クレームの形式については、「 Scope the trust policy to your pipeline 」と「 Grant least-privilege permissions 」のリファレンスに従ってください。 これらのポリシーのスコープを決める際の判断ポイントを次に示します。 最初に判断するのは、 信頼ポリシーのスコープをどこまで厳密にするか です。このパイプラインでデプロイするブランチが 1 つだけであれば、 sub クレームをそのブランチ (例えば、 main ) に固定するのが適切なデフォルトです。複数のブランチや環境で正当にゲートを実行する場合は、プロバイダーのクレームが対応していれば、ブランチではなく環境単位でスコープを限定してください。なお、すべてのプロバイダーがクレームにブランチを含めるわけではない点に注意してください。Bitbucket では、リポジトリ (およびオプションでデプロイ環境) が最も厳密なスコープとなります。まずは実際のデプロイ状況が許す限り狭い範囲から始め、実際のブランチや環境で必要になった場合にのみ範囲を広げてください。また、2026 年 7 月 15 日以降に作成または名前変更された GitHub リポジトリは、数値 ID を含むイミュータブルな sub クレームを発行します。ポリシーを作成する前に、パイプラインが実際に発行する sub を確認してください。 ステップ 3: パイプラインにゲートステップを追加する ステップの考え方はどのプロバイダーでも同じで、異なるのは構文だけです。アップストリームの変更によってパイプラインで実行される内容が変わらないよう、インテグレーションはイミュータブルなバージョン (リリースタグ、コミット SHA、または固定したコンポーネントバージョン) に固定してください。設定の完全なリファレンスとデフォルト値の一覧については、「 Defaults the integration ships with 」を参照してください。 ゲートを本格的に運用する前に、 ドライランモード で一度実行してください。ドライランでは、スコープを限定したペネトレーションテストのジョブを開始することなく、認証が成功すること、リージョンの指定が正しいこと、および対象のリポジトリを正しく特定できることを確認します。検証に失敗した場合は、エラー処理の設定にかかわらずステップが失敗するため、設定ミスにすぐ気付くことができます。 具体的な例: GitHub Actions 次のワークフローは、ゲートを機能させるための 3 つのジョブ構成を示しています。 deploy はステージング環境へのデプロイ、 security-pentest はゲートの実行、 deploy-prod は本番環境への昇格を担当します。 deploy-prod は needs: [security-pentest] を宣言しているため、ゲートが失敗すると GitHub は本番環境へのデプロイをスキップします。 注: チュートリアルでは、ゲートがブロックする実際の検出結果を得るために、意図的に SQL インジェクションの脆弱性を含めたアプリケーションを使用しています。このアプリケーションは、隔離された非本番環境にのみデプロイし、作業が終わったら削除してください。 jobs: deploy: runs-on: ubuntu-latest environment: staging steps: - uses: actions/checkout@v4 with: persist-credentials: false - run: ./deploy.sh staging security-pentest: needs: [deploy] runs-on: ubuntu-latest permissions: id-token: write contents: write actions: read deployments: read steps: - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::111122223333:role/my-pentest-gate-role aws-region: us-west-2 role-duration-seconds: 7200 - uses: aws-actions/aws-continuum-run-pentest@v1 with: agent-space-id: as-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx pentest-id: pt-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx severity-threshold: HIGH on-scope-conflict: block timeout-minutes: "45" deploy-prod: needs: [security-pentest] runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 with: persist-credentials: false - run: ./deploy.sh production アカウント ID、ロール名、リージョン、 as-/pt- 識別子は、実際の値に置き換えてください。 この例では、2 つの点に注意してください。まず、 contents: write アクセス許可によって、ゲートはリポジトリ内に ref として保持している ベースラインマーカーを進める ことができます。書き込みアクセス権がないと、毎回の実行で意図よりも広い範囲がテストされてしまいます。次に、認証情報ステップの role-duration-seconds: 7200 は、ペネトレーションテストの所要時間より長くする必要があります。ロールで許可されている上限を超える期間をリクエストすると、AWS STS は期間を短縮するのではなくリクエストを拒否します。そのため、ロールの最大セッション期間は少なくとも (タイムアウト + 10) x 60 秒に設定してください。途中で認証情報の有効期限が切れると、本来は正常な実行が、あたかもサービス側に問題があるかのように失敗します。さらに、クリーンアップ処理も、取り残されて実行を続けているジョブを停止できなくなります。 4 つのプロバイダーすべてについて、詳細な手順を解説したチュートリアルへのリンクをこの記事の最後に掲載しています。 ゲートのロールアウト: レポート専用モードからブロック運用へ ロールアウトの前に、最も重要なポイントを押さえておきましょう。 ステップが失敗するかどうかは 3 つの独立した設定によって決まり、それぞれ異なる結果を対象としています。 severity-threshold (検出結果の扱い)、 on-scope-conflict (変更がテストされなかった場合の扱い)、 fail-on-infrastructure-error (ジョブを実行できなかった場合の扱い) です。これらは互いに独立しているため、1 つを緩和しても他の設定には影響しません。 多くのチームは、まず レポート専用モード でゲートを導入します。しきい値を NONE に設定すると、テストは実行されて検出結果も報告されますが、パイプラインはブロックされません。1~2 回のリリースで検出内容を確認してから、しきい値を HIGH に変更して、判定を厳しくします。この段階的なロールアウトは妥当な方法ですが、 重要な注意点が 1 つあります。 ゲートを通過した実行は、レポート専用モードでの実行も含めて、ベースラインを進めます。 その実行の範囲に含まれるコミットは通過済みとして記録されるため、後でしきい値を厳しくしても 再テストされません 。例えば、1 か月間レポート専用モードで運用した後に HIGH に切り替えた場合、ゲートが評価するのは最後のレポート専用モードでの実行 以降 のコミットのみです。既にレポート済みの内容まで遡って再チェックすることはありません。 これは設計上の動作です。設定を緩和するということは、その設定で許容される結果を受け入れることを意味します。ただし、以前の実行で通過済みとなった範囲を、より厳しい設定で再評価したい場合は、 head と base のコミット SHA をオーバーライドしてください。具体的には、 base-commit-sha と head-commit-sha を設定します。マーカーの保存場所はプロバイダーによって異なります。プロバイダーごとの対応表については、「 What advances the baseline, and why that matters 」を参照してください。 また、注意すべきデフォルト値も 1 つあります。 fail-on-infrastructure-error のデフォルト値は false (フェイルオープン) です。昇格にセキュリティ承認が必要なパイプラインでは、最初から true に設定してください。 GitLab: コミットした設定はデフォルト値にすぎず、保証ではない GitLab CI/CD では、パイプライン変数が、ジョブ自身の variables: ブロックで設定された値よりも優先されます。つまり、パイプラインを実行できるユーザーであれば誰でも、しきい値を下げる、ドライランを有効にする、エラー処理を緩和するといった変数を指定できてしまいます。その場合、ゲートは .gitlab-ci.yml の記述ではなく、変数の指定どおりに動作します。リリースを止める役割をゲートに任せる前に、プロジェクトの CI/CD 設定で、変数をオーバーライドできるユーザーを制限してください。 ランナー上の認証情報の保護 ステップの実行中は、一時的な認証情報と OIDC トークンを機密情報として扱う必要があります。次の 3 つの対策が重要です。 デバッグと詳細トレースを無効にしておく : 認証情報を扱うステップが対象です。シェルのトレースモード (例えば、GitLab CI の CI_DEBUG_TRACE ) は、コマンド引数を平文でジョブログに出力します。 ソース管理の認証情報をワークスペースに残さない : チェックアウトステップで persist-credentials: false を設定し、後続のステップから読み取れるランナーの .git 設定にトークンが書き込まれないようにします。 信頼できないステップにトークンを公開しない : OIDC トークンのアクセス許可は必要なジョブにのみ付与し、トークンを読み取れるジョブでは信頼できないコード (フォークのビルドなど) を実行しないようにします。 本番環境とマルチアカウント構成への適用 この例では、わかりやすくするために 1 つのアカウントを使用しています。実際には、ステージング環境と本番環境を別々の AWS アカウントに分けることも多いでしょう。その場合も、このパターンは次のように無理なく拡張できます。 ペネトレーションテストゲート用の IAM ロールは、ペネトレーションテストと Agent Space が存在するアカウント (セキュリティアカウント) に作成します。パイプラインは、どのワークロードアカウントにデプロイする場合でも OIDC を介してこのロールを引き受けます。そのため、各アカウントにロールのコピーや長期間有効なキーを置く必要がなく、適切にスコープを設定した 1 つのゲートロールを維持するだけで済みます。 昇格の経路にある本番前の各環境に対してゲートを実行し、その結果に基づいて次のステージへの昇格を制御します。ベースラインはゲートを通過した場合にのみ進むため、デプロイをまたいでもカバレッジが途切れることはありません。 ゲートが実際のリリースを止める役割を担うようになったら、 fail-on-infrastructure-error を true に設定し、パイプライン変数をオーバーライドできるユーザーを制限します。 アップストリームの変更が実行前にレビューされるよう、インテグレーションのバージョンを固定します。 AWS Security Agent に関するより幅広いガイダンス (非本番環境に対するテスト、AI が生成した検出結果の検証、IAM など) については、「 Security best practices for AWS Continuum 」を参照してください。 クリーンアップ ゲートを試すためにいずれかのプロバイダー向けチュートリアルを実施した場合は、そのチュートリアルの「 Clean up 」セクションの手順に従って、作成したリソースをすべて削除してください。対象は、サンプルアプリケーションのステージング環境、IAM ロールと OIDC ID プロバイダー、そして (ウォークスルー専用に作成した場合は) Continuum for penetration testing コンソールのペネトレーションテスト (および専用の Agent Space) です。これらを削除することで、継続的な料金の発生を防ぎ、意図的に脆弱性を含めたサンプルアプリケーションをオフラインにできます。 まとめ ペネトレーションテストのスコープをデプロイした変更に限定することで、四半期ごとの取り組みではなく、デプロイごとのゲートとしてペネトレーションテストを実用的に運用できるようになります。押さえておくべき重要な判断は次のとおりです。 厳格さ : レポート専用モード ( NONE ) から始めます。ただし、ベースラインが進む点に注意し、しきい値を厳しくする際にはマーカーを削除してください。 失敗時の動作 : セキュリティ承認が必要なものについては、 fail-on-infrastructure-error を true に設定します。 信頼のスコープ : sub クレームは、実際のデプロイ状況が許す限り狭く固定します。 ロールの配置場所 : セキュリティアカウントに 1 つのロールを配置し、各ワークロードのパイプラインから OIDC を介して引き受けます。 お使いのプラットフォームでゲートをエンドツーエンドで構築するには、プロバイダーに対応するチュートリアルを参照してください。 Tutorial: Gate a GitHub Actions deployment with a scoped penetration test Tutorial: Gate a GitLab CI/CD deployment with a scoped penetration test Tutorial: Gate a Bitbucket Pipelines deployment with a scoped penetration test Tutorial: Gate an Azure DevOps deployment with a scoped penetration test 概念の説明と完全なリファレンスについては、「 Run penetration tests from your CI/CD pipeline 」を参照してください。 Jigar Bhatt Jigar は AWS Continuum for Penetration Testing のシニアソフトウェアエンジニアです。AI を活用したペネトレーションテスト機能を開発し、お客様がアプリケーション内の悪用可能な脆弱性を検出して修正できるよう支援しています。AI セキュリティの分野に携わる前は、AWS CodeBuild で数年間にわたり開発者ツールの構築に従事していました。インドの BITS Pilani でソフトウェアシステムの工学修士号を取得しています。 Benjamin Li Benjamin は AWS Continuum for Penetration Testing チームのソフトウェアエンジニアで、AI を活用したペネトレーションテスト機能を開発しています。UW で数学の学士号を取得しました。 本ブログは Security Solutions Architect の 中島 章博 が翻訳しました。
はじめまして。東京科学大学理学院数学系修士1年の岩崎丈至です。8月3日から6週間にわたって、LINEスキマニのフロントエンド開発にインターンシップとして参加しました。本稿ではその期間中に行った、メイン...

動画

書籍