Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Securing the Service Mesh with SPIRE

Ryuma Yoshida
October 02, 2019

Securing the Service Mesh with SPIRE

SPIFFE Meetup Tokyo #2 で発表したスライドとなります。
https://spiffe-jp.connpass.com/event/142393/

発表の中で実施したデモのソースコードは以下となります。
https://github.com/zlabjp/spiffejp-demo

発表の録画は YouTube で公開しております。
https://youtu.be/UzZClSaUWng

Ryuma Yoshida

October 02, 2019
Tweet

More Decks by Ryuma Yoshida

Other Decks in Technology

Transcript

  1. Ryuma Yoshida / @ryysud ▶ DMM.com にて Hadoop Ecosystem を利⽤したデータ

    分析基盤の開発と運⽤に関わった後、2018年12⽉に ゼットラボ株式会社に⼊社 ▶ Kubernetes をベースとしたインフラ基盤の研究開発を ⾏っている ▶ 研究開発の⼀環で最近は SPIRE を触ることが多く、 SPIRE へのコントリビュートもしている
  2. アジェンダ 1. Service Mesh に求められるもの 2. SPIFFE/SPIRE について 3. Envoy

    について 4. SPIRE と Envoy を組み合わせた Service Mesh 5. Service Mesh 間の Federation について 6. まとめ 7. Appendix
  3. ▶ Protocols + Polyglot Programming が前提 ▶ Service Discovery ▶

    Traffic Management + ロードバランシング + フェイルオーバー + サーキットブレーカー ▶ Observability + 分散トレーシング + ログ/メトリクス収集 ▶ Security + サービス間の通信の暗号化 + 認証/認可 https://www.redhat.com/cms/managed-files/service-mesh-1680.png Service Mesh に求められるもの = マイクロサービスにおける課題の解決
  4. 何を使って Service Mesh を構築するか? ▶ 代表的なところだと Istio がある + 多機能であることのメリットは⼤きいがちゃんと運⽤できるか不安が残る

    + Kubernetes でしか利⽤できないので他の Container Orchestrator を使っ て Service Mesh を構築したいケースではどうするか? ▶ セキュアな Service Mesh を⼩さく始めたい⽅向け に Data Plane として Envoy, Control Plane として SPIRE を使った Service Mesh + Envoy による認証と通信の暗号化 と SPIRE による証明書の⾃動管理
  5. SPIFFE について ▶ SPIFFE = Secure Production Identity Framework For

    Everyone ▶ サービス間認証のための標準仕様 ▶ SPIFFE を導⼊したシステムでは簡単かつ安全にサービス同⼠が相互認証できる + プラットフォームに縛られることなく GCP, AWS, Azure, オンプレ どこでサー ビスが稼働していても SPIFFE によりサービス同⼠の相互認証が可能になる ▶ SPIFFE の実装としては SPIRE, Istio, Consul Connect, Athenz などがある ▶ CNCF の Sandbox プロジェクト(2019年10⽉2⽇現在) + Scytale社 が中⼼となって進められている + Uber, Pinterest, Square など有名企業でも導⼊されている
  6. SPIFFE で標準化されている主要コンポーネント ▶ SPIFFE ID + 認証対象(Node/Workload)を識別するためのURI 形式で構造化された⽂字列 + Workload

    = Unixプロセス や Container などソフトウェアの実⾏単位 + spiffe://<trust domain>/<workload identifier> で構成される + 例: spiffe://production.example.com/payments/api + Trust Domain は組織, 実⾏環境, 部⾨ などセキュリティの境界を描くために使⽤ + 同⼀の Trust Domain 配下の Workload 同⼠で相互認証が可能 ▶ SVID(SPIFFE Verifiable Identity Document) + Node/Workload Identity としての SPIFFE ID を証明するためのデータ形式 + 現在仕様が固まっているのは X.509-SVID と JWT-SVID の2つ ▶ Workload API + SVID と Trust Bundle(SVID を検証するための証明書や公開鍵)を取得するための API
  7. X.509-SVID の例(SAN に SPIFFE ID がセットされる) Certificate: Data: Version: 3

    (0x2) Serial Number: 4 (0x4) Signature Algorithm: ecdsa-with-SHA384 Issuer: C=US, O=SPIFFE ... Subject: C=US, O=SPIRE ... X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment, Key Agreement X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication ... X509v3 Subject Alternative Name: URI: spiffe://example.org/workload ...
  8. SPIRE について ▶ SPIFFE の参照実装 + SPIRE Server, SPIRE Agent

    から構成される ▶ SPIRE Server + Node を認証するための Node API + Workload の情報管理をするための Registration API + SVID に署名するための鍵ペアや認証情報の管理など ▶ SPIRE Agent + Node でデーモンとして稼働 + Workload を認証して SVID, 秘密鍵, Trust Bundle を配布するための Workload API + Trust Bundle は Workload が別の Workload から提⽰される SVID を検証するために利⽤される + 実体は CA証明書チェーン + X.509-SVID を検証するためのCA証明書, JWT-SVID を検証するための公開鍵が含まれる ▶ Node Attestation, Workload Attestation を経て Workload に SVID, 秘密鍵, Trust Bundle が配布される ▶ SVID, 秘密鍵, Trust Bundle は⾃動でローテーションされる + デフォルトで SVID, 秘密鍵 は 1h で Trust Bundle は 24h でローテーションされる ▶ SPIFFE と同じく CNCF の Sandbox プロジェクト(2019年10⽉2⽇現在)
  9. SPIRE を使って Workload に SVID が配布されるまでの流れ SPIRE Server Cloud Provider(e.g.

    GCP, AWS, Azure, OpenStack, etc.) Node 管理者 kernel / kubelet / dockerd Workload SPIRE Agent (1) SVID の配布を許可す る Workload 登録 (2) Node Attestation を要求 (3) Node の正当性検証 (4) Node Attestation OK! Node に SVID, 秘密鍵, Trust Bundle を配布 (5) Workload Attestation を要求 (6) Workload の情報を取得して SVID の配布が許可されている Workload か検証 (7) Workload Attestation OK! Workload に SVID, 秘密鍵, Trust Bundle を配布
  10. Envoy について ▶ C++ 製の⾼性能なプロキシ ▶ L7/L4 ロードバランサー + ⾃動リトライ,

    サーキットブレーカー, レートリミット など ▶ 様々なプロトコルをサポート + TCP, TLS, HTTP/1.1, HTTP/2, gRPC, MongoDB, DynamoDB, Redis など ▶ モニタリングのための機構も備わっている + L7トラフィックの豊富なメトリクス, 分散トレーシング など ▶ サービスディスカバリ ▶ xDS API を使うことで動的な設定変更が可能 + ホットリロード/リスタートもサポート ▶ Service Mesh アーキテクチャの Data Plane 向けに設計されている
  11. xDS API について ▶ xDS API = Envoy の設定を更新するための API

    + Envoy “が” xDS API Server に⾃⾝の設定情報を問い合わせる + この xDS API Server が Service Mesh でいう Control Plane に該当 ▶ Envoy から提供されている xDS API(⼀部) + LDS(Listener Discovery Service), CDS(Cluster Discovery Service) + EDS(Endpoint Discovery Service), RDS(Route Discovery Service) + SDS(Secret Discovery Service) + SDS Server からTLS証明書やシークレットが取得可能 + SPIRE Agent では SDS Server として振る舞う機能がサポートされている + SPIRE に TLS証明書 の管理(配布やローテーション)を⼀任できる
  12. ハイレベルアーキテクチャ Envoy SDS Server SPIRE Agent Service Service SDS Server

    SPIRE Agent Envoy mTLS X.509-SVID Private Key Trust Bundle X.509-SVID Private Key Trust Bundle [ Control Plane ] [ Data Plane ] [ Data Plane ] [ Control Plane ]
  13. K8s Worker Node SDS Server (UDS) SPIRE Agent Service Pod

    Envoy X.509-SVID Private Key Trust Bundle SDS Server (UDS) Mount SDS Server (UDS) SPIRE Agent Service Pod Envoy X.509-SVID Private Key Trust Bundle SDS Server (UDS) Mount K8s Worker Node mTLS Kubernetes 上に構築した Service Mesh gRPC gRPC
  14. SPIRE Agent で SDS Server 起動を有効化 agent { data_dir =

    "./.data" log_level = "DEBUG" server_address = "127.0.0.1" server_port = "8081" socket_path ="/tmp/agent.sock" trust_bundle_path = "./conf/agent/dummy_root_ca.crt" trust_domain = "example.org" enable_sds = true } plugins { ... }
  15. Envoy から SDS Server に通信するための設定 clusters: - name: spire_agent connect_timeout:

    0.25s http2_protocol_options: {} hosts: - pipe: path: /tmp/agent.sock
  16. SDS Server から TLS証明書(X.509-SVID)と秘密鍵を取得するための設定 tls_context: common_tls_context: tls_certificate_sds_secret_configs: - name: "spiffe://example.org/envoy"

    sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent ※ TLS証明書(X.509-SVID)の名前には Envoy に割り当てられた SPIFFE ID を指定すること
  17. SDS Server から CA証明書(Trust Bundle)を取得するための設定 tls_context: common_tls_context: validation_context_sds_secret_config: name: "spiffe://example.org"

    sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent ※ 検証コンテキストの名前には Trust Domain の SPIFFE ID を指定すること
  18. API Pod Envoy X.509-SVID Private Key Trust Bundle Envoy の設定ファイル例

    spiffe://example.org/api Web Pod Envoy X.509-SVID Private Key Trust Bundle spiffe://example.org/web mTLS SDS Server SDS Server
  19. Envoy の Listener に右記の設定を追加 tls_context: common_tls_context: # サーバー証明書として使⽤する X.509-SVID を

    SDS Server から取得 tls_certificate_sds_secret_configs: - name: "spiffe://example.org/api" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent combined_validation_context: # Web のクライアント証明書の SAN に含まれる SPIFFE ID のバリデーション default_validation_context: verify_subject_alt_name: - "spiffe://example.org/web" # Web のクライアント証明書を検証する Trust Bundle を SDS Server から取得 validation_context_sds_secret_config: name: "spiffe://example.org" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent API Pod Envoy X.509-SVID Private Key Trust Bundle spiffe://example.org/api SDS Server
  20. tls_context: common_tls_context: # クライアント証明書として使⽤する X.509-SVID を SDS Server から取得 tls_certificate_sds_secret_configs:

    - name: "spiffe://example.org/web" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent combined_validation_context: # API のサーバー証明書の SAN に含まれる SPIFFE ID のバリデーション default_validation_context: verify_subject_alt_name: - "spiffe://example.org/api" # API のサーバー証明書を検証する Trust Bundle を SDS Server から取得 validation_context_sds_secret_config: name: "spiffe://example.org" sds_config: api_config_source: api_type: GRPC grpc_services: envoy_grpc: cluster_name: spire_agent Envoy の Cluster に左記の設定を追加 Web Pod Envoy X.509-SVID Private Key Trust Bundle spiffe://example.org/web SDS Server
  21. OK Envoy API curl Envoy curl Envoy Valid API Client

    Invalid API Client NG API 0.0.0.0:8000 127.0.0.1:8080 :8000 :8000 ▶ minikube で Kubernetes Cluster を作成 + SPIRE Agent は Worker Node 起動しており Node Attestation は完了済み + Workload( API, Valid API Client, Invalid API Client )の登録も事前に実施済み ▶ Pod で Envoy とセットでサービスを3つ起動 + API( spiffe://example.org/api ) + ok という⽂字列を返す API で Valid API Client との通信を想定 + Valid API Client( spiffe://example.org/valid-api-client ) + API と通信可能なサービス(curl コンテナ) + Invalid API Client( spiffe://example.org/invalid-api-client ) + API と通信不可能なサービス(curl コンテナ) ▶ デモの中で確認していくこと + Envoy の設定 + API と Valid API Client が mTLS による相互認証を⾏えること + API と Invalid API Client が mTLS による相互認証を⾏えないこと + X.509-SVID がローテーションされる様⼦
  22. SPIRE の Federation API 実装について ▶ SPIRE Server : Trust

    Domain : Trust Bundle = 1 : 1 : 1 + Trust Bundle を使うことで同⼀の Trust Domain 配下の Workload の SVID が検証可能 ▶ Federation API + SPIRE Server が⾃⾝の Trust Bundle を JWK Set で公開する機能 + JWK Set の中⾝は X.509-SVID を検証するためのCA証明書, JWT-SVID を検証するための公開鍵 + SPIFFE で標準化されている SPIFFE Bundle Endpoint の仕様に準拠 ▶ Federation API を使うことで異なる Trust Domain 間で Trust Bundle が交換可能 + 別の SPIRE Server の Federation API にリクエストして Trust Bundle を取得する流れ ▶ 現在は Experimental な機能で今後改良が進められるとのこと + 詳細は https://github.com/spiffe/spire/issues/836 を参照
  23. Federation API のサンプルレスポンス { "keys": [ { "use": "x509-svid", "kty":

    "EC", "crv": "P-384", "x": "WjB-nSGSxIYiznb84xu5WGDZj80nL7W1c3zf48Why0ma7Y7mCBKzfQkrgDguI4j0", "y": "Z-0_tDH_r8gtOtLLrIpuMwWHoe4vbVBFte1vj6Xt6WeE8lXwcCvLs_mcmvPqVK9j", "x5c": [ "MIIBz " ] }, { "use": "jwt-svid", "kty": "EC", "kid": "BVjEYxb6i6OZU0gFTS3jW3al5GuSDw6H", "crv": "P-256", "x": "thNPDns_L_UzabUdL3sE2D2VNodI01x3rRcofG5MhmI", "y": "goq_SPZLI2Wk3uS_v5XRHXOHHwDwYR1PW2OIvcBWVgM" } ], "spiffe_refresh_hint": 15768000 } X.509-SVID を検証するための情報(CA証明書) JWT-SVID を検証するための情報(公開鍵)
  24. SPIRE Server の Federation 設定 server { trust_domain = "payments.example.org"

    ... experimental { bundle_endpoint_enabled = true bundle_endpoint_address = "0.0.0.0" // Default value bundle_endpoint_port = 443 // Default value } } ※ Federation API を介して Trust Bundle を別の SPIRE Server に “公開” する側の設定
  25. SPIRE Server の Federation 設定 server { trust_domain = "web.example.org"

    ... experimental { federates_with "payments.example.org" { bundle_endpoint_address = "https://web.example.org" bundle_endpoint_port = 443 // Default value bundle_endpoint_spiffe_id = "spiffe://payments.example.org/spire/server" // Default value bootstrap_bundle = "" // Path to SPIFFE bundle on disk. } } } ※ Federation API を介して Trust Bundle を別の SPIRE Server から “取得” する側の設定 federation_with で Federation する Trust Domain を指定
  26. SPIRE Server の Federation 設定 spiffe://payments.example.org SPIRE Server Service Mesh

    spiffe://web.example.org SPIRE Server Service Mesh (3) Federation により取得した Trust Bundle で SVID を検証できるので 異なる Trust Domain の Workload 同⼠で相互認証が可能になる (1) Federation API を利⽤して互いの Trust Bundle を交換 ※ これにより別 Trust Domain の SVID が検証可能になる (2) ⾃⾝の Trust Bundle と Federation 対象の Trust Bundle が 配布される (2) ⾃⾝の Trust Bundle と Federation 対象の Trust Bundle が 配布される
  27. Istio で構築された Service Mesh との Federation ▶ Istio には Federation

    API が実装されているのでそれを利⽤して SPIRE Server との Federation が可能 https://istio.io/docs/concepts/deployment-models/
  28. まとめ ▶ Data Plane として Envoy, Control Plane として SPIRE

    を使った Service Mesh + Envoy による認証と通信の暗号化 と SPIRE による証明書の⾃動管理 ▶ 証明書のローテーションも頻繁に⾏われるのでセキュリティ⾯でも良い + Zero Trust Network の考えに基づいたセキュアな Service Mesh が構築可能 + 悪意のあるものに証明書を奪われても被害を最⼩限に留められる ▶ Federation 機能も実装されているので Trust Domain の設計も柔軟に⾏える + Trust Domain = 組織, 実⾏環境, 部⾨ などセキュリティの境界を描くためのもの
  29. これから SPIFFE/SPIRE を始める⽅へ ▶ 公式チュートリアル + https://github.com/spiffe/spire/blob/master/doc/SPIRE101.md + https://spiffe.io/spire/getting-started-linux/ +

    https://spiffe.io/spire/getting-started-k8s/ ▶ SPIFFE コミュニティの Slack ワークスペース + http://spiffe.slack.com ▶ Qiita + https://qiita.com/tags/spiffe ▶ SPIFFE Meetup Tokyo #1 でのセッションが⼊⾨にオススメ! + https://spiffe-jp.connpass.com/event/126507/
  30. これから SPIFFE/SPIRE を始める⽅へ ▶ Scytale社のブログ + https://blog.scytale.io ▶ SPIFFE Community

    Day + 定期的に⾏われるイベント + Roadmap や SPIFFE/SPIRE の Update 紹介 + SPIFFE を採⽤している企業の事例発表 + Square, Uber, Pinterest, VMware など + インターネット中継もされる + 次の開催は JST で 10/12 (⼟) 1:30 ~ 7:00 + https://www.eventbrite.com/e/spiffe-community-day-october-2019- registration-67786454109
  31. マイクロサービスにおける他の課題をどのように解決するか? ▶ 今回紹介した SPIRE と Envoy を組み合わせた Service Mesh ではサービス間の認証と通信の暗号化しかクリア

    できていない ▶ Envoy の xDS Server として振る舞う Control Plane を増やして解決していく + OSS の Control Plane を使う + OPA を Envoy の External Authorization Filter として使⽤して SPIFFE ID ベースの認可なども⾏える + GitHub で⾃前 Control Plane を公開されている⽅もいるのでそこから要件に合うものを探すのも良い + ⾃ら Control Plane を実装する + xDS Server として振る舞うためには xDS Protocol の仕様に従う必要がある + 公式から提供されている Go と Java のライブラリを利⽤するのが良さそう + https://github.com/envoyproxy/go-control-plane + https://github.com/envoyproxy/java-control-plane ▶ Uber や Square は SPIRE を独⾃の Control Plane に統合して Service Mesh を構築しているとのこと + SPIFFE コミュニティの⽅からお伺いしました
  32. 今回紹介した Service Mesh と Istio との Identity 周りの⽐較 ▶ Istio

    のセキュリティ機能である Istio Security で扱われる Workload Identity は SPIFFE の 仕様に準拠しているので、SPIRE と実装は異なるものの今回紹介したものと同様に SPIFFE ベースの Workload Identity を使った Service Mesh を構築することが可能となって いるので、Workload Identity に関しては違いはないと思っています