セキュアで信頼性のあるシステム構築

―Google SREが考える安全なシステムの設計、実装、保守

[cover photo]
TOPICS
System/Network
発行年月日
PRINT LENGTH
588
ISBN
978-4-8144-0025-6
原書
Building Secure and Reliable Systems
FORMAT
Print PDF EPUB
Ebook
5,280円
Ebookを購入する
Print
5,280円

システムのセキュリティと信頼性は表裏一体です。セキュリティは、プロダクトの品質、パフォーマンス、可用性と密接にかかわるため、スケーラブルなシステムの設計と運用にとって極めて重要です。本書は、GoogleのセキュリティとSREのエキスパートが、根本からセキュアで、スケーラブルかつ信頼性の高いシステムを設計するためのベストプラクティスを紹介します。
既刊書『SRE サイトリライアビリティエンジニアリング』と『サイトリライアビリティワークブック』は、企業がソフトウェアシステムをスムーズに構築、デプロイ、監視、保守するうえで、サービスライフサイクル全体への取り組みが重要な理由とその方法を解説しました。本書では、システムの設計、実装、保守に関する考え方と実践法を解説します。また、ベストプラクティスに取り組むために必要となる組織の文化についても説明します。

目次

本書への推薦の言葉
Royal Hansenによる序文
Michael Wildpanerによる序文
はじめに

第I部 入門資料

1章 セキュリティと信頼性が交わるところ
    1.1 パスワードと電動ドリルについて
    1.2 「信頼性」対「セキュリティ」:設計上の考慮事項
    1.3 機密性、完全性、可用性
        1.3.1 機密性
        1.3.2 完全性
        1.3.3 可用性
    1.4 信頼性とセキュリティ:共通の特徴
        1.4.1 不可視性
        1.4.2 評価
        1.4.3 単純さ
        1.4.4 進化
        1.4.5 弾力性
        1.4.6 設計からプロダクション環境まで
        1.4.7 システムの調査とロギング
        1.4.8 危機対応
        1.4.9 リカバリ
    1.5 まとめ

2章 攻撃者に対する理解
    2.1 攻撃者のモチベーション
    2.2 攻撃者のプロファイル
        2.2.1 ホビイスト
        2.2.2 脆弱性研究者
        2.2.3 政府および法執行機関
        2.2.4 活動家
        2.2.5 犯罪当事者
        2.2.6 自動化と人工知能
        2.2.7 インサイダー
    2.3 攻撃者の手法
        2.3.1 脅威インテリジェンス
        2.3.2 サイバーキルチェーン
        2.3.3 戦術・技術・手順
    2.4 リスク評価の考慮事項
    2.5 まとめ

第II部 システムの設計

3章 ケーススタディ:セーフプロキシ
    3.1 プロダクション環境におけるセーフプロキシ
    3.2 Google Tool Proxy
    3.3 まとめ

4章 設計におけるトレードオフ
    4.1 設計の目的と要件
        4.1.1 機能要件
        4.1.2 非機能要件
        4.1.3 「機能」対「創発特性」
        4.1.4 例:Googleの設計ドキュメント
    4.2 要件のバランスの確保
        4.2.1 例:決済処理
    4.3 緊張の管理と目標の調整
        4.3.1 例:マイクロサービスとGoogleのWebアプリケーションフレームワーク
        4.3.2 創発特性要件の調整
    4.4 初期速度と持続速度
    4.5 まとめ

5章 最小権限を前提とする設計
    5.1 概念と用語
        5.1.1 最小権限
        5.1.2 ゼロトラストネットワーキング
        5.1.3 ゼロタッチ
    5.2 リスクに基づくアクセスの分類
    5.3 ベストプラクティス
        5.3.1 小さく機能的なAPI
        5.3.2 非常ボタン
        5.3.3 監査
        5.3.4 テストと最小権限
        5.3.5 アクセス拒否の診断
        5.3.6 グレースフルな障害と非常ボタンの仕組み
    5.4 導入例:設定の配布
        5.4.1 OpenSSH経由のPOSIX API
        5.4.2 ソフトウェア更新API
        5.4.3 OpenSSHのカスタムForceCommand
        5.4.4 カスタムHTTPレシーバー(サイドカー)
        5.4.5 カスタムHTTPレシーバー(インプロセス)
        5.4.6 トレードオフ
    5.5 認証と認可を判断するためのポリシーフレームワーク
        5.5.1 高度な認可制御の使用
        5.5.2 広く使われている認可フレームワークへの投資
        5.5.3 潜在的な落とし穴の回避
    5.6 高度な制御
        5.6.1 マルチパーティ認可(Multi-Party Authorization = MPA)
        5.6.2 3要素認可(Three-Factor Authorization = 3FA)
        5.6.3 ビジネス上の正当性
        5.6.4 一時アクセス
        5.6.5 プロキシ
    5.7 トレードオフと緊張関係
        5.7.1 セキュリティの複雑さの増大
        5.7.2 コラボレーションと企業文化への影響
        5.7.3 セキュリティに影響を与える高品質のデータとシステム
        5.7.4 ユーザーの生産性への影響
        5.7.5 開発者の複雑さへの影響
    5.8 まとめ

