Infra flow deck (インフラフローデッキ)
出力: 1つのプライベートHTMLアーティファクト、約8スライド、発表者が説明するミーティング用。 図が意味を伝えます。テキストは最小限です。すべてのブロック、矢印、および主張はコードから得られます。メモリやドキュメントだけからは得られません。
作業順序: ステップ0 セットアップ → ステップ1 調査と台帳の作成 → ステップ2 構築 → ステップ3 0 problem(s) になるまでチェック → ステップ4 公開と報告。
ステップ0 — セットアップ
assets/template.htmlを1つのスクラッチパスにコピーします。すべてのリビジョンと公開で同じパスを使用するため、アーティファクトURLは同じままです。- 台帳 (ステップ1) をその隣の
ledger.txtに配置します。assets/ledger.example.txtにフォーマットが示されています。その中のIDとパスは架空のものです。 - SVGをレイアウトする前に
artifact-diagrammingスキルをロードします。アーティファクトページの契約(テーマトークン、doctypeなし、サイドガター)に従います。
テンプレートは、実際の例が組み込まれた動作するデッキです。スライドエンジン、再生/ステップ/リセットロジック、AWSスタイルのタイル、アカウントとリージョンボックス、点線のセカンダリフロー、ブランドロゴタイルが含まれています。データと座標は変更しますが、エンジンは書き換えないでください。
エンジンの事実:
player(svgId, prefix, steps, idleCaption)は1つのPlayスライドを実行します。プレフィックス''は#play/#back/#next/#reset/#capを使用し、'n'は#nplay/…/#ncap(ネットワーク)、'i'は#iplay/…/#icap(IAM)、'r'は#rplay/…/#rcap(リリース) を使用します。その戻り値をstopsにプッシュします。ステップは{n:[ノードID], a:[矢印ID], c:'キャプション'}です。aは空でもかまいません。player()は自身をwindow.__playersに登録します。scripts/check.pyがそれを読み取るため、その行を維持します。tile(id,cx,cy,color,glyph,label,sub,side):sideは偽値 (ラベルは下)、'l'、't'、または真値 (右) です。下のラベルはその列を通る垂直線をブロックします。脇に移動します。chipRow(cy, items, x0)はロールタイルの隣にグラントチップを描画します。各アイテムは[text, stripe colour, id, deny?]です。各チップは.nodeであるため、Playステップでそれを照らすことができ、deny?は赤いアウトラインを追加します。チップの幅は360pxです。テキストがそれを超えるとチェックに失敗します。- 矢印マーカーは
bodyの上部にある1つの非表示だがレンダリングされたsvgに存在します。スライド内でdefs()を追加しないでください。display:noneのスライド内のマーカーは他のスライドに描画されません。 - ラインクラス:
.arr実線のメインフロー矢印 (すべてがPlayステップに含まれている必要があります)。.arr deny赤い破線、明示的な拒否または許可の境界用。.mon点線のセカンダリフロー。.deployリポジトリ → アカウント。.usesクロスアカウントの使用。パスはM H V Lのみを使用します。 G内のグリフ: コアclock,ecs,lambda,ssm,kms,sqs,rpc,hash,cube,target; ネットワークalb,nat,igw,ep,ec2,db,waf,r53,logs,user; アイデンティティrole,gcp; リリースbranch,cloud; AIbrain; ブランドgithub,vercel,discord,pagerduty,slack。ブランドグリフは白です。タイルにブランドカラーを与えます (github#24292f,vercel#000000,discord#5865F2,pagerduty#06AC38;slackはカラーで、タイルは #ffffff)。ブランドは実際のロゴパスとしてのみ追加します。- ネットワーク、IAM、リリース、マトリックスのスライドは、コメントアウトされたセクションとしてテンプレートに含まれています。セクションのコメントを解除し、
#net、#iam、#relまたは.mxテーブルを入力し、各Playをplayer()で登録します。
ステップ1 — コード内のシステムを調査 (必須、描画前)
デプロイブランチ で調査: プロダクションに適用されるマージ先のブランチ。デフォルトブランチとの比較は、ドリフトを確認するためだけに行います。プロダクションが実行しているものを描画します。リポジトリが大きい場合は、1つのサブエージェントに委任します。ファイルパスを含む事実に基づいたブリーフィングを依頼します。
- リポジトリの
AGENTS.md/READMEファイル、次に IaC (Terraform, CDK など)、サービスコード、コントラクト、デプロイドキュメントを読み取ります。兄弟リポジトリへの参照を追跡します。 - チャートが示すべきものを決定します。 ユーザーが尋ねたメインフローから始めます。それが触れる要素をエンドツーエンドでリストし、オーディエンスがそのフローを理解するために必要なものだけを保持します。要素の一般的な種類:
- ランタイムコンポーネント: タスク、関数、サービス、ワーカー、モニター、ジョブ。
- トリガー: スケジューラー、キュー、イベント、ウェブフック、ユーザー。
- データと設定: パラメータストア、シークレット、データベース、キュー。
- 信頼と署名: キーストア、署名者、境界を越えるロール。
- 外部パーティ: RPC/APIプロバイダー、チャット/アラートツール、チェーン、サードパーティサービス。
- 境界: アカウント、リージョン、ネットワーク、オンチェーン vs オフチェーン。 除外する要素とその理由を述べます。
- 保持する各要素について、チャートに関連するコード内の情報を見つけます。 ブロック、矢印、またはキャプションになる事実のみ: 何がそれを開始するか; 何を読み取るか; 何を書き込むかまたは送信するか; 誰が署名または承認するか、そして何で; 誰が支払うか (手数料、ガス、コスト所有者; 例外を探す); どの境界に存在するか。
- 所有権。 アカウント × リージョンのテーブル、およびリポジトリ → 各リポジトリがどこに何をデプロイするかを作成します。ただし、システムに複数のアカウントまたは複数のリージョンがある場合のみ。 そうでない場合は、このテーブルと所有権スライドをスキップします。
- ネットワーク。 ネットワークIaCを完全に読み取ります: VPCとサブネット (CIDR、AZ数、各リソースが存在するティア)、ルートテーブル、NATとインターネットゲートウェイ、プライベートエンドポイント (プライベートDNSが有効かどうか)、すべてのセキュリティグループとすべてのルール (送信元、ポート、CIDRまたはSG参照)、ロードバランサー (内部またはインターネット向け、リスナーのデフォルトアクション)、CDNオリジンタイプ、サービスディスカバリー、踏み台またはその他の人間のアクセス、フローログ。パブリックサブネットに存在するものをメモします。エンドポイントが存在しないためにNATを通じて出ていくクラウドAPIコールをメモします。結果を描画前に エッジ台帳 として書き出します。セキュリティグループルールペアとロードバランサーターゲットグループごとに1行、
source → destination :port (file:line)の形式で。すべてのルールリソース (AWSの場合:aws_vpc_security_group_ingress_rule、aws_vpc_security_group_egress_rule、ingress/egressブロック、aws_lb_target_group、aws_lb_listener、aws_vpc_endpoint) をルートとそれが呼び出すすべてのモジュールにわたってgrepします。サマリーやメモリから台帳を構築しないでください。 - IAM。 ルートとそのモジュール内のすべてのロール、ポリシー、ポリシーアタッチメント、ポリシードキュメント、信頼ポリシー、許可の境界をgrepします。IAM台帳 をロールごとに1行書き出します:
role | trusted by + すべての条件 | 主な許可 | 明示的な拒否、境界 | file:line。条件はオーディエンスが必要とする事実です: OIDCリポジトリID、ref、環境、ExternalId、SourceAccount、セッション名。次に選択します:- 主要ロール: 境界 (別のアカウント、CI、顧客) を越えるロール、インフラストラクチャを変更できるロール、または顧客データに触れるロール。自分自身のログのみを書き込むロールは除外します (報告します)。
- クリティカルポリシー (0–5): 明示的な拒否ステートメント、許可の境界、
*リソース、iam:PassRole、クロスアカウントsts:AssumeRole。sidを引用します。存在しない場合はそのように述べます。発明しないでください。
- リリースパス。 すべてのCIワークフローを読み取ります: トリガー (
pull_requestまたはpush、ブランチ、paths)、CI環境、想定するロール、フォークPRガード、適用前のビルドステップ、手動ディスパッチ。リリースをマージするためのリポジトリルールを読み取ります。アプリイメージについては、デプロイヤーロール (信頼ref、プッシュおよび更新できるもの) と、IaCがタスク定義の変更を無視するかどうかを読み取ります。このリポジトリ外のアプリリポジトリワークフローは、それらを読み取らない限り未確認です。 - データストア。 顧客データ、監査データ、またはシークレットデータを保持するすべてのストアをリストします: データベース、バケット、IaC状態、ロググループ、シークレットストア。各ストアについて: 暗号化キー (顧客KMS、クラウド管理、ストレージ管理) とTLS、保持 (バックアップ、オブジェクトロック、バージョニング、ライフサイクル、ログ日数、削除保護、シークレット回復ウィンドウ)、可用性 (マルチAZ、別のリージョンまたはアカウントへのコピー)、露出、データを読み取れるユーザー (設定ではなく) 拒否後のCIを含む、監査 (データイベント、データベースログ)。各セルを strong、partial、gap のいずれかで評価し、file:line を付けます。
- ライブ状態。 すべてのコンピュート要素について、その希望する数 (またはレプリカ、またはスケジュール) とその前のゲート (WAFデフォルトアクション、リスナールール、機能フラグ) を読み取ります。ゼロのサービス、またはエッジでブロックされているサービスは停止中です。デッキはそのように述べます。
- パブリック露出。
public_access_block、principalsが"*"のもの、acl、publicly_accessible、associate_public_ip_address、internal = false、オープンなセキュリティグループCIDRをgrepします。すべてのパブリックオブジェクト、エンドポイント、またはアカウント全体の緩和をリストし、それが何を犠牲にするか (たとえば、保護の1つのレイヤーを失うバケット) を記述します。 - 手作業。 トラストアンカー (DNSゾーン、OIDCプロバイダー、状態バケット、接続、アカウント設定) のデータルックアップと、コメントやデプロイガイド内の「console」、「by hand」、「out of band」、「manual apply」をgrepします。1つのリストを保持します: 「IaC外で手作業により作成」。
- コードで確認できないものはすべて未確認としてマークします。ユーザーにそのことを伝えます。事実として描画しないでください。
- ステップの順序はコードから取得します。 ユーザーのリストからは取得しません。コードの順序が異なる場合は、それを使用し、そのように述べます。
次に、エッジ台帳とIAM台帳からチェック用の ledger.txt を書き出します:
arrowId | source -> destination :port | file:line、または - | left out: reason | file:line。
ステップ2 — デッキを構築する
スライド:
- タイトル。
- Play付きメインフロー図。 最初のトリガーから最終的な効果までのブロック。Play、Step Back、Step Next、Resetボタン、およびステップごとに1つのキャプション。
- Play付きネットワークフロー図。 1つのVPC。1回のみ描画 (AZごとには描画しない。ボックスタイトルにAZ数とサブネットCIDRを記述)。バンド: パブリックサブネット、プライベートサブネット。
VPCの外側: CDNまたはクライアント、オペレーター、インターネット。Playステップ (この順序): トラフィックの受信 (CDNオリジン、ロードバランサーSG、タスクSG)、アプリからデータへ (データベースSG、内部ロードバランサー)、トラフィックの送信 (タスク出力、NATへのルート、インターネットゲートウェイ)、分離されたパス (インターネットルートのない関数、エンドポイント)、人間のアクセス (踏み台、ポートフォワード)。
ポートを
.tagテキスト (:443、:5432) として各矢印の横に配置します。フローログやその他のオブザーバーは点線でPlayには含めません。 システムに独自のネットワークがない場合 (たとえば、マネージドサーバーレスのみ)、このスライドをスキップし、報告でそのように述べます。 - Play付き主要IAMロール。 3列: 引き受け可能な主体 (リポジトリとブランチ、クラウドサービス、別のアカウント) → ロールタイル (セキュリティ #DD344C) → 到達するもの (リソースタイルまたはチップ)。信頼条件を
.tagテキストとして信頼矢印に配置します (ref: main、ExternalId)。各クリティカルポリシーを赤い.arr denyラインとして、それがブロックするものまで描画し、sidまたはアクションをタグ (Deny ssm:*) として付けます。ロールグループごとに1つのPlayステップ (CI、デプロイヤー、ランタイム、クロスアカウント)、次にクリティカルポリシーごとに1つのステップ。他のスライドと同じ名前を使用します。 - 変更がプロダクションに到達する方法 (Play付き)。 一番上の行にブランチタイル (ラベルは上)、各ブランチが適用されるアカウントの下に1つのアカウントタイル、アプリリポジトリとデプロイヤーロールは一番下のレーンに。矢印タグはゲートを示します (
PR + plan、merge: apply、push to main)。ステップは実際の順序に従います。人間が手で行うステップを述べます。 - データの所在 (マトリックス)。 HTMLテーブル (
.mx)。SVGではありません。ストアごとに1行、列: 暗号化、保持、可用性、露出、データを読み取れるユーザー、監査。各セルはステータスアイコンとラベル (✓ strong、◐ partial、✕ gap) で始まり、ステータストークン--good/--warn/--critを使用し、シリーズカラーは使用しません。各セルにはソースを示すtitleがあります。フッターはクロスカッティングギャップ (別のリージョンへのコピーがない、自身の拒否を編集できるCI) を記載します。マトリックスは独自のフォントサイズを維持します。スクロールせずにスライドに収まる必要があります。 - アカウント、リージョン、リポジトリ。 静的な図。ステップ1 (所有権) が適用される場合のみ。
- 重要なポイント、3–5行の短い行。ステップ1で検証した主張のみを使用します。該当する場合は1つのネットワークの主張を含めます (たとえば、パブリックサブネットに存在するもの)。「手作業で作成」リストはここまたはアカウントスライドに配置します。
ルール (レビューから学んだもの。すべてに従うこと)
正確性
- コードが持つすべての署名関係を描画します。キーストア (たとえば KMS) が署名を行う場合、それを使用するすべてのコンポーネントは、それへの独自の矢印を取得します。複数の署名者を探します。
- コードで例外を検索するまで、絶対的な主張 (「Xは決して支払わない」、「Yはシークレットを保持しない」、「Zは常に…」) を書かないでください。例外が存在する場合は、それを述べるか、主張を削除します。
- スライド上のすべての安全性または信頼性の特性は、コードまたは設定から得られるものでなければなりません。見つけなかったもっともらしい保証 (クォーラム、リトライ、冗長性) を追加しないでください。
- 保持する各要素について、すべてのトリガーとすべての読み取り/書き込みを描画します。メインパス上のものだけを描画しないでください。
範囲とノイズ
- 同じ図を環境ごと (dev/staging/prod を並べて) にコピーしないでください。1つの環境 (デフォルトではプロダクション) を示し、そのように述べます。
- プロダクションがマルチリージョンの場合は、それを示します。各アカウント内にリージョンボックスを配置し、各リージョンにそのロール (プライマリ、レプリカ、スタンバイ、バックアップ) をラベル付けします。
- メインフロー vs セカンダリフロー。 Playステップは、ユーザーが尋ねたメインフローのみをカバーします。同じインフラストラクチャを共有する他のフロー (監視、アラート、管理、またはバッチジョブ) は点線として描画します。Playステップからは除外し、短い凡例を付けます。
カバレッジ (公開前に毎回チェック)
- 環境をまたがるスライド (リリースパス、アカウント) では、プロダクションだけでなくすべてのルートを読み取ります。すべてのルートが呼び出すモジュール (デプロイヤーロール、パイプライン、信頼) によって作成されたデプロイパスは、すべての環境に到達します。環境ごとに1つの矢印を、各環境が信頼するブランチまたは条件とともに描画します。「プロダクションのみ」には、他のルートがそれを呼び出さないという証拠が必要です。
- ロードバランサー、プロキシ、ゲートウェイ、エンドポイント、またはキューは、矢印の終点ではありません。それとその背後にあるコンポーネントを、2番目のホップを独自の矢印とステップとして描画します。
…
[翻訳のために切り詰め]