無印吉澤

Site Reliability Engineering(SRE)、ソフトウェア開発、クラウドコンピューティングなどについて、吉澤が調べたり試したことを書いていくブログです。

Building Secure and Reliable Systems 読書メモ - Chapter 5

f:id:muziyoshiz:20200430014145p:plain:w320

SRS 本の読書メモの続きです。Chapter 5 はなかなか重たい内容だったので、この章のみでメモを上げます。

SRS 本はこちらから無償でダウンロードできます。

前回までの読書メモは SRS Book タグ を参照のこと。

Chapter 5. Design for Least Privilege

最小権限の原則(The principle of least privilege)とは、アクセス主体が人間かシステムかに関わらず、タスクを達成するのに必要な最低限度のアクセス権限のみを与えるべきという原則である。新機能の設計段階から考慮することで、この原則が最も有効に働く。

社員の操作に完璧は期待できない。そこに悪意があるにせよないにせよ。思考実験として、もしあなたがなにか悪いことをしたいと思ったら、自分の組織にどのようなダメージを与えられるか考えてみよう。どんなことを、どのように実行できる? あなたの悪事は気づかれる? あなたの操作履歴を隠すことはできる? あるいは、もし良い意図だとしても、あなたができる最も破壊的なミスはどんなもの? 普段どれくらいのコマンドを手で実行していて、そのなかにどれくらいのタイミングミスやコピペミスがある?

そのような悪いアクションによる影響を最小化できる、または取り除けるようにシステムを設計することを推奨する。ここでも SRE の格言を引用すると、hope is not a strategy. である。

Concepts and Terminology

ベストプラクティスの詳細に入る前に、業界および Google での用語の定義について。

  • Least privilege(最小権限)
    • セキュリティ業界で確立された、幅広いコンセプト
    • 最小権限の目的は、そのシステムのすべての認証・認可のレイヤに渡って拡張されるべき
  • Zero Trust Networking
    • ユーザのネットワーク的な位置(それが社内ネットワークかどうか)によって、何の権限も付与しないという原則
    • Google では BeyondCorp program によって大規模な zero trust networking の実装に成功した
  • Zero Touch
    • SRE が直接システムやネットワークに触らず、拡張可能な自動化や、安全な API や、回復性のある多要素承認システム(resilient multi-party approval system)を通してのみ変更を行うこと
    • Google ではこれを実現するために Zero Touch Production (ZTP) や Zero Touch Networking (ZTN) などのインターフェイスを開発してきた

Classifying Access Based on Risk

すべてのアクセスを同じ方法で一律に制限するのではなく、セキュリティリスクや影響度に応じてアクセスを分類する必要がある。例えば、アクセスされるデータの種類による分類や、その API が書き込み可能かどうかによる分類がありがちだろう。

あなたのシステムの分類が明確に定義され、一貫性を持って適用され、広く理解されれば、開発者はそれを共通言語としてシステムやサービスを設計できる。この分類フレームワーク(classification framework)は、データストア、API、サービスやその他のエンティティに幅広く適用されうる。

p.64 の Table 5-1. Example access classifications based on risk に、アクセスを Public, Sensitive, Highly sensitive の3種類に分類した例を示す。

Best Practices