6章 理解しやすさに配慮した設計
    6.1 理解しやすさが重要な理由
        6.1.1 システムの不変条件
        6.1.2 不変条件の分析
        6.1.3 メンタルモデル
    6.2 理解しやすいシステムの設計
        6.2.1 「複雑さ」対「理解しやすさ」
        6.2.2 複雑さの打破
        6.2.3 セキュリティと信頼性の要件に対する責任の一元化
    6.3 システムアーキテクチャ
        6.3.1 理解しやすいインターフェースの仕様
        6.3.2 理解しやすいアイデンティティ、認証、アクセス制御
        6.3.3 セキュリティ境界
    6.4 ソフトウェア設計
        6.4.1 サービス規模の要件に対応するアプリケーションフレームワークの使用
        6.4.2 複雑なデータフローの理解
        6.4.3 APIの使いやすさの考慮
    6.5 まとめ

7章 状況の変化に対応する設計
    7.1 セキュリティ変更の種類
    7.2 変更の設計
    7.3 変更を容易にするアーキテクチャ上の意思決定
        7.3.1 依存関係を常に最新の状態に維持して頻繁に再構築
        7.3.2 テストの自動化を活用して頻繁にリリース
        7.3.3 コンテナの使用
        7.3.4 マイクロサービスの使用
    7.4 異なる変更:異なるスピード、異なるタイムライン
        7.4.1 短期の変更:ゼロデイ脆弱性
        7.4.2 中期の変更:セキュリティ体制の改善
        7.4.3 長期の変更:外部の要求
    7.5 状況の複雑化:計画を変更する場合
    7.6 例:対象範囲の拡大―Heartbleed
    7.7 まとめ

8章 弾力性を担保する設計
    8.1 弾力性を担保する設計原則
    8.2 多層防御
        8.2.1 トロイの木馬
        8.2.2 Google App Engineの分析
    8.3 品質低下の制御
        8.3.1 障害のコストの差別化
        8.3.2 レスポンスの仕組みの導入
        8.3.3 責任ある自動化
    8.4 爆風半径の制御
        8.4.1 ロールの分離
        8.4.2 ロケーションの分離
        8.4.3 時間の分離
    8.5 障害ドメインと冗長性
        8.5.1 障害ドメイン
        8.5.2 コンポーネントの種類
        8.5.3 冗長性の制御
    8.6 継続的な検証
        8.6.1 検証の重点領域
        8.6.2 検証の実際
    8.7 実用的なアドバイス:どこから始めるか
    8.8 まとめ

9章 リカバリを想定した設計
    9.1 リカバリが必要となる状況
        9.1.1 ランダムエラー
        9.1.2 偶発的なエラー
        9.1.3 ソフトウェアのエラー
        9.1.4 悪意のあるアクション
    9.2 リカバリを想定した設計原則
        9.2.1 可能な限り迅速に対応するための設計(ポリシーによる保護)
        9.2.2 外部の時間概念に対する依存度の制限
        9.2.3 セキュリティと信頼性のトレードオフであるロールバック
        9.2.4 明示的な失効の仕組みの使用
        9.2.5 意図した状態の詳細かつ徹底的な把握
        9.2.6 テストと継続的な検証を促進する設計
    9.3 緊急アクセス
        9.3.1 アクセス制御
        9.3.2 通信
        9.3.3 対応者の習慣
    9.4 想定外のメリット
    9.5 まとめ

10章 サービス拒否攻撃の緩和
    10.1 攻撃と防御の戦略
        10.1.1 攻撃側の戦略
        10.1.2 防御側の戦略
    10.2 防御を強化する設計
        10.2.1 防御力の高いアーキテクチャ
        10.2.2 防御力の高いサービス
    10.3 攻撃の緩和
        10.3.1 監視とアラート
        10.3.2 グレースフルデグラデーション
        10.3.3 DoS緩和システム
        10.3.4 戦略的対応
    10.4 自己誘発型攻撃への対処
        10.4.1 ユーザーの行動
        10.4.2 クライアントの再試行動作
    10.5 まとめ

第III部 システムの実装

