🐝

精読「マイクロサービスアーキテクチャ 第2版」(第二部 実装 - 第11章 セキュリティ)

に公開


マイクロサービスアーキテクチャ 第2版
マイクロサービスの設計、実装、運用に必要なベストプラクティスや最新技術を解説した、実践的なガイドブックです。これを読めば、マイクロサービスに関してそれっぽい会話もできますよ。

関連記事

基本原則

マイクロサービスのセキュリティは、最も弱い部分がシステム全体のセキュリティを決定するため、全体的なバランスが重要。高度な技術(例:JWTトークンや相互TLS)に注目する前に、基本的なセキュリティ対策が適切に実施されているか確認する必要がある。

最小権限の原則

「最小権限の原則」は、個人やシステムにアクセス権を与える際に、必要最低限の権限を必要な期間だけ付与する考え方。この原則を守ることで、資格情報が侵害されても被害を最小限に抑えられる。

多層防御

「多層防御」の原則は、攻撃者が1つの防御を突破しても、次の防御が立ちはだかる仕組みを構築することを意味する。マイクロサービスアーキテクチャでも、機能を複数のサービスに分割し、それぞれの範囲を限定することで、この原則を適用できる。さらに、異なるネットワークセグメントやセキュリティ技術を組み合わせることで、単一のゼロデイ攻撃の影響を最小限に抑えることができる。これにより、モノリシックアプリケーションよりも強固でセキュアなシステムを構築可能。

自動化

マイクロサービスアーキテクチャでは、自動化がシステムの管理やデリバリ速度の向上に不可欠。自動化は、繰り返し作業やエラーを減らし、人よりも高速かつ効率的に処理を行える。また、最小権限の原則を実現しやすくし、セキュリティキーの失効やローテーション、潜在的なセキュリティ問題の検出などに役立つ。自動化の文化を取り入れることで、セキュリティ面での強化も可能になる。

セキュリティプロセスへのセキュリティの組み込み

セキュリティは、ソフトウェアデリバリのプロセスに最初から組み込むべきであり、後付けでは大きな修正が必要になることがある。セキュリティ専門家は開発チームを支援し、ツールの活用やトレーニングを通じて、セキュリティの考え方をソフトウェアに統合する役割を担う。また、自動化ツール(例: OWASP ZAP、Brakeman、Snyk)を用いることで、脆弱性を検出し、セキュリティチェックをCI/CDプロセスに組み込むことが推奨される。ただし、これらのツールは局所的な問題への対応が中心であり、システム全体のセキュリティを把握する必要性は依然として重要。

サイバーセキュリティの5つの機能

要約:
米国国立標準技術研究所(NIST)は、サイバーセキュリティ活動を「特定」「保護」「検知」「対応」「復旧」の5つの機能に分類している。このモデルは、全体的な視点を提供し、セキュリティ活動を体系的に理解する助けとなる。

  • 特定
    攻撃者や脆弱性を認識する。
  • 保護
    資産を防御する。
  • 検知
    攻撃の発生を見つける。
  • 対応
    問題に対処する。
  • 復旧
    問題後に元の状態に戻す。

これらの機能を理解し、マイクロサービスアーキテクチャの文脈で適用することで、従来のモノリシックアーキテクチャとは異なるセキュリティ要件に対応できるようになる。セキュリティ活動は、特定から復旧までの一連の流れとして考えるべきで、特定の脅威や攻撃のシナリオを想定しながら計画を立てることが重要。

特定

セキュリティを考える前に、誰が何を狙っているかを理解することが重要。そのためには脅威モデリングが必要です。開発者は技術的な解決策に集中しがちですが、セキュリティはシステム全体を視野に入れて考えるべき。

  • 脅威モデリングは攻撃者視点で脅威を分析し、全体的なリスクを把握する。
  • システム全体を対象にした分析が重要で、部分的な対策だけでは十分なセキュリティを確保できない。

脅威モデリングの結果を基に、セキュリティ対策やシステム修正が推奨される。

保護

最も重要で脆弱な資産を特定した後、それを保護する必要がある。マイクロサービスアーキテクチャでは攻撃対象が広がるため、保護すべき対象も増えるが、逆に多層防御を構築する選択肢も増加する。特に、マイクロサービスアーキテクチャでは保護の課題が多く発生する。

検知

マイクロサービスアーキテクチャでは、インシデントの検知が複雑化することがある。監視対象となるネットワークやマシンが増えるため、情報源が増え、問題の検出が難しくなる。ログ集約など、10章で紹介されたテクニックが問題の検知に役立つ。また、侵入検知システムなどの特殊なツールも有効。

