Kubernetes Secret を利用した Spring アプリケーションの SSL 証明書管理

Kubernetes 環境で Secret を使用して SSL 証明書を管理するための Spring Boot 設定方法を説明します。PKCS12 形式と PEM 形式の証明書、それぞれに対応した設定を示します。

前提条件

1. Secret の作成

Kubernetes 上で事前に Secret を作成し、証明書と秘密鍵を格納します。

# PKCS12 形式 (推奨)
kubectl create secret generic ssl-secret \
  --from-file=server.p12=path/to/server.p12 \
  --from-file=truststore.p12=path/to/truststore.p12

# PEM 形式 (ホットリロードを有効にする場合)
kubectl create secret generic ssl-secret \
  --from-file=server.crt=path/to/server.crt \
  --from-file=server.key=path/to/server.key \
  --from-file=truststore.crt=path/to/truststore.crt

2. Pod へのマウント設定

Deployment で Secret をコンテナ内の指定パス(例: `/etc/secrets`)にマウントします。

spec:
  volumes:
    - name: ssl-secret-volume
      secret:
        secretName: ssl-secret
        defaultMode: 0400  # ファイル権限の制限
  containers:
    - name: app
      volumeMounts:
        - name: ssl-secret-volume
          mountPath: /etc/secrets
          readOnly: true    # ファイルの改変防止

方法一:PKCS12 形式証明書

1. Spring Boot 設定 (`application.yaml`)


server:
  port: 18083
  ssl:
    enabled: true
    key-store: /etc/secrets/server.p12      # Secret からマウントされたパス
    key-store-password: ${KEYSTORE_PASSWORD}
    key-password: ${KEY_PASSWORD}
    key-store-type: PKCS12
    key-alias: server
    trust-store: /etc/secrets/truststore.p12
    trust-store-password: ${TRUSTSTORE_PASSWORD}
    trust-store-type: PKCS12
    client-auth: need

2. 環境変数による注入

Deployment でパスワードを環境変数として渡します(ハードコーディングを避けるため)。

env:
  - name: KEYSTORE_PASSWORD
    valueFrom:
      secretKeyRef:
        name: ssl-secret
        key: keystore-password  # パスワードは Secret に個別に保存可能
  - name: TRUSTSTORE_PASSWORD
    valueFrom:
      secretKeyRef:
        name: ssl-secret
        key: truststore-password

方法二:PEM 形式証明書(ホットリロード対応)

1. Spring Boot 設定 (`application.yaml`)


server:
  port: 18083
  ssl:
    enabled: true
    bundle: "server-bundle"  # SSL Bundle 設定を使用

spring:
  ssl:
    bundle:
      pem:
        server-bundle:
          reload-on-update: true  # ホットリロードを有効化
          keystore:
            certificate: "/etc/secrets/server.crt"  # PEM 証明書
            private-key: "/etc/secrets/server.key"  # PEM 秘密鍵
        truststore-bundle:
          reload-on-update: true
          keystore:
            certificate: "/etc/secrets/truststore.crt"

証明書の更新戦略

1. Secret の更新

証明書の更新が必要な場合は、Kubernetes Secret を直接更新します。

kubectl create secret generic ssl-secret --from-file=server.p12=path/to/new-server.p12 --dry-run=client -o yaml | kubectl apply -f -

2. アプリケーションへの証明書リロードのトリガー

方法一:Pod のローリングリスタート(汎用的な方法)
Deployment の `annotations` を変更して、ローリングアップデートをトリガーします。

spec:
  template:
    metadata:
      annotations:
        timestamp: {{ timestamp }}  # 更新ごとに現在のタイムスタンプに置き換え
方法二:ホットリロード(Spring Boot 3.2+)
PEM 形式と `reload-on-update: true` を使用している場合、Spring Boot はファイル変更を自動検出し、証明書をリロードします。再起動は不要です。

完全な Deployment の例


apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-app
  template:
    metadata:
      labels:
        app: spring-app
    spec:
      volumes:
        - name: ssl-secret-volume
          secret:
            secretName: ssl-secret
            defaultMode: 0400
      containers:
        - name: app
          image: your-registry/spring-app:latest
          volumeMounts:
            - name: ssl-secret-volume
              mountPath: /etc/secrets
              readOnly: true
          env:
            - name: KEYSTORE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: ssl-secret
                  key: keystore-password
            - name: TRUSTSTORE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: ssl-secret
                  key: truststore-password
          ports:
            - containerPort: 18083

注意事項

1. ファイル権限

  • Secret がマウントされるディレクトリ(例: `/etc/secrets`)の権限を `0400` に設定し、秘密鍵の漏洩を防ぎます。
  • SecurityContext でコンテナユーザーの権限を制限します:
    
            securityContext:
              runAsNonRoot: true
              runAsUser: 1000
              readOnlyRootFilesystem: true  # ファイルシステムへの書き込みを禁止
            

2. 証明書のエイリアスの一貫性

PKCS12 形式を使用する場合、`server.p12` 内の証明書エイリアスと、設定の `key-alias: server` が一致していることを確認してください。

3. ログ監視

SSL ハンドシェイクの失敗問題をトラブルシューティングするために、SSL ログを有効にします。

logging:
  level:
    org.springframework.web: DEBUG
    org.apache.tomcat.util.net: DEBUG
上記の設定により、Spring Boot アプリケーションは Kubernetes 環境で Secret を使用して SSL 証明書を安全に管理でき、動的な更新にも対応できます。

タグ: Kubernetes Spring Boot SSL secret PKCS12

9月9日 00:17 投稿