Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Kubernetes でもJava アプリでTLS 接続を終端したい
Search
Cybozu
PRO
June 16, 2024
Programming
2
210
Kubernetes でもJava アプリでTLS 接続を終端したい
2024年6月16日 (日) に開催されたJJUG CCC Spring 2024ランチセッション(6月16日 (日) 12:00 - 12:45)の発表資料です。
Cybozu
PRO
June 16, 2024
Tweet
Share
More Decks by Cybozu
See All by Cybozu
サイボウズ 開発本部採用ピッチ / Cybozu Engineer Recruit
cybozuinsideout
PRO
9
41k
テクニカルライティング
cybozuinsideout
PRO
3
100
サイボウズのアジャイルクオリティ2024
cybozuinsideout
PRO
2
88
モブに早く慣れたい人のためのガイド2024
cybozuinsideout
PRO
2
90
モバイル
cybozuinsideout
PRO
2
64
ソフトウェアライセンス
cybozuinsideout
PRO
2
52
ソフトウェアテスト
cybozuinsideout
PRO
2
80
自動テスト
cybozuinsideout
PRO
2
80
Docker入門2024
cybozuinsideout
PRO
2
120
Other Decks in Programming
See All in Programming
Scala におけるコンパイラエラーとの付き合い方
chencmd
1
150
フロントエンドカンファレンス北海道2024 『小規模サイトでも使えるVite 〜HTMLコーディングをよりスマートに〜』長谷川広武(ハム)
h2ham
1
2.5k
null or undefined
susisu
20
4k
iOSDC 2024
auramagi
3
590
プログラマのための音楽入門
cheebow
4
540
オートマトン学習しろ / Do automata learning
makenowjust
3
100
健康第一!MetricKitで始めるアプリの健康診断 / App Health Checkups Starting with MetricKit
nekowen
4
790
楽しく簡単に!QRコードの読み取り機能を実装しよう
penguinsan_pg
1
190
全力の跳躍を捉える計測アプリを作る
ogijun2018
0
1k
dotfiles について話したい #湘なんか
stefafafan
2
280
ゲームボーイアドバンスでSwiftを動かそう
k_koheyi
0
510
LangGraphでのHuman-in-the-Loopの実装
os1ma
3
550
Featured
See All Featured
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
165
48k
It's Worth the Effort
3n
182
27k
What's in a price? How to price your products and services
michaelherold
241
11k
We Have a Design System, Now What?
morganepeng
48
7.1k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
354
29k
Scaling GitHub
holman
458
140k
Building an army of robots
kneath
302
42k
How GitHub Uses GitHub to Build GitHub
holman
472
290k
The Illustrated Children's Guide to Kubernetes
chrisshort
46
48k
Done Done
chrislema
180
16k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
27
8.9k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
45
4.8k
Transcript
Kubernetes でも Java アプリで TLS 接続を終端したい JJUG CCC 2024 Spring
#jjug_ccc_b 2024年6⽉16⽇ サイボウズ株式会社 齋藤 耕平 1
はじめまして︕ ▌齋藤 耕平 (さいとう こうへい) l サイボウズ株式会社 l 2022年中途⼊社 l
バックエンドエンジニア l グローバル向け AWS 版 kintone の開発/運⽤ ▌GitHub: github.com/sightseeker ▌Xアカウント: @SightSeekerTw 2 Tw は Twitter の 識別⽤につけてた名残り
チームワークあふれる 社会を創る サイボウズの理念は「チームワークあふれる社会を創る」こと。 私たちはその理念に沿ってチームワークを⽀えるソフトウェアを 開発し続けてきました。 サイボウズという会社
主⼒製品群 中⼩企業向けグループウェア 78,000社 中堅・⼤規模組織向けグループウェア 7,800社 業務システム構築プラットフォーム 32,000社 メール共有システム 14,200社 ※2023年11⽉末時点
4
kintone つかってますか︖ 5
あなたの近くでも “kintone” を使った業務があるかも︖ 6
私事ですが。 ▌最近⾞を乗り換えた ▌⾃動⾞の取得(購⼊)には、保管場所使⽤承諾証明書が必要 ▌⾃宅はマンションなので管理会社に発⾏を依頼する必要があった 7 乗り換え
従来の⼿続きの流れ ▌所定の⽤紙に書いて、管理会社に郵送 ▌管理会社に保管場所使⽤承諾証明書を郵送で送りかえしてもらう 8 郵送 発⾏ 郵送 リードタイム 1週間
申請, 発⾏がオンラインで完結するようになっていた ▌Webフォームに必要情報を⼊⼒して送信 ▌数時間後、承諾証明書のPDFのダウンロードURLがメールで送られてきた 9 Webフォームに申請内容を記⼊して送信 証明書をPDF 形式で発⾏ ダウンロード
1週間かかってた ⼿続きが数時間に︕ 10
11 申請フォームのURLに kintone の⽂字が !?
form.kintoneapp.com とは︖ ▌トヨクモ (株) さんの提供する FormBridge というサービスのURL︕ 12 画像出典: “トヨクモ
(株) FormBridge 製品紹介ページ https://fb.kintoneapp.com/"
kintone 最⾼︕ 13
ここからが本題 14
年々、セキュリティ要求/要件 が厳しくなってきましたね︕(雑) ▌ISMS ▌GRPR ▌PCI DSS ▌HIPAA etc… 15
最近は Java アプリ も Kubernetes に デプロイすること 多くなってきたよね︕ 16
Kubernetes クラスタ内のトラフィックを キャプチャ されても/しても ⼤丈夫なようにしときたい︕ 17
通信は暗号化 されていてほしい︕ 18
ということで、本⽇は、 19
Kubernetes でも Java アプリで TLS 接続を終端したい 20
TLS接続を終端できるようにするには何が必要か︖ 21
サーバー(TLS)証明書 22 誰のもの︖ (ドメイン名) いつまで有効︖ 発⾏者は︖ 本物︖ (発⾏者の署名)
証明書はどうやって発⾏する︖ ▌Certification Authority (CA, 認証局) に CSR (Certificate Signing Request)
を作って依頼発⾏してもらう 23
保管場所承諾証明書の話に置き換えると、こんな感じ︖ 保管場所承諾証明書 TLS 証明書 保管場所承諾書の申請書 (あるいは申請フォーム) CSR (Certificate Signing Request)
マンションの管理会社 Certification Authority (CA, 認証局) 24
パブリックドメインの証明書の認証局は︖ 25
プライベートネットワークのプライベートなドメインの認証局は︖ ▌オレオレ認証局 (独⾃に発⾏したキーペアを利⽤) ▌Private PKI サービスを利⽤ l DigiCert Private PKI
l Venafi Zero Touch PKI l HashiCorp Vault ▌クラウドベンダー提供のプライベートCAサービス l AWS Private Certificate Authority l Microsoft Active Directory Certificate Service l Google Cloud Certificate Authority Service 26
Kubernetes 内では︖ cert-manager の Issuer/ClusterIssuer を置くのが⼀般的 だと思う。 27
cert-manager とは ▌Cloud Native Computing Foundation のプロジェクトの⼀つ ▌Kubernetesクラスタ内でアプリケーション⽤の TLS 証明書の発⾏と管理を⾃動化するためのツール
(K8s の カスタムコントローラ/CRD で構成される) ▌証明書は Secret リソースとして発⾏され、 Pod にマウントして利⽤できる 28
Issuer とは ▌意味: 〔株式や本などの〕発⾏⼈[者・社] (英辞郎 on the WEB より) ▌
証明書を発⾏するための設定を定義する cert-manager のカスタムリソース ▌ 証明書を発⾏するための具体的な⽅法や 認証局(CA)の情報が含まれている ▌ ただの Issuer はデプロイされてる Namespace 内でのみ利⽤可能 ▌ ClusterIssuer は Namespace 横断で使える Issuer 29 証明書を発⾏するよ︕ Issuer さん
Issuer には多様な選択肢がある ▌⾃前で⽤意した CA ⽤のキーペアを利⽤したものや、 各種ベンダー提供の PKI, プライベート CA サービスを
Issuer として設定可能 ※各種PKI, プライベートCAサービス を Issuer として利⽤するには 別途対応するカスタムコントローラ, CRD をデプロイが必要な場合がある 30
TLS証明書を利⽤するまでの流れ ▌(cert-manager を Kubernetes にデプロイ)今回は説明を省略 ▌Issuer リソースを作成 ▌Issuer に証明書を発⾏してもらう l
Certificate リソースを作成 l Issuer が Certificate リソースに対応する証明書を発⾏ (証明書の Secret が作成される) ▌発⾏された証明書の Secret を アプリのコンテナの所定のパスにマウントして利⽤する 31
ざっくりこんな雰囲気 32 CSR が含まれるリソース
Issuer を作成する (1/2) ▌ openssl コマンドで CA ⽤のキーペアを作成 (Private PKI
サービスなどを使わない場合) 33 # CA のプライベートキーの作成 (RSA 2048 bit) openssl genrsa -out ca.key 2048 # プライベートキーを使って CA の証明書の発⾏ openssl req -x509 -new -nodes -key ca.key ¥ -subj "/CN=sandbox" -days 3650 -out ca.crt ▌ ⽣成したキーペアの Secret を作成 # キーペアの Secret を作成 kubectl create secret tls ca-key-pair --cert=ca.crt --key=ca.key
Issuer に証明書を発⾏してもらう 34 ▌ Certificate リソースのマニフェストを作成 ▌ Keystore のパスワードの Secret
を作成する kubectl create secret generic keystore-password ¥ --from-literal=password=changeit apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: demo-cert spec: secretName: sandbox-cert-tls duration: 24h renewBefore: 12h subject: organizations: - My Organization commonName: demo dnsNames: - demo.sandbox.svc.cluster.local keystores: jks: create: true passwordSecretRef: name: keystore-password key: password issuerRef: name: sandbox-issuer kind: Issuer group: cert-manager.io kubectl apply -f demo-cert.yaml demo-cert.yaml 有効期間, 再発⾏時期 誰のものか TLS接続を終端するドメイン名 証明書のフォーマット (ここではJKSのみ定義) ※PKCS12については省略してます 発⾏者 (Issuer) の情報
⽣成された証明書の Secret の中⾝ 35 apiVersion: v1 type: kubernetes.io/tls kind: Secret
metadata: annotations: cert-manager.io/alt-names: demo.sandbox.svc.cluster.local cert-manager.io/certificate-name: demo-cert cert-manager.io/common-name: demo cert-manager.io/ip-sans: "" cert-manager.io/issuer-group: cert-manager.io cert-manager.io/issuer-kind: Issuer cert-manager.io/issuer-name: sandbox-issuer cert-manager.io/subject-organizations: My Organization cert-manager.io/uri-sans: "" labels: controller.cert-manager.io/fao: "true" name: demo-cert-tls namespace: sandbox data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tL (省略) keystore.jks: /u3+7QAAAAIAAAACAAAAAQAL (省略) tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS (省略) tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSB (省略) truststore.jks: /u3+7QAAAAIAAAABAAAAAgACY2EA (省略) truststore.p12: MIIEFgIBAzCCA+IGCSqGSIb3DQEH (省略) Certificate や Issuer に関する注釈 PEM形式の TLS 証明書キーペア (tls.crt, tls.key) PEM形式の Issuer の CA 証明書 (ca.crt) JKS形式の TLS 証明書 (keytstore.jks) JKS形式の Issuer の CA 証明書 (truststore.jks) PKCS12形式の TLS 証明書 (keystore.p12) PKCS12形式の Issuer のCA 証明書 (truststore.p12) ※Base64 Encoded
証明書の中⾝の確認 36 Subject: O=My Organization CN=demo Subject Alt Name: DNS:demo.sandbox.svc.cluster.local
Issuer: CN=sandbox Infoaccess: undefined Validfrom: Jun 10 07:30:24 2024 GMT Validto: Jun 11 07:30:24 2024 GMT Fingerprint: 4D:BA:29:C2:9D:91:47:A7:7E:24:43:90:B0:F8:F0:9A:94:7B:56:84 Fingerprint256: A1:9F:94:E7:1A:8B:C7:9A:DF:A7:A1:C6:C9:03:E8:81:6D:E6:EF:72:6D:0D:7A:BC: 0D:02:2B:46:1A:1D:17:7B Keyusage: undefined Serialnumber: d14d6498d92f7e63ef57724579212a7a 有効期間 (Validfrom, Validto) 誰のものか (Subject) TLS接続を終端するドメイン名 (Subject Alt Name) 発⾏者 (Issuer) の情報 発⾏された証明書の識別情報 Fingerprint(256), Serialnumber
その証明書を使って Spring Boot アプリで TLS 接続を終端できるようにするには︖ 37 申し訳程度の Java 要素
Spring Boot でのマウントされた証明書の設定例 (JKS形式) 38 # サーバ証明書が⼊ってる keystore ファイルのパス spring.ssl.bundle.jks.demo.keystore.location=/path/to/cert/keystore.jks
# keystore のパスワード spring.ssl.bundle.jks.demo.keystore.password=changeit # keystore の種別 (JKS) spring.ssl.bundle.jks.demo.keystore.type=JKS # keystore 内の証明書のエイリアス spring.ssl.bundle.jks.demo.key.alias=certificate # 使⽤する SSL Bundle の名前 server.ssl.bundle=demo # LISTEN ポート server.port=8443 application.properties
Spring Boot でのマウントされた証明書の設定例 (PKCS12形式) 39 # サーバ証明書が⼊ってる PKCS12 形式のファイルのパス spring.ssl.bundle.jks.demo.keystore.location=/path/to/cert/keystore.p12
# keystore のパスワード spring.ssl.bundle.jks.demo.keystore.password=changeit # keystore の種別 (PKCS12) spring.ssl.bundle.jks.demo.keystore.type=PKCS12 # keystore 内の証明書のエイリアス spring.ssl.bundle.jks.demo.key.alias=1 # 使⽤する SSL Bundle の名前 server.ssl.bundle=demo # LISTEN ポート server.port=8443 application.properties 最近は Java 界隈も JKS から PKCS12 に移⾏しつつあるよね︕
Spring Boot でのマウントされた証明書の設定例 (PEM形式) 40 # 証明書のパス spring.ssl.bundle.pem.demo.keystore.certificate=/path/to/cert/tls.crt # 証明書の秘密鍵のパス
spring.ssl.bundle.pem.demo.keystore.private-key=/path/to/cert/tls.key # 使⽤する SSL Bundle の名前 server.ssl.bundle=demo # LISTEN ポート server.port=8443 application.properties Tomcat と Netty 限定︕
これで、 Spring Boot で TLS 接続を終端できるようになったけれど クライアント的には… 41
42
クライアントが通信先はその証明書を信頼していない 43 Issuer (CA) あるいはその上位の CA の証明書を クライアント側で持っていて、信頼するものとして認識必要がある Issuer (CA)
の発⾏した証明書を信頼する必要がある
▌パブリックな CA の ルート証明書は標準でOSにバンドルされてるけれど ▌プライベートな CA の証明書は個別でインストールする必要がある 44
PEM や PKCS12 などアプリやコンテナによって必要な形式が違うし 何よりも様々なアプリのコンテナ内の 信頼するCA証明書が統⼀されてることを保証しにくい Issuer の CA証明書 がインポートされている必要があるけれど
▌コンテナイメージをビルドするときに証明書をインストールする ▌initContainer で証明書をインストールして emptyDir 経由でアプリ のコンテナに共有する 45 課題
信頼するCA証明書は ConfigMap や Secret で配布して 各Podがマウントすればよいのでは︖ 46 それでも PEM と
PKCS12 と JKS それぞれの形式で中⾝が同じ信頼するCA証明書 を同じものを作るのツラい
▌そんな悩みを解決してくれる trust-manager 47
trust-manager とは ▌cert-manager のプロジェクトで提供されている もう⼀つのカスタムコントローラと CRD のセット 48
信頼するCA証明書の設定 (Bundle) 49 apiVersion: trust.cert-manager.io/v1alpha1 kind: Bundle metadata: name: mybundle
spec: sources: - useDefaultCAs: true - secret: name: ca-cert-secret key: ca.crt target: configMap: key: "ca-certificates.crt" additionalFormats: jks: key: "bundle.jks" pkcs12: key: "bundle.p12" namespaceSelector: matchLabels: sandbox: "true" パブリックな CA のルート証明書など useDefaultCAs -> Debian コンテナにデフォで⼊ってるやつ Issuer の CA 証明書 の Secret (Secret 以外にも In-line で PEMの内容を書いたりもできる) 発⾏する証明書のフォーマット (configMap, additinalFormats) ※keystoreのパスワード設定は省略してます 信頼するCA証明書のConfigMapを配布先 Namespace の指定 合成した CA 証明書ファイルを
こんな ConfigMap を作ってくれる 50 apiVersion: v1 binaryData: bundle.jks: /u3+7QAAAAIAAACCAAAAAgCkMDJlZDBlYjJ8Y249ZW50cnVzd (省略)
bundle.p12: MIMCtEUCAQMwgwK0PQYJKoZIhvcNAQcBoIMCtC0EgwK0KDCD (省略) data: ca-certificates.crt: | -----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE (省略) -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx (省略) ----END CERTIFICATE----- . . . kind: ConfigMap metadata: annotations: trust.cert-manager.io/hash: (省略) labels: trust.cert-manager.io/bundle: mybundle name: mybundle JKS 形式の CA 証明書 PKCS12 形式の CA 証明書 PEM 形式の CA 証明書 信頼できる CA 証明書が 各フォーマットですべて⼊っていて 中⾝が揃っている
要は、この ConfigMap は macOS でいうところの キーチェーンアクセス に登録されてる 信頼できる証明書の全量 51
あとは Pod にマウントして使うだけ ▌PEM形式は適切なパスにマウントするのが良さそう (Linux はディストリビューションによってパスが異なる) 52 /etc/ssl/certs/ca-certificates.crt // Debian/Ubuntu/Gentoo
etc. /etc/pki/tls/certs/ca-bundle.crt // Fedora/RHEL 6 /etc/ssl/ca-bundle.pem // OpenSUSE /etc/pki/tls/cacert.pem // OpenELEC /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem // CentOS/RHEL 7 /etc/ssl/cert.pem // Alpine Linux ▌Java で使いたい場合は適当なところに置いてオプションで指定が良さそう︖ java –Djavax.net.ssl.trustStore=/app/resources/bundle.p12 ¥ -Djavax.net.ssl.trustStorePassword=changeit ¥ -Djavax.net.ssl.trustStoreType=PKCS12 -jar /app/app.jar
まとめ 53
cert-manager / trust-manager 最⾼︕ ▌証明書を作るのに、クセ強めな openssl コマンドを駆使しなくていい ▌証明書の発⾏に必要な定義ファイル (Certificate のマニフェスト)
は YAML で可読性が⾼い︕ ▌プライベートでも TLS 証明書, CA 証明書の発⾏、管理、利⽤が楽︕ ▌PEM だけでなく Java でも使える JKS, PKCS12 形式もサポート︕ 54 Kubernetes でも Java アプリで TLS 接続を終端するのは難しくないよね︕
ご清聴ありがとうございました。 55
紹介しきれなかった話 ▌ cert-manager / trust-manager のインストール⽅法 (helmで簡単に⼊れられるよ︕) ▌ 証明書のローテーション l
cert-manager は Certificate に有効期間を定義できて、 ⾃動的に対応する証明書の Secret をローテーションしてくれる l Secret の値が更新されても、Pod にマウントされてる証明書は更新されないので、Pod の置き換えが必要 l Secret や ConfigMap の更新をトリガーに rollout restart してくれるコントローラ “wave-k8s/wave” とかを⼊れておくのが良さそう (Deployment や StatefulSet, DaemonSet リソースの annotation で対象を識別する) ▌ 1枚の TLS 証明書 の Secret を複数の replicas Pod で使い回すのどうなの︖ っていう気持ちにも対応できる 公式 CSI Driver もあるよ ▌ Issuer (CA) の階層化, 証明書発⾏の承認プロセス, 証明書のRBAC ▌ Replicas Pod 間の通信で IP SANs を使いたいとき 56