対応

最悪の事態が発生した場合、まずは侵害の範囲と漏洩したデータを把握することが重要。もし漏洩したデータに個人識別情報(PII)が含まれている場合、法的義務に従い、セキュリティやプライバシーのインシデント対応、通知プロセスを進める。多くの組織では、事後対応の不備により影響が悪化し、ブランド損失や罰金が増加する。例えば、GDPRでは個人データの漏洩を72時間以内に関係当局に報告することが義務付けられている。

また、対応時には外部連絡だけでなく、内部の対応も重要。非難や恐怖を重視する文化の組織ではインシデント対応が悪化することが多いが、開放性と安全を重視する組織では、教訓を学び、同様のインシデントを未然に防ぐために最適な場所となる。

復旧

復旧とは、攻撃後にシステムを再稼働させ、再発のリスクを抑えるために学んだ教訓を実装する能力のこと。マイクロサービスアーキテクチャでは、多くの部品が絡んでいるため、問題が広範囲に影響を与えると復旧が難しくなることがある。そのため、本章の後半では、システムをできるだけ早期に復旧・再稼働させるための手段として、自動化やバックアップなど、単純な対策が役立つことについてする。

アプリケーションセキュリティの基礎

資格情報(クレデンシャル)

資格情報(クレデンシャル)に関する議論は、セキュリティの観点から非常に重要。特に、マイクロサービスアーキテクチャにおいては、関与するコンポーネントやシステムが増えるため、資格情報の管理が複雑になる。適切なアクセス制御を行わなければ、システム全体のセキュリティが脅かされる可能性がある。以下は、資格情報とシークレット管理に関連する重要なポイント。

  • 資格情報とシークレットの違い:

    • 資格情報は、ユーザやシステムが制限されたリソースにアクセスするために使用するもの(例:ユーザー名とパスワード、APIキーなど)。
    • シークレットは、機密性が高く、システムの運用に不可欠な情報(例:TLS証明書、SSHキー、データベースのアクセス情報など)。
  • 資格情報の管理:

    • 資格情報はシステムやユーザーアカウントへのアクセスを制限するために使用されます。悪意のある攻撃者により資格情報が盗まれると、システムへの不正アクセスやデータ漏洩のリスクがある。
    • パスワード管理に関するベストプラクティスとして、長い複雑なパスワードの使用、パスワードマネージャーの利用、定期的なパスワード変更の推奨などがあり、これらはセキュリティ向上に寄与する。
  • シークレット管理:

    • シークレットは、システムの運用において不可欠な情報であり、厳格に管理されるべき。これらには、公開/秘密のAPIキーやデータベースの認証情報が含まれる。
    • シークレット管理には、生成、配布、保存、監視、ローテーションといったライフサイクル管理が重要。特に、シークレットが安全に保存されていること、アクセス権限が適切に制御されていることが必要。
  • ツールとサービス:

    • Vault(HashiCorp)は、シークレット管理のための強力なツールで、動的シークレットの生成や管理が可能。これにより、シークレットの更新が自動化され、セキュリティが向上する。
    • また、AWS Secrets ManagerやAzure Key Vaultなど、クラウドサービスにもシークレット管理ツールが提供されているが、クラウドに依存することに不安がある場合、自分で管理する選択肢もある。
  • 攻撃者による利用:

    • 資格情報が盗まれると、攻撃者はそれを利用してシステムにアクセスしたり、不正にリソースを消費することが可能。例えば、ビットコインマイニングなどの不正行為が行われることもある。
  • ローテーションの重要性:

    • 資格情報やシークレットは頻繁にローテーションすることが理想的。これにより、万一、資格情報が漏洩した場合でも、被害を最小限に抑えることができる。

資格情報やシークレットの管理は、マイクロサービスアーキテクチャにおいて非常に重要であり、適切なセキュリティ対策を講じることがシステム全体の信頼性を保つために不可欠。

パッチ適用

現代のインフラでは、管理やパッチ適用が必要なレイヤーが複数あり、それらの負担を軽減するために、パブリッククラウドプロバイダを活用することも一つの方法。また、コンテナ環境でも、イメージやOSの脆弱性が問題となることがある。定期的なアップデートやパッチ適用を行うことが難しいため、セキュリティツールを活用して、常に最新の状態を維持することが求められる。

SnykやGitHub Code Scanningなどのツールは、依存関係に含まれる既知の脆弱性を自動的にスキャンし、問題が見つかれば更新を提案するなどの機能を提供する。これらのツールをCIプロセスに組み込むことで、問題があるライブラリにリンクされている場合にマイクロサービスのビルドを失敗させることも可能。

バックアップ

バックアップは、デンタルフロスのように定期的に行うべきこと。多くの人がバックアップを取っていると言うが、実際に行っている人は少ないかもしれない。技術の進歩により、ディスクの信頼性やレプリケーションの機能が向上したが、それでもバックアップは重要。システム障害やバグによるデータ損失を防ぐため、重要なデータは確実にバックアップを取るべき。また、バックアップが正しく機能するか確認するために、定期的に復元テストを行い、データが本物であることを確認しよう。バックアップは、システムの稼働場所とは別の場所に保存し、バックアップが侵害されないようにすることも大切。

再構築

システムが侵害された場合、再稼働させることが最優先だが、権限を持たない関係者のアクセスを排除する必要がある。過去にはルートキットを使用した攻撃を受け、サーバを再インストールすることで対処した。定期的なサーバ再構築と資格情報のローテーションで攻撃者の影響を制限できる。マイクロサービスでは、再構築を自動化し、バックアップの品質を確認することが重要。

暗黙の信頼とゼロトラスト

暗黙の信頼では、ネットワーク内のすべてを信頼し、ゼロトラストではすべてを疑い、アクセスごとに検証する。

暗黙の信頼

「暗黙の信頼」モデルでは、ネットワーク内のサービス呼び出しを信頼する前提だが、攻撃者が侵入すると大きなリスクを伴う。この方法は多くの組織で無意識に採用されていて、危険性に対する認識が不足している。

ゼロトラスト

ゼロトラストでは、すべての環境が既に危険にさらされていると仮定し、安全に作業するために予防策を講じる必要がある。内部ネットワークも信頼できるものとは見なさず、外部からの接続も慎重に評価する。システムは常に危険にさらされていると仮定し、すべてのデータを暗号化し、アクセスに関する決断も柔軟に行うべき。ゼロトラストは、単なるツールではなく、システムの構築と進化に関する基本的な方針。

併用のバリエーション

暗黙の信頼とゼロトラストは、どちらか一方を選ぶべきものではなく、システム内で信頼度を調整できる。例えば、個人情報を扱うサービスにはゼロトラストを適用し、他の領域ではより緩やかなセキュリティを使用することが可能。セキュリティの実装コストは脅威モデルに基づいて判断する必要がある。実際の例として、MedicalCoではデータの機密性に応じて異なるゾーンでマイクロサービスを運用し、各ゾーンに適したセキュリティ対策を実施していた。

データをセキュアにする

転送データ

通信プロトコルを選択する際のセキュリティ対策として、TLS(Transport Layer Security)を使ったHTTP通信の保護について、以下の主要なポイントがある

  • 通信プロトコルとセキュリティ
    転送データの保護は、使用する通信プロトコルに大きく依存する。例えば、HTTP通信にはTLSを使うことでセキュリティが確保される。

  • サーバIDの確認
    サーバと通信する際に、悪意のある第三者がサーバを偽装するリスクがあるため、サーバIDの確認が重要。これにより、安全な通信が確保されます。HTTPSを使用することで、サーバIDの確認が実施され、セキュリティが向上する。

  • クライアントIDの確認
    マイクロサービスアーキテクチャでは、リクエストを送るマイクロサービスのIDを確認することも重要。これにより、不正なアクセスを防ぐことができます。相互TLSを使用して、クライアントとサーバ両方の認証を行うことが一般的。

  • データの可視性と操作
    転送中のデータが中間者に見られたり変更されたりしないように、TLSによってデータを暗号化する。また、データが公開されている場合、HMAC(ハッシュベースのメッセージ認証コード)を使用して、データの改ざんを防止する。

このように、マイクロサービス間の通信ではセキュリティを重視し、適切なプロトコルと認証メカニズムを選択することが重要である

保存データ

機密性の高いデータを保護するためには、以下の点が重要である

  • 暗号化の重要性
    データを保存する際には、暗号化を行うことが最も基本的かつ効果的な方法です。自分独自の暗号化アルゴリズムを使用するのは避け、信頼性の高いアルゴリズムを使うことが推奨されている。

  • パスワード管理
    パスワードは「ソルト付きのパスワードハッシュ」を使って保存するべき。これにより、攻撃者が1つのパスワードを解読しても、他のパスワードを守ることができる。

  • 暗号化のリスク管理
    暗号化には適切なキーの管理が必要。キーをどこに保存するか、キー管理システムを使うかなど、キーのライフサイクルを適切に管理することが重要。

  • バックアップの暗号化
    本番データと同じく、バックアップデータも暗号化して保存するべき。これにより、万が一バックアップが不正にアクセスされた場合でも、データの保護が維持される。

  • データ最小化
    必要最低限のデータのみを収集・保存し、不必要な個人情報を削除することで、データ漏洩のリスクを減少させることができる。

これらの対策を講じることで、攻撃者からのリスクを最小限に抑え、データのセキュリティを強化することが可能。また、暗号化やキー管理においては定期的にレビューやパッチ適用を行い、最新の状態を維持することが重要。

認証認可

認証(authentication)は、ユーザーが自称通りの存在であることを確認するプロセスで、通常はユーザー名やパスワードで行う。認可(authorization)は、その認証されたユーザーが実行できる活動を決定する仕組み。シングルサインオン(SSO)は、複数のマイクロサービスへのアクセスを1回のログインで可能にし、使いやすさを向上させる。

サービス間認証

サービス間認証には、相互TLSやAPIキーの使用が考えられる。相互TLSでは、クライアントとサーバが互いに認証し、通信を保護する。APIキーでは、クライアントがリクエストをハッシュして送信し、サーバが有効なキーであることを検証する。

人の認証

人の認証では、従来のユーザ名・パスワードに加えて、複数の認証要素を組み合わせる多要素認証(MFA)が普及している。MFAでは、ユーザ名・パスワードに加え、セキュアトークンやモバイル認証アプリ、生体認証など、追加の要素を求めることが一般的。これによりセキュリティが向上し、多くのサービスがMFAをサポートしている。特に機密性の高い情報へのアクセスには、MFAの使用が必須とされている。

一般的なシングルサインオン(SSO)の実装

シングルサインオン(SSO)は、ユーザーが一度認証すれば複数のサービスやアプリケーションにアクセスできる仕組み。IDプロバイダ(IdP)が認証を担当し、認証後、サービスプロバイダ(SP)がユーザーにアクセス権を与える。企業では、LDAPやActive Directoryなどのディレクトリサービスと連携した自社のIDプロバイダを使用することが一般的。現在、OpenID ConnectはOAuth 2.0に基づいたシンプルな実装として広く使用されており、SSOの主要なメカニズムとなっている。

シングルサインオン(SSO)ゲートウェイ

SSO(シングルサインオン)ゲートウェイのアプローチでは、マイクロサービスの間でIDプロバイダへのリダイレクトとハンドシェイクを集中管理する。これにより、外部からの認証要求を効率的に処理し、重複したコードを減らすことができる。共通のゲートウェイを使用して、複数のマイクロサービスが同一の認証プロセスを共有する。ゲートウェイは、ユーザー名やロールなどの情報を下流のサービスに渡すため、ヘッダやJWT(JSON Web Token)を利用してデータを転送する方法が一般的。

また、ゲートウェイに認証処理を委任することで、各マイクロサービスが独自に認証を行う負担を軽減できるが、その分、個々のサービスがゲートウェイに依存するため、ゲートウェイが単一障害点(SPOF)になるリスクもある。セキュリティ対策として、複数の防御層(多層防御)を意識する必要があり、ゲートウェイレイヤに多くの機能を集約しすぎないように注意が求められる。

粒度の細かい認可

粒度の細かい認可は、非常に詳細な制御を提供することができる。例えば、ユーザーに対して特定のリソースやエンドポイントへのアクセスを許可または制限することが可能。SSOゲートウェイを利用することで、認証結果としてユーザーに関する情報(ロールやグループなど)を取得でき、その情報をもとにきめ細かい判断を行うことができる。

しかし、極端に粒度の細かいロールや権限の管理は非常に複雑で、メンテナンスが困難になる可能性がある。例えば、非常に詳細なロール(「CALL_CENTER_50_DOLLAR_REFUND」など)を使用すると、個々のサービスにおいて細かな権限の管理が必要となり、組織内の他の部門と同期を取るのが難しくなる。このような細かなロール管理はサービスの独立したライフサイクルを妨げる原因となる。

そのため、代わりに組織の構造に基づいた粒度の粗いロールを使用する方が良いとされている。例えば、役職や部門に基づいたロールを使うことで、管理が簡素化され、サービスの独立性が保たれる。

混乱した代理問題

「混乱した代理問題(Confused Deputy Problem)」は、システムのセキュリティにおける脆弱性で、代理の役割を持つシステム(例えば、Web Shop)が不正に別のユーザーにアクセスを許可するような状況を指す。問題は、上流のサービス(例えば、ブラウザ)からのリクエストを受けた際、下流のサービス(例えば、Orderサービス)が誤って本来の意図に反してリクエストを処理してしまうこと。

具体例として、顧客がオンラインショッピングサイトにログインした後、注文の詳細を確認するために注文情報をリクエストするケースを挙げている。顧客が自分の注文情報を確認するためのリンクをクリックし、Web Shopがその注文の詳細をOrderサービスから取得する必要がある。しかし、顧客がシステムのUIを誤用し、他のユーザーの注文情報をリクエストできる場合、この「混乱した代理問題」が発生する。

この問題は、ユーザー認証は行われているものの、適切な認可(アクセス制御)が行われていないために起こる。つまり、ログインしたユーザーの認証情報を使って他人の情報を不正に取得できる可能性がある。

解決策としては、認証だけでなく、きちんとした認可の仕組みを導入する必要がある。例えば、ユーザーAが自分の注文情報を閲覧したい場合に、そのリクエストがA自身からのものであることを確認する仕組みを導入することが求められる。このような認可チェックをどこで行うかが重要なポイント。

一元的な上流での認可

一元的な上流での認可を避けるための方法として、リクエストが受信された時点で必要な認可をすべて行うというアプローチがある。これにより、上流のゲートウェイやWeb Shopでリクエストが認可され、下流のサービス(例えば、OrderやShippingサービス)にリクエストが送信される前に認可されていると見なすことができる。

この方法は、ゼロトラストモデルとは異なり、上流のシステムにある程度の暗黙の信頼を置くことになる。具体的には、ShippingやOrderサービスは、上流から送信されたリクエストが認可されたものであると信じて処理する。このアプローチは簡便ではありますが、上流エンティティ(例えば、ゲートウェイ)が下流のサービスに対するアクセス制限方法を認識する必要があり、依存関係の問題が生じる可能性がある。

理想的には、マイクロサービスは自己完結型で、変更や新機能のロールアウトが容易で、独立してデプロイ可能な状態が望ましい。この場合、呼び出しの認可をマイクロサービス自体が判断できるようにするのが理想的。これにより、マイクロサービスは自律的になり、ゼロトラストの実装が可能になる場合がある。

認可の分散化

一元的な認可が抱える課題に対して、認可のロジックを各マイクロサービスに任せる方法が提案されている。具体的には、Orderサービスが注文詳細へのアクセスを制御する役割を担い、リクエストが有効かどうかを判断することが理にかなっている。

ただし、このアプローチでは、Orderサービスがリクエストを行ったユーザーの情報を知る必要がある。この情報をどのようにOrderサービスに渡すかが課題となる。最も簡単な方法として、リクエストにユーザー識別子を含めることが考えられる。例えば、HTTPヘッダーにユーザー名を追加する方法。しかし、悪意のある攻撃者が他のユーザー名を挿入してリクエストを偽装することを防ぐ方法も考慮する必要がある。

理想的には、リクエストが「本当に」認証されたユーザーのために行われ、ユーザーに関連する追加情報(例えば、ユーザーが属するグループなど)を伝える方法が必要。このような認証と認可の統合を実現するために、一般的に使われる解決策としてJSON Web Token(JWT)がある。JWTを使用すると、リクエストを送る際にユーザー情報を安全に伝えることができ、認可を行う際にその情報を活用することができる。

JSON Web Token(JWT)

JWT(JSON Web Token)は、ユーザーの認証情報を安全にやり取りするためのトークン。JWTはヘッダー、ペイロード、署名の3部分から構成され、通常はユーザーの情報や認証データ(クレーム)をJSON形式で含む。JWTは暗号化され、署名されることにより、改ざん防止やデータの正当性を保証する。

JWTはマイクロサービスアーキテクチャなどで利用され、リクエストごとに生成され、サービス間で認証・認可情報を渡すために使われる。JWTは、トークンの有効期限や署名アルゴリズムを指定することができ、シンプルで多くのライブラリがサポートしている。しかし、キー管理やトークンの有効期限の管理には注意が必要。

参考

Discussion