11章 ケーススタディ:パブリックに信頼できるCAの設計・実装・維持
    11.1 パブリックに信頼できるCAに関する予備知識
    11.2 パブリックに信頼できるCAが必要であった理由
    11.3 構築か購入かの判断
    11.4 設計・実装・維持の考慮事項
        11.4.1 プログラミング言語の選択
        11.4.2 「複雑さ」対「理解しやすさ」
        11.4.3 サードパーティとオープンソースのコンポーネントの保護
        11.4.4 テスト
        11.4.5 CA鍵素材の弾力性
        11.4.6 データの検証
    11.5 まとめ

12章 コードの記述
    12.1 セキュリティと信頼性を強制するフレームワーク
        12.1.1 フレームワークを使用するメリット
        12.1.2 例:RPCバックエンド用のフレームワーク
    12.2 一般的なセキュリティ脆弱性
        12.2.1 SQLインジェクション脆弱性:TrustedSqlString
        12.2.2 XSSの防止:SafeHtml
    12.3 フレームワークの評価と構築に関する教訓
        12.3.1 シンプルで安全な信頼性の高い共通タスク用ライブラリ
        12.3.2 ロールアウト戦略
    12.4 安全で信頼性の高いコードにつながるシンプルさ
        12.4.1 マルチレベルのネスト構造の回避
        12.4.2 YAGNI臭の除去
        12.4.3 技術的負債の返済
        12.4.4 リファクタリング
    12.5 デフォルトのセキュリティと信頼性
        12.5.1 適切なツールの選択
        12.5.2 強い型の使用
        12.5.3 コードのサニタイジング
    12.6 まとめ

13章 コードのテスト
    13.1 ユニットテスト
        13.1.1 効果的なユニットテストの作成
        13.1.2 ユニットテストを作成するタイミング
        13.1.3 ユニットテストがコードに及ぼす影響
    13.2 結合テスト
        13.2.1 効果的な結合テストの作成
    13.3 動的プログラム解析
    13.4 ファズテスト
        13.4.1 ファズエンジンの仕組み
        13.4.2 効果的なファズドライバの作成
        13.4.3 ファザーの例
        13.4.4 継続的なファジング
    13.5 静的プログラム解析
        13.5.1 自動コード検査ツール
        13.5.2 開発者ワークフローへの静的解析の統合
        13.5.3 抽象解釈
        13.5.4 形式手法
    13.6 まとめ

14章 コードのデプロイ
    14.1 概念と用語
    14.2 脅威モデル
    14.3 ベストプラクティス
        14.3.1 コードレビューを義務づける
        14.3.2 自動化を頼りとする
        14.3.3 人間だけでなくアーティファクトを検証する
        14.3.4 設定をコードとして扱う
    14.4 脅威モデルに基づくセキュリティ対策
    14.5 高度な緩和戦略
        14.5.1 バイナリプロベナンス
        14.5.2 プロベナンスベースのデプロイメントポリシー
        14.5.3 検証可能なビルド
        14.5.4 デプロイメントのチョークポイント
        14.5.5 デプロイメント後の検証
    14.6 実践的なアドバイス
        14.6.1 一歩ずつ確実に進む
        14.6.2 対応可能なエラーメッセージを提供する
        14.6.3 曖昧でないプロベナンスを確保する
        14.6.4 曖昧でないポリシーを作成する
        14.6.5 デプロイメント用の非常ボタンを用意する
    14.7 脅威モデルに基づくセキュリティ対策(残りの対応関係)
    14.8 まとめ

15章 システムの調査
    15.1 デバッグから調査まで
        15.1.1 例:一時ファイル
        15.1.2 デバッグ手法
        15.1.3 行き詰まったときの対処方法
        15.1.4 共同デバッグ:教える方法
        15.1.5 セキュリティ調査とデバッグの違い
    15.2 適切で有用なログの収集
        15.2.1 ロギングをイミュータブルにする設計
        15.2.2 プライバシーへの配慮
        15.2.3 保持するセキュリティログの判断
        15.2.4 ロギングのバジェット
    15.3 頑健で安全なデバッグアクセス
        15.3.1 信頼性
        15.3.2 セキュリティ
    15.4 まとめ

第IV部 システムの維持

16章 ディザスタプランニング
    16.1 「ディザスタ」の定義
    16.2 動的なディザスタ対応戦略
    16.3 ディザスタリスク分析
    16.4 インシデント対応チームの設置
        16.4.1 チームメンバーと役割の特定
        16.4.2 チーム憲章の制定
        16.4.3 重大度/優先度モデルの確立
        16.4.4 IRチームを機能させる稼働パラメータの定義
        16.4.5 対応計画の策定
        16.4.6 詳細な手順書の作成
        16.4.7 アクセスと更新の仕組みの確保
    16.5 インシデントに先立つシステムと人間の事前準備
        16.5.1 システムの設定
        16.5.2 訓練
        16.5.3 プロセスと手順
    16.6 システムと対応計画のテスト
        16.6.1 自動化システムの監査
        16.6.2 非侵襲型の机上演習の実施
        16.6.3 プロダクション環境における対応のテスト
        16.6.4 レッドチームによるテスト
        16.6.5 対応の評価
    16.7 Googleの例
        16.7.1 グローバルな影響に基づくテスト
        16.7.2 緊急アクセスをテストするDiR T演習
        16.7.3 業界規模の脆弱性
    16.8 まとめ