著者らが推奨する、最小権限モデルを実装する際のベストプラクティスを紹介する。

  • Small Functional APIs
    • さながら UNIX 哲学にあるように、1つのことだけをうまくやる API を作る
    • POSIX API のような巨大な API に対しては、制限や監査ログの記録(audit)は難しい
    • ユーザー向けの API より、管理用の API(Administrative API)のほうが権限が強い分、より一層の注意が必要
  • Breakglass
    • ガラスを割って非常ボタンを押すように、非常時に認証システムをバイパスする仕組みを breakglass mechanism と呼ぶ
    • 予期せぬ状況から復旧するために、このような仕組みは有用
    • For more context, see “Graceful Failure and Breakglass Mechanisms” on page 74 and “Diagnosing Access Denials” on page 73.
  • Auditing
    • 監査ログの記録から、意味のある検知ができるかどうかは、そのシステムの「アクセス制限がどれくらいの粒度か」と「リクエストに関するメタデータがどれくらい明確に記録されるか」に依存している
  • Testing and Least Privilege
    • 最小権限に関連するテストには、2つの重要な次元がある
    • Testing of least privilege
      • 必要なリソースのみに対するアクセス権限を正しく与えられていることを保証する
      • 本番環境への悪影響を避けるため、アクセス権限を実際に変更する前に、このテストは自動実行されるべき。テストカバレッジが不完全な場合は、監視やアラートの仕組みで一部補うこともできる
    • Testing with least privilege
      • テストのためのインフラが、そのテストに必要なアクセスのみを与えられていることを保証する
      • 例えば、新しい機能を開発したい人(データアナリスト)向けに、限られたデータセットへのアクセスのみを許可したいケースがある
      • テスト環境を作る代わりに、本番環境にテストアカウントを作るという方法もあるが、これは監査やACLにノイズを増やすことにもなる。テスト環境は高価だが、それを用意しなかった場合のリスクもある。あなたの状況ごとに、費用対効果をよく考えることが重要
  • Dignosting Access Denials
    • ユーザーの持っている権限によって、アクセス拒否時に渡す情報を変える。情報を与えすぎるとシステムを攻撃するための情報を与えることになりかねないが、与えなさすぎるとセキュリティポリシーチームのサポート負荷が限界を超えてしまう
    • Zero trust model の実装の初期段階では、アクセス拒否時にトークンを提示し、サポートチャンネルに問い合わせさせることを推奨する
  • Graceful Failure and Breakglass Mechanisms
    • breakglass mechanism を導入する際に考慮すべきガイドライン:
      • breakglass mechanism の利用は強く制限されるべき。一般的に、そのシステムの SLA に責任を持つ SRE チームに制限するべき
      • Zero trust networking のための breakglass mechanism は、特定の場所(例えば、物理的なアクセス制限のある panic rooms)からのみ利用できるようにすべき。ネットワーク上の位置を信頼しないという ZTN のコンセプトに反しているように見えるかもしれないが、この場合は、物理的なアクセス制限を前提として信頼する
      • breakglass mechanism の全ての利用は入念に監視されるべき
      • breakglass mechanism は、本番サービスに責任を持つチームによって定期的にテストされるべき

Auditing のベストプラクティスについては、この節のなかで更に深堀りされている。

  • よい監査ログを集める
    • よい監査ログを集めるうえで、Small Functional APIs には強いアドバンテージがある。Small Functional APIs がないと、一時的に強くて広い権限の API へのアクセスを与えるか、事前に監査を受けた上でシステムの直接操作を許可することになる。いずれも監査ログの追跡を難しくする
    • 最終的には、管理用 API と自動化を構築するチームは、監査を容易にする方法でそれらを設計する必要がある。そのためには、監査を重視する文化が必要。文化なしでは、監査は常に承認され、breakglass は日常利用され、意味をなさなくなってしまう
  • 監査者(auditor)を選ぶ
    • 監査の目的次第で、どのような監査者を選ぶべきかは変わる。Google では監査を以下の大きな2カテゴリに分類している
      • ベストプラクティスに沿っていることを確実にするために監査する(Audits to ensure best practices are being followed)
      • セキュリティ違反を特定するために監査する(Audits to identify security breaches)
    • 前者は、例えば breakglass を多用しすぎていないかを毎週の SRE チームミーティングでレビューすること。Google では breakglass review をチームレベルで分散して、社会規範化(social norming)を促進している。これは、現行の administrative APIs の欠点を明らかにし、改善を促すことにもなる
    • 後者は、Google では central auditing team に集約している。そのような攻撃は、複数の組織の監査ログを俯瞰的に見ないとわからないことがある
    • 著者らは、Google にて、structured justification(構造化された正当化)というものを使って、audit log events を構造化されたデータと関連付けている。これは、バグ番号や、チケット番号、カスタマーケース番号などに対する構造化された参照のことである。このような構造化されたデータがあれば、監査ログを自動的に検証できる

Worked Example: Configuration Distribution

具体例として、Web サーバ群に設定ファイルを配布する事例を考える。設定ファイルの管理に関するベストプラクティスは次のようになる。

  1. バージョン管理システム上に設定ファイルを保管する
  2. そのファイルに対する変更をコードレビューする
  3. その変更をまず canary set に配布し、ヘルスチェックを通ったら、すべての Web サーバに対して段階的に配布する。このステップは、この自動的なアクセスに対して、設定ファイルの更新権限を与えることを要求する

この更新機能を実現するために公開する Small API のアプローチはいくつかある。この節では以下の4通りを考える(p.75 の Table 5-2 に詳細)。

  • POSIX API via OpenSSH
  • Software update API
  • Custom OpenSSH ForceCommand
  • Custom HTTP receiver

POSIX API via OpenSSH はシンプルで一般的だが、何でもできてしまうため様々なリスクがある。Software update API は apt-get などのパッケージを使った更新のことだが、バイナリの更新と設定ファイルの更新を同時に行うため、やりたいことに対して操作が高価かつ破壊的すぎる(詳しくは Chapter 9 で触れる)。

Custom OpenSSH ForceCommand は OpenSSH 経由の操作を安全にできるが、いろいろな操作に広げていくことが難しい。OpenSSH の上でいろいろなコマンドを送れるようにしていくと、それは結局独自の RPC メカニズムを作ることになる。それなら gRPC や Thrift の上に作ったほうが良い。

Custom HTTP Receiver は Sidecar として実装する方法と、In-Process に実装する方法がある。In-Process の方法が最も柔軟性があり、Google での設定ファイルの管理方法にとても近い。

A Policy Framework for Authentication and Authorization Decisions

API に対するアクセス制限として、認証(Authentication)と認可(Authorization)の2つのステップをどのように行うかを決めなければいけない。この節では、Google で有用とわかったさまざまなテクニックについて議論する。

  • Using Advanced Authorization Controls
    • 認証、認可を正しく実装するのは大変なので、AWS や GCP が提供する IAM 機能を使ったほうがいい
  • Investing in a Widely Used Authorization Framework
    • 認証、認可のフレームワークを共通化することで、すべてのサービスエンドポイントに対する機能の強化(後述する MFA や MPA のサポート追加など)や設定変更が可能になる
  • Avoiding Potential Pitfalls
    • ポリシー言語の設計は難しい。ポリシー言語をシンプルにしすぎると目的を達成できず、汎用的にしすぎるとその内容を推測するのが難しくなる。いずれかの極端によらないよう、反復的なアプローチで設計するのがよい

Advanced Controls

多くの認可に関する判断は yes か no かの二択になるが、厳密な二択にする代わりに、逃がし弁としての "maybe"(追加のチェック) を用意することで、システムにおける緊張を劇的に緩和できる。

以下で示す方法は、単独でも使えるし、組み合わせて使うこともできる。どのような使い方が適切かは、データの重要性、操作の危険性や、既存のビジネスプロセス次第である。

  • Multi-Party Authorization (MPA)
    • 他の人に認可を与えてもらうこと。ミスを防げる、悪事への抑止効果がある、などのいくつかのメリットがある
    • MPA は、広範なアクセス権限を与えるために使われがちであるが、可能なら Small Functional API と組み合わせたほうがよい
    • MPA を導入するだけでなく、組織的、あるいは仕組み的に No といえる環境を用意する必要がある。悩んだ場合はセキュリティチームにエスカレーションできるような仕組みがあれば、組織的な圧力を弱めることができる
  • Three-Factor Authorization (3FA)
    • 1個のプラットフォーム(例えば全員が共通で使っているワークステーション1台)が攻撃されただけでは権限を奪われないようにしたい。MPA だとこの種の攻撃は防げない
    • 少なくとも2個のプラットフォームを用意したい。安価な方法としては、リスクが高い操作については、セキュリティ的に強化されたモバイルプラットフォーム(hardened mobile platform)からの認可を求める、という方法がある
    • 3FA と Two-factor authentication(2FA、二要素認証)や Multi-factor authentication(MFA、多要素認証)は別のものである。3FA は強い認可を提供するものであり、強い認証を提供するものではない。ただし、3FA の 3 が誤解を招く用語であることは確か。3FA は第2のプラットフォームからの認可を求めるものであり、第3ではない
    • MPAと3FAによって防がれる脅威は別のものである、ということを理解することが重要。そうすることで、一貫したポリシーに基づいて、これらの技術を適用できるようになる
  • Business Justifications
    • 認可を求める際に、ビジネス的な正当性を、バグID、インシデントID、チケットID、ケースID、関連アカウントなどと紐付けることを強制する
    • また、それらの ID に関連して、アクセスを許可するデータも特定のものに限定すべきである。適切に構成されたシステムでは、入力されたチケット ID に関連する、特定の顧客に関連するデータへのアクセスしか許可しないことも可能になる
  • Temporary Access
    • 一時的なアクセス権限を与えることで、認可に関する決定によるリスクを限定することができる。これは、特に、すべての操作に対して細かなアクセス権限を設定できない場合に有用である。また、root 権限のような ambient authority(環境全体に関する認可)を減らすことにも繋がる
  • Proxies
    • バックエンドサービスに対する細かなアクセス権限を設定できない場合、次善の策として、強く監視され、利用が制限されたプロクシ(あるいは踏み台)を用いることができる
    • 例えば、緊急時に、他の API による操作では復旧できない場合に、プロクシ経由の操作を許可する

Tradeoffs and Tensions

最小権限アクセスモデルを導入することで、あなたの組織のセキュリティに対する姿勢は間違いなく改善される。しかし、これまでに説明した利点と、モデルを導入することによるコストを割り引いて考えなければいけない。この節ではそれらのコストについて考える。

  • セキュリティの複雑性が増す。このユーザーはこのデータにアクセスできるのか? このデータにアクセスできるのは誰なのか?
  • すべてのデータへのアクセスを同様に禁じると、情報の透明性がなくなり、組織文化に影響する。例えば、ソースコードも機密情報の一種である。しかし、ある程度のリスクを許容して、開発者にソースコードへの広範なアクセス権限を与えた場合、開発者はソースコードから学んだり、コントリビュートすることができる。この問題については Chapter 21 で詳しく触れる
  • 最小権限を与えるためのデータ(コンテキスト)の品質が悪いと、セキュリティに影響する。セキュリティに影響するデータの品質をできるだけ高くするために、それらのデータを作るシステムをレビューすべきである
  • ワークフローを行うユーザーにとっての利便性が下がる。ユーザーの苦痛をなるべく小さくするためのナビゲーションや、自己診断〜サポートへの連絡を助ける方法が必要である
  • 最小権限のためのモデルが導入されたら、開発者はそれに従う必要がある。開発者にこのモデルを理解してもらうために、トレーニング教材や API ドキュメントを整備すべきである。また、開発者がセキュリティエンジニアによるレビューを気軽かつ迅速に受けられるようにすべきである

Conclusion

複雑なシステムを設計するにあたって、最小権限モデルは、クライアントにその目的を達成するために必要な能力を与え、かつそれ以上のものを与えないための最も安全な方法である。

Google はこのモデルを実装するために莫大な時間および労力を投じてきた。最後に、最小権限モデルを実装するための主要なコンポーネントを挙げる。

  • あなたのシステムの機能に関する包括的な知識。この知識があることで、あなたはそれぞれの機能が持つセキュリティリスクのレベルに従って、それらの機能を分類できる
  • この分類に基づく、できるだけ細かいレベルでの、あなたのシステムおよびあなたのデータへのアクセスの分割(partitioning)
  • あなたのシステムへのアクセスを試みるユーザーのクレデンシャルを検証するための認証システム
  • 適切に分割されたシステムに対してアタッチされた、うまく定義されたセキュリティポリシーを適用するための認可システム
  • 細かな認可を与えるための、高度な制御機能。例えば、一時的な認可、MPA、3FA など
  • これらのキーコンセプトを支えるための、あなたのシステムに対する運用面での要件。少なくとも、以下が必要である
    • すべてのアクセスを監査し、あなたが脅威を見つけてフォレンジック調査を行うきっかけとなるシグナルを生成する能力
    • セキュリティポリシーを論理的に考えて、定義し、テストし、デバッグするための手段、およびそのポリシーに関するエンドユーザーサポートを提供する手段
    • あなたのシステムが想定通りに動かなかった場合に breakglass mechanism を提供する手段

ここまでの感想

5章だけで30ページ近くあり、具体例も豊富で勉強になりました。例えば、Auditor には2種類ある、というのは僕にとっては新しい観点でした。MPA と 3FA で目的が違う(MFA もまた違う)、というのも本書を読んでよく理解できました。

扱われている話題の範囲も広く、Google が実現しているレベルに達するのはかなり大変そうだ……というのが率直な感想です。

その一方で、いままで自分たちもやっていたことだけど、Google ではそう呼んでいるのか、と気づいた部分もありました。システムに対する作業を、今の仕事では Backlog の課題キー(チケット ID に相当するもの)と関連付けて記録しているのですが、これはまさに本章で "Business Justification" と呼ばれているものでした。

Google の事例を見て落ち込みすぎず、本書の内容を手本として、ベストプラクティスをできるところから少しずつ取り入れていきたいですね。