Slide 1

Slide 1 text

SPIFFE Meetup Tokyo #2 Ryuma Yoshida @ryysud Securing the Service Mesh with SPIRE

Slide 2

Slide 2 text

#spiffejp

Slide 3

Slide 3 text

Ryuma Yoshida / @ryysud ▶ DMM.com にて Hadoop Ecosystem を利⽤したデータ 分析基盤の開発と運⽤に関わった後、2018年12⽉に ゼットラボ株式会社に⼊社 ▶ Kubernetes をベースとしたインフラ基盤の研究開発を ⾏っている ▶ 研究開発の⼀環で最近は SPIRE を触ることが多く、 SPIRE へのコントリビュートもしている

Slide 4

Slide 4 text

ゼットラボ株式会社 ▶ 2015年に設⽴されたヤフー株式会社100%⼦会社 ▶ ヤフーのインフラ課題に対して R&D でソリューション提供 ▶ Kubernetes as a Service を開発・提供 ▶ https://zlab.co.jp ▶ https://qiita.com/organizations/zlab

Slide 5

Slide 5 text

アジェンダ 1. Service Mesh に求められるもの 2. SPIFFE/SPIRE について 3. Envoy について 4. SPIRE と Envoy を組み合わせた Service Mesh 5. Service Mesh 間の Federation について 6. まとめ 7. Appendix

Slide 6

Slide 6 text

Service Mesh に求められるもの

Slide 7

Slide 7 text

▶ Protocols + Polyglot Programming が前提 ▶ Service Discovery ▶ Traffic Management + ロードバランシング + フェイルオーバー + サーキットブレーカー ▶ Observability + 分散トレーシング + ログ/メトリクス収集 ▶ Security + サービス間の通信の暗号化 + 認証/認可 https://www.redhat.com/cms/managed-files/service-mesh-1680.png Service Mesh に求められるもの = マイクロサービスにおける課題の解決

Slide 8

Slide 8 text

▶ サービス間の認証や通信の暗号化に使う TLS証明書 の管理 + サービスのスケールと共に証明書管理のコストが⾼くなる + 証明書がサービス数に⽐例して増えていく + ローテーションを⾏うにも⼿動管理の場合にはオペレーターの負担が増す + Zero Trust Network の考え⽅に基づき悪意のあるものに証明書を奪われても被 害を最⼩限に留められるのが望ましい Security における課題

Slide 9

Slide 9 text

何を使って Service Mesh を構築するか? ▶ 代表的なところだと Istio がある + 多機能であることのメリットは⼤きいがちゃんと運⽤できるか不安が残る + Kubernetes でしか利⽤できないので他の Container Orchestrator を使っ て Service Mesh を構築したいケースではどうするか? ▶ セキュアな Service Mesh を⼩さく始めたい⽅向け に Data Plane として Envoy, Control Plane として SPIRE を使った Service Mesh + Envoy による認証と通信の暗号化 と SPIRE による証明書の⾃動管理

Slide 10

Slide 10 text

SPIFFE/SPIRE について

Slide 11

Slide 11 text

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 など有名企業でも導⼊されている

Slide 12

Slide 12 text

SPIFFE で標準化されている主要コンポーネント ▶ SPIFFE ID + 認証対象(Node/Workload)を識別するためのURI 形式で構造化された⽂字列 + Workload = Unixプロセス や Container などソフトウェアの実⾏単位 + spiffe:/// で構成される + 例: 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

Slide 13

Slide 13 text

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 ...

Slide 14

Slide 14 text

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⽇現在)

Slide 15

Slide 15 text

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 を配布

Slide 16

Slide 16 text

Envoy について

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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証明書 の管理(配布やローテーション)を⼀任できる

Slide 19

Slide 19 text

SPIRE と Envoy を組み合わせた Service Mesh

Slide 20

Slide 20 text

ハイレベルアーキテクチャ 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 ]

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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 { ... }

Slide 23

Slide 23 text

Envoy から SDS Server に通信するための設定 clusters: - name: spire_agent connect_timeout: 0.25s http2_protocol_options: {} hosts: - pipe: path: /tmp/agent.sock

Slide 24

Slide 24 text

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 を指定すること

Slide 25

Slide 25 text

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 を指定すること

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Demo

Slide 30

Slide 30 text

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 がローテーションされる様⼦

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

https://github.com/zlabjp/spiffejp-demo

Slide 33

Slide 33 text

Service Mesh 間の Federation について

Slide 34

Slide 34 text

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 を参照

Slide 35

Slide 35 text

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 を検証するための情報(公開鍵)

Slide 36

Slide 36 text

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 に “公開” する側の設定

Slide 37

Slide 37 text

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 を指定

Slide 38

Slide 38 text

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 が 配布される

Slide 39

Slide 39 text

Istio で構築された Service Mesh との Federation ▶ Istio には Federation API が実装されているのでそれを利⽤して SPIRE Server との Federation が可能 https://istio.io/docs/concepts/deployment-models/

Slide 40

Slide 40 text

まとめ

Slide 41

Slide 41 text

まとめ ▶ Data Plane として Envoy, Control Plane として SPIRE を使った Service Mesh + Envoy による認証と通信の暗号化 と SPIRE による証明書の⾃動管理 ▶ 証明書のローテーションも頻繁に⾏われるのでセキュリティ⾯でも良い + Zero Trust Network の考えに基づいたセキュアな Service Mesh が構築可能 + 悪意のあるものに証明書を奪われても被害を最⼩限に留められる ▶ Federation 機能も実装されているので Trust Domain の設計も柔軟に⾏える + Trust Domain = 組織, 実⾏環境, 部⾨ などセキュリティの境界を描くためのもの

Slide 42

Slide 42 text

これから 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/

Slide 43

Slide 43 text

これから 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

Slide 44

Slide 44 text

We are hiring! ご興味ある⽅はゼットラボ社員に直接ご連絡ください

Slide 45

Slide 45 text

Thank you!

Slide 46

Slide 46 text

Appendix

Slide 47

Slide 47 text

マイクロサービスにおける他の課題をどのように解決するか? ▶ 今回紹介した 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 コミュニティの⽅からお伺いしました

Slide 48

Slide 48 text

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