17章 危機管理
    17.1 危機か、それとも危機ではないか?
        17.1.1 インシデントのトリアージ
        17.1.2 侵害とバグの違い
    17.2 インシデント対応の指揮
        17.2.1 最初のステップ:パニックを起こさない!
        17.2.2 対応の開始
        17.2.3 インシデント対応チームの確立
        17.2.4 運用セキュリティ
        17.2.5 優れたOpSecよりも優先すべき大義
        17.2.6 調査のプロセス
    17.3 インシデントのコントロールの維持
        17.3.1 インシデント対応の並列化
        17.3.2 引き継ぎ
        17.3.3 士気
    17.4 コミュニケーション
        17.4.1 誤解
        17.4.2 ヘッジング
        17.4.3 ミーティング
        17.4.4 適切な対象者に対する適切な詳細度の情報提供
    17.5 すべてを組み合わせる―危機管理の全体像
        17.5.1 トリアージ
        17.5.2 インシデントの宣言
        17.5.3 コミュニケーションと運用セキュリティ
        17.5.4 インシデント対応の開始
        17.5.5 引き継ぎ
        17.5.6 インシデントの返却
        17.5.7 コミュニケーションと改善の準備
        17.5.8 終結
    17.6 まとめ

18章 リカバリとその後
    18.1 リカバリのロジスティクス
    18.2 リカバリのタイムライン
    18.3 リカバリの計画
        18.3.1 リカバリの対象範囲
        18.3.2 リカバリの考慮事項
        18.3.3 リカバリチェックリスト
    18.4 リカバリの開始
        18.4.1 資産の分離(隔離)
        18.4.2 システムの再構築とソフトウェアのアップグレード
        18.4.3 データのサニタイズ
        18.4.4 リカバリに用いるデータ
        18.4.5 クレデンシャルと機密データのローテーション
    18.5 リカバリ後
        18.5.1 ポストモーテム
    18.6 実施例
        18.6.1 侵害されたクラウドインスタンス
        18.6.2 大規模なフィッシング攻撃
        18.6.3 複雑なリカバリを要する標的型攻撃
    18.7 まとめ

第V部 組織と文化

19章 ケーススタディ:Chromeのセキュリティチーム
    19.1 背景とチームの進化
    19.2 セキュリティはチームの責任
    19.3 ユーザーが安全にWebを閲覧するための支援
    19.4 スピードが重要
    19.5 多層防御を実現する設計
    19.6 透明性の確保とコミュニティへの関与
    19.7 まとめ

20章 役割と責任の理解
    20.1 セキュリティと信頼性に責任を持つのは誰か
        20.1.1 専門家の役割
        20.1.2 セキュリティに関する専門知識の理解
        20.1.3 認定資格と学術機関
    20.2 セキュリティの組織への統合
        20.2.1 セキュリティ専門家とセキュリティチームの配置
        20.2.2 例:Googleにおけるセキュリティの組み込み
        20.2.3 特別なチーム:ブルーチームとレッドチーム
        20.2.4 外部の研究者
    20.3 まとめ

21章 セキュリティと信頼性の文化の構築
    21.1 健全なセキュリティと信頼性の文化の定義
        21.1.1 セキュリティと信頼性がデフォルトの文化
        21.1.2 レビューの文化
        21.1.3 自覚の文化
        21.1.4 イエス(Yes)の文化
        21.1.5 不可避性の文化
        21.1.6 持続可能性の文化
    21.2 優れたプラクティスを通じた文化の変革
        21.2.1 プロジェクトの目標と参加者のインセンティブの整合性
        21.2.2 リスク低減の仕組みによる恐怖心の緩和
        21.2.3 セーフティネットの標準化
        21.2.4 生産性と使いやすさの向上
        21.2.5 オーバーコミュニケーションと透明性
        21.2.6 共感の醸成
    21.3 リーダー層の説得
        21.3.1 意思決定プロセスの理解
        21.3.2 変更の論拠の構築
        21.3.3 勝算がある取り組みの選択
        21.3.4 エスカレーションと問題解決
    21.4 まとめ

22章 まとめ

付録A ディザスタリスク評価マトリクス

索引