yu nkt’s blog

nkty blog

I'm an enterprise software and system architecture. This site dedicates sharing knowledge and know-how about system architecture with me and readers.

DHARMA: マイクロサービスアーキテクチャのSecurity by Design

背景

マイクロサービスアーキテクチャは、独立して稼動する各マイクロサービス間で、APIコールやメッセージングなどの通信が発生します。 開発していると、それらのI/Fを整えることだけに気がいきがちですが、通信が発生するということは、セキュリティリスクが高まるとも言えます。

私はセキュリティエンジニアではありませんが、そんな人間でもセキュリティを意識せざるを得ない時代が来たといえます。 この記事では、そういった時代に必要な、Security by Designという潮流と、DHARMAという新しいアプローチについて、説明します。

Security by Design

後付けのセキュリティ対策の問題点

多くの開発現場では、セキュリティ対策を、後付けで考えていないでしょうか。 まず、正常系、次に異常系を設計開発します。 それとは独立した議論として、「マシンにセキュリティソフトを入れておく」とか「OSのFirewallの設定はこうしておく」「ルータなどのネットワーク機器はこう設定しておく」とか考えているかと思います。 長期に構成がほとんど変わらずに安定稼働するシステムなら、Waterfall開発としてこのプロセスでも良いかもしれません。

しかし、近年のITシステムにおいては、いくつもの問題があります。

まず、システムの構成は変化することが多いのですが、上記のプロセスでは、その変化への追従が困難です。 例えば、k8sなどの仕組みで処理をスケールアウトする仕組みが一般的ですが、スケールアウトのためにクラスタに参加させるマシン・VMごとに、セキュリティソフトを入れて、OS設定して、というのはコストが高すぎます。 属人化されやすく、デバイスごとに正しい設定になっているか管理するのも大変です。

また、様々な種類のデバイスが混在するシステムでは、統一的なセキュリティ設定が難しい場合があります。 例えば、様々な種類のIoTデバイスが混在する、IoTシステムです。 特定のデバイスには、従来のセキュリティ対策ガイドラインが適用できず、その場しのぎの暫定対応が積み重なることがありえます。

このような静的なガイドラインのせいで、システムの柔軟性が低下し、ビジネスメリットが阻害されるケースが増えてきます。

セキュリティだけでなく、プライバシーデータの保護の分野にも、Privacy by Designという似た概念が提唱されています。GDPRの条文の中にも、わざわざ一章分使って説明されています。

gdpr-info.eu

プライバシー情報を扱う場合に、万が一流出したら手の施しようがない、というのは、「仕方ないこと」ではなく「組織側の怠慢」であり制裁の対象である、ということです。 一例ですが、プライバシー情報は全て、個人ごとに(or 単発のデータごとに)暗号化し、万が一流出した場合に、鍵を削除する、といった仕組みを、システムのセキュリティ機能として、設計段階から組み込まなければいけません。

システム設計にセキュリティ機能を組み入れる

Security by Designとは、システムの重要な機能の一部として、セキュリティ対策に関する保守のための機能を入れましょう、ということです。 例えば、システムをモニタして問題を検知する機能、システムやネットワークをコントロールする機能(できれば最低限のシステムの可用性は担保しつつ)、新たに導入するセキュリティ機能の効果を評価する環境の用意、などなどが考えられます。

とはいっても、システムが長期運用されるなら、将来どんなリスクがあるかわからない、となりそうです。 確かに、個々のビジネス領域におけるリスクは、一般化できるものではなく、これまでの経験や想像力は必要になります。 ただ、これは、要件が最初から定まっていないアジャイル開発とも共通する所であり、基本的な発想は、システムや内部のアプリケーションを、後からセキュリティ機能の拡張を組み入れやすい設計にしておくことや、問題が起こった時を想定したテストを実行するCI環境を用意して、おくことです。

いったんコスパを度外視して、理想論を言うなら、以下のような開発プロセスが必要です。 詳しくは、詳しくは下記引用元を参照してください。

  • システム設計時に、システムやネットワークなどをコントロールする管理者用の機能とAPIを用意する
  • 想定しうるセキュリティリスクのユースケースを定義する
  • サードパーティコンポーネント脆弱性チェックや脆弱性情報を取得する方法を検討する
  • セキュリティテストを用意し、CI環境で結合テストを自動化する
  • インシデント対応手順をテストし、セキュリティの問題についてすべての構成変更を確認する
  • システムの負荷テストを行い、可用性を確認する

medium.com

このように、セキュリティの設計開発をデプロイパイプラインの組み込んで自動化していく文化を、DevSecOpsと呼びます。

インシデント対応としては、Istioなどによる環境の切り替えや、SDNを用いたコントロールプレーン上でのネットワーク構成変更などが考えられます。 その他のAPIアクセス認証の考え方として、次にDHARMAを紹介します。

DHARMA

Domain Hierarchy Access Regulation for Microservice Architectureの略で、恐らく、ダルマと呼ばせたいのだと思います。

DHARMAとは、複数のマイクロサービスのグループ(ここではこれをドメインと呼びます)を階層的に表現し、その各階層においてAPIアクセスを制御するアプローチです。 特に、クロスプラットフォームでマイクロサービスを運用する際に効果的です。 DHARMAだけがマイクロサービスアーキテクチャにおけるSecurity by Designではありませんが、その一つの考え方として紹介します。

日本語の解説があまりありませんが、英語で検索すると、結構情報が出てきます。 "Securing Microservice APIs"という書籍もおすすめです。 Broadcom社が無償でPDF配布しています。

(クリックすると、PDFがダウンロードされます) docs.broadcom.com

Zero Trust Network

DHARMAの背景に、ゼロトラスト、というセキュリティの考え方があります。 ゼロトラストとは、それぞれのサービスが、別のどのサービスも信頼しない(Untrusted)、ということです。

ゼロトラスト以前の一般的なネットワーク設計では、ネットワークを、互いの端末が信頼できる領域(サブネット)で区切るようにして設計してきました。 つまり、同じプライベートNW内の端末同士は、互いに信頼できるという暗黙の前提が含まれています。こういった、信頼できるネットワークを静的に構成する方法は、問題のある端末(乗っ取られた、ウイルス感染した)が現れた場合のセキュリティ対策として不十分です。

そこで、事前に信頼できる端末を設定することなどはせずに全端末が本質的に信頼できないものとみなす、ゼロトラストと言う考えが生まれました。具体的には、全端末間の全通信にプロキシを挟むなど、通信が発生する時に信頼できるかを判定します。これにより、問題が起きても、迅速かつフレキシブルに対応することができます。

マイクロサービスアーキテクチャのサービス間の通信においても、ゼロトラストを用いる、という手は確かにあります。 Kubernetesでも、Istioでこれを実現できます。

ただ、このような方法では通信の効率が悪いのは明らかです。 また、全通信にフラットに同レベルの暗号化を行うなら、その鍵や証明書の管理がシステム全体に及びます。単一障害点にならないように複雑な構成が必要になります。

マイクロサービス間の通信であれば、動的でありつつも、もっと効率的にアクセス制御をすることはできないでしょうか。

そこで、DHARMAという考え方の出番です。

DHARMAの構成

DHARMAでは、サービスの集合であるドメインを定義します。 このドメイン内は信頼でき、別ドメインからのアクセスは、信頼度が低いものとみなします。 ドメイン内のサービスに見せるAPIエンドポイントを、Interior endpointドメインの外からのアクセスを受けるエンドポイントをboundary endpointと呼び、それぞれで認証方式を変えます。

このドメインを、一つのマイクロサービスアーキテクチャのシステム内で、階層的に構築するのが、DHARMAの構成です。

https://image.slidesharecdn.com/sany18-api-security-microservices-v2018-02-28-180315180755/95/api-security-in-a-microservice-architecture-29-638.jpg?cb=1521137447

(引用元:https://www.slideshare.net/MattMcLarty/api-security-in-a-microservice-architecture)

この階層的なドメインのアクセスコントロールを実装していく手順は、以下の通りです。

  1. 信頼できるドメインを定義する (上図のinner domain)。例えば、より密に処理連携が行われて、かつ、同じプラットフォームで稼動させられるサービス同士を含めるとかです(効率重視)。
  2. ドメインごとに、アクセスコントロールの方法を決める
  3. Interior endpointとboundary endpointを決める
  4. ドメインの下回りのプラットフォームを決める

システムを管理する組織が手を出せないところからのアクセス(最も外側の階層のBoundary endpoint)では、OAuth 2.0やOpenID Connectなどが良いでしょう。 API gatewayを用意することになります。これは普通のマイクロサービスアーキテクチャの開発と同じです。

その内側の階層のBoundary endpointでは、比較的組織内でハンドリングできるため、証明書付きの、JWTなどのトークンを使えば良いかもしれません。 内部の階層は、効率重視にすればよいです。ただ、トークンを使うなど最低限のセキュリティは欲しいです。 それは、軽量なリバプロを用意すればよいでしょう。 一応、auditdなどで監査ログも残しておくのが良いと思います。

認証局と証明書管理の仕組み、トークン発行・管理(期限とかも)の仕組みは必要です。 DHARMAでは、適切なドメインのサービスに適切な証明書、トークン発行を行うよう注意して設定する必要があります。 やや面倒かもしれませんが、システムの中で、重要度に合わせて管理を分けられるのは、効率性とセキュリティを調整しやすいとも言えます。

https://image.slidesharecdn.com/sany18-api-security-microservices-v2018-02-28-180315180755/95/api-security-in-a-microservice-architecture-35-638.jpg?cb=1521137447

(引用元:https://www.slideshare.net/MattMcLarty/api-security-in-a-microservice-architecture)

あとは、SDNのコントロールプレーンのように、アクセスポリシーが変更されたら、それに応じてAPI gatewayや軽量プロキシが動的に設定を反映させるようにする必要があります。 その他、細かい注意や、適切な開発チーム構成などは、上記した書籍や他の情報リソースを参考にしてください。

おわりに

基本的には、しっかりセキュリティを意識したエンジニアが設計したら、無意識にDHARMAと同じような構成になるような気はします。 ただ、こういったプラクティスに名前が付けられることで、知見が広まりやすく、もしかしたらより効率的に構築するためのツールやサービスが出てくるかもしれません。

重要なのは、マイクロサービスアーキテクチャを、モノリシックのWaterfall開発の時と同じ観点で構築したら、リスクが増えることです。 設計の段階で、セキュリティ観点(セキュリティ面の動的な設定を行える機能を仕様に入れること)を含めることを心がけましょう。 それがあまりに億劫であれば、本当にマイクロサービスアーキテクチャが必要かという点から見直すのも一つの手です。