# 機能設計書 121-証明書管理

## 概要

本ドキュメントは、kubeadmの証明書管理機能（`kubeadm certs`コマンド群）の設計を記述する。クラスター内の各種TLS証明書の生成、更新（ローテーション）、有効期限確認、CSR生成、および証明書キー生成を管理する機能である。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetesクラスターは、API Server、etcd、front-proxy、kubelet間の通信をTLS証明書で保護している。これらの証明書は有効期限があり、定期的な更新が必要となる。kubeadm certsは、クラスター管理者がこれらの証明書のライフサイクルを一元管理し、クラスターのセキュリティを維持するための機能を提供する。

**機能の利用シーン**：クラスター初期構築時のPKI作成（init時に自動呼び出し）、証明書の定期更新、証明書有効期限の確認、外部CA連携時のCSR生成、クラスター参加時の証明書キー生成など、クラスターライフサイクル全体にわたって利用される。

**主要な処理内容**：
1. `kubeadm certs renew` - 個別または全証明書の更新（ローカルCA使用）
2. `kubeadm certs check-expiration` - 全証明書の有効期限確認と表示
3. `kubeadm certs generate-csr` - 外部CA用の鍵とCSRの生成
4. `kubeadm certs certificate-key` - 証明書キーの生成（init --upload-certs用）
5. PKI作成 - CA証明書・サーバー証明書・クライアント証明書の階層的生成

**関連システム・外部連携**：etcd（etcd CA/サーバー/ピア/クライアント証明書）、API Server（サービング証明書、kubeletクライアント証明書）、front-proxy（front-proxy CA/クライアント証明書）、外部CAシステム（CSR生成時）。

**権限による制御**：証明書ファイルはコントロールプレーンノードの`/etc/kubernetes/pki`ディレクトリに保存される。ファイルシステムレベルのアクセス制御で保護されており、通常root権限が必要。kubeadm-config ConfigMapの読み取りにはクラスターへのアクセス権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 50 | kubeadm certs | 主画面 | クラスター内の各種TLS証明書の生成、ローテーション、管理を行う主処理 |
| 45 | kubeadm init | 参照画面 | init実行時にクラスター内の各種TLS証明書を自動生成する |
| 46 | kubeadm join | 参照画面 | 参加時にノード用証明書の生成・取得を行う |
| 52 | kubeadm upgrade | 参照画面 | アップグレード時に証明書の更新を行う |
| 51 | kubeadm kubeconfig | 参照画面 | kubeconfig生成時にクライアント証明書情報を埋め込む |

## 機能種別

証明書管理（PKI管理） / セキュリティ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --config | string | No | kubeadm設定ファイルパス | ファイル存在チェック |
| --cert-dir | string | No | 証明書ディレクトリパス（デフォルト: /etc/kubernetes/pki） | ディレクトリパスの妥当性 |
| --kubeconfig | string | No | kubeconfigファイルパス（デフォルト: /etc/kubernetes/admin.conf） | ファイル存在チェック |
| --kubeconfig-dir | string | No | kubeconfig出力ディレクトリ（generate-csr用） | ディレクトリパスの妥当性 |

### 入力データソース

- kubeadm設定ファイル（--config指定時）
- クラスター上のkubeadm-config ConfigMap（--config未指定時）
- 既存の証明書ファイル（/etc/kubernetes/pki/配下）
- デフォルト設定（上記いずれも利用できない場合のフォールバック）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CA証明書/鍵 | .crt/.key | Kubernetes CA、front-proxy CA、etcd CA |
| サーバー証明書/鍵 | .crt/.key | API Server、etcdサーバー、etcdピア証明書 |
| クライアント証明書/鍵 | .crt/.key | kubeletクライアント、front-proxyクライアント、etcdクライアント証明書 |
| SA鍵ペア | .key/.pub | ServiceAccountトークン署名用鍵ペア |
| CSRファイル | .csr | 外部CA用の証明書署名要求 |
| 有効期限情報 | テキスト/JSON | check-expirationコマンドの出力 |

### 出力先

- ファイルシステム（/etc/kubernetes/pki/配下）
- 標準出力（有効期限情報、証明書キー）

## 処理フロー

### 処理シーケンス

```
1. PKI作成（CreatePKIAssets）
   └─ 証明書リストの決定（ローカルetcd有無で分岐）
2. 証明書ツリーの構築（CertTree）
   └─ CA → リーフ証明書のマッピング作成
3. 各CAについてループ
   └─ 既存CA確認 → なければ新規生成
4. 各リーフ証明書についてループ
   └─ 既存証明書確認 → なければCAから署名して生成
5. SA鍵ペアの生成
   └─ 既存鍵確認 → なければ新規生成
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{etcdはローカル?}
    B -->|Yes| C[GetDefaultCertList]
    B -->|No| D[GetCertsWithoutEtcd]
    C --> E[CertTree構築]
    D --> E
    E --> F{CAごとにループ}
    F --> G{CA証明書は存在する?}
    G -->|Yes| H{CA鍵は存在する?}
    G -->|No| I[新規CA生成]
    H -->|Yes| J[既存CA使用]
    H -->|No| K{全リーフ証明書が存在する?}
    K -->|Yes| L[スキップ - 外部CA]
    K -->|No| M[エラー]
    I --> J
    J --> N{リーフ証明書ごとにループ}
    N --> O{証明書は存在する?}
    O -->|Yes| P[検証してスキップ]
    O -->|No| Q[CAで署名して生成]
    P --> N
    Q --> N
    N --> R[SA鍵ペア生成]
    R --> S[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-121-1 | 既存証明書再利用 | 証明書が既に存在し有効であればスキップする | 全証明書生成/更新時 |
| BR-121-2 | 外部CA検出 | CA証明書が存在するがCA鍵が存在しない場合、外部CAと判定する | PKI作成時 |
| BR-121-3 | 証明書バックデート | 小さな時刻ジャンプを許容するため、証明書のNotBefore値をバックデートする | 全証明書生成時 |
| BR-121-4 | 無条件更新 | 証明書更新は有効期限に関係なく無条件で実行される | renew実行時 |
| BR-121-5 | 暗号化アルゴリズム | ClusterConfigurationのencryptionAlgorithmTypeに従う | 全鍵生成時 |
| BR-121-6 | 有効期間設定 | CertificateValidityPeriod/CACertificateValidityPeriodに従う | 証明書生成時 |

### 計算ロジック

証明書のNotBefore/NotAfter算出：
- `NotBefore = kubeadm起動時刻 - CertificateBackdate`
- CA証明書: `NotAfter = 起動時刻 + CACertificateValidityPeriod`
- リーフ証明書: `NotAfter = 起動時刻 + CertificateValidityPeriod`

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを直接操作しない。Kubernetes APIを介してConfigMap（kubeadm-config）の読み取りを行う場合がある。

| 操作 | 対象リソース | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定読み取り | ConfigMap (kubeadm-config) | SELECT | クラスター構成情報の取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 証明書読み込みエラー | 証明書ファイルが破損 | 証明書ファイルの再生成 |
| - | CA鍵不在 | 外部CA使用時にrenewを試行 | 外部CAで証明書を再発行 |
| - | 署名検証エラー | 証明書がCAで署名されていない | 正しいCAで再署名 |
| - | SAN不一致 | 既存証明書のSANが設定と不一致 | 証明書の再生成 |
| - | API Server接続エラー | クラスターからの設定取得失敗 | デフォルト設定にフォールバック |

### リトライ仕様

API Serverからの設定取得失敗時は、デフォルト設定にフォールバックする。証明書ファイルの書き込み自体にはリトライは行われない。

## トランザクション仕様

ファイルシステム操作であり、データベーストランザクションは存在しない。証明書ファイルは個別に書き込まれ、途中で失敗した場合は既に書き込まれたファイルはそのまま残る（冪等性を持つ設計のため、再実行で解決可能）。

## パフォーマンス要件

証明書の生成は暗号化演算を含むが、クラスターライフサイクルイベント（初期化・更新）時のみ実行されるため、厳密なパフォーマンス要件はない。通常、全証明書の生成は数秒以内に完了する。

## セキュリティ考慮事項

- CA秘密鍵は最も機密性の高いファイルであり、コントロールプレーンノードのみに保存される
- 証明書ファイルのパーミッションはkubeadmが適切に設定する
- 外部CAモードでは秘密鍵をkubeadmの管理外に置くことが可能
- 証明書キー（certificate-key）は暗号的に安全な乱数で生成される
- 証明書の有効期限は定期的に確認し、更新する運用が推奨される

## 備考

- kubeadm certs renewの実行後は、kube-apiserver、kube-controller-manager、kube-scheduler、etcdの再起動が必要
- 証明書の更新はクラスター停止なしに実行可能だが、コンポーネントの再起動が必要
- 外部CAモードの詳細はKubernetes公式ドキュメントの「External CA Mode」を参照

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

証明書定義の構造体とツリー構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | certlist.go | `cmd/kubeadm/app/phases/certs/certlist.go` | KubeadmCert構造体（44-56行目）、CertificateTree型（145行目）、Certificates型（236行目）の定義 |
| 1-2 | certlist.go | `cmd/kubeadm/app/phases/certs/certlist.go` | GetDefaultCertList()（249-264行目）で定義される全証明書のリスト |
| 1-3 | certlist.go | `cmd/kubeadm/app/phases/certs/certlist.go` | 各証明書定義関数（KubeadmCertRootCA: 279行目、KubeadmCertAPIServer: 293行目等） |

**読解のコツ**: KubeadmCert構造体のCANameフィールドが空の場合はCA証明書、値がある場合はそのCAに署名されるリーフ証明書を意味する。configMutatorsは初期化設定に応じてAltNames等を動的に設定するための関数スライス。

#### Step 2: エントリーポイントを理解する

CLIコマンドの構造とサブコマンドの登録を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | certs.go | `cmd/kubeadm/app/cmd/certs.go` | newCmdCertsUtility()（104-117行目）でサブコマンド構造を理解 |
| 2-2 | certs.go | `cmd/kubeadm/app/cmd/certs.go` | getRenewSubCommands()（233-312行目）で更新コマンドの動的生成を理解 |

**主要処理フロー**:
1. **104-117行目**: メインコマンド構築 - renew、check-expiration、certificate-key、generate-csrの4サブコマンド登録
2. **233-312行目**: renewサブコマンドの動的生成 - renewal.Managerから証明書リストを取得し各証明書用のコマンドを生成
3. **320-344行目**: renewCert() - 個別証明書の更新ロジック（ローカルCA使用）

#### Step 3: PKI作成フローを理解する

証明書の実際の生成処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | certs.go | `cmd/kubeadm/app/phases/certs/certs.go` | CreatePKIAssets()（45-72行目）がメインのPKI作成エントリーポイント |
| 3-2 | certlist.go | `cmd/kubeadm/app/phases/certs/certlist.go` | CreateTree()（148-209行目）がCAとリーフ証明書を再帰的に作成 |
| 3-3 | certs.go | `cmd/kubeadm/app/phases/certs/certs.go` | writeCertificateFilesIfNotExist()（210-252行目）が冪等な証明書書き込み |

**主要処理フロー**:
- **45-72行目**: etcd設定に応じた証明書リスト決定、ツリー構築、SA鍵ペア生成
- **107-129行目**: CreateCACertAndKeyFiles() - CA証明書の生成
- **133-144行目**: CreateCertAndKeyFilesWithCA() - CA読み込みとリーフ証明書生成

#### Step 4: 有効期限確認を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | certs.go | `cmd/kubeadm/app/cmd/certs.go` | newCmdCertsExpiration()（430-477行目） |
| 4-2 | certs.go | `cmd/kubeadm/app/cmd/certs.go` | fetchCertificateExpirationInfo()（376-423行目）で各証明書の有効期限情報を収集 |

### プログラム呼び出し階層図

```
newCmdCertsUtility()
    |
    ├─ newCmdCertsRenewal()
    |      └─ getRenewSubCommands()
    |             └─ renewCert()
    |                    └─ renewal.NewManager()
    |                    └─ rm.RenewUsingLocalCA()
    |
    ├─ newCmdCertsExpiration()
    |      └─ getInternalCfg()
    |      └─ renewal.NewManager()
    |      └─ fetchCertificateExpirationInfo()
    |
    ├─ newCmdCertificateKey()
    |      └─ copycerts.CreateCertificateKey()
    |
    └─ newCmdGenCSR()
           └─ runGenCSR()
                  ├─ certsphase.CreateDefaultKeysAndCSRFiles()
                  └─ kubeconfigphase.CreateDefaultKubeConfigsAndCSRFiles()

CreatePKIAssets() [init時に呼び出し]
    ├─ GetDefaultCertList() / GetCertsWithoutEtcd()
    ├─ CertTree.CreateTree()
    |      ├─ pkiutil.NewCertificateAuthority()
    |      ├─ writeCertificateAuthorityFilesIfNotExist()
    |      └─ KubeadmCert.CreateFromCA()
    |             └─ pkiutil.NewCertAndKey()
    |             └─ writeCertificateFilesIfNotExist()
    └─ CreateServiceAccountKeyAndPublicKeyFiles()
```

### データフロー図

```
[入力]                       [処理]                              [出力]

kubeadm設定ファイル ───▶ configutil.LoadOrDefaultInit ───▶ InitConfiguration
                              │
kubeadm-config ConfigMap ──▶  │
                              │
InitConfiguration ──────▶ CreatePKIAssets() ──────────────▶ CA証明書/鍵 (.crt/.key)
                              │                              サーバー証明書/鍵
                              │                              クライアント証明書/鍵
                              │                              SA鍵ペア (.key/.pub)
                              │
既存証明書ファイル ─────▶ renewCert() ─────────────────▶ 更新された証明書/鍵
                              │
renewal.Manager ───────▶ fetchCertificateExpiration ──▶ 有効期限情報（stdout）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| certs.go | `cmd/kubeadm/app/cmd/certs.go` | ソース | CLIコマンド定義（renew、check-expiration、generate-csr、certificate-key） |
| certs.go | `cmd/kubeadm/app/phases/certs/certs.go` | ソース | PKI作成・検証ロジック（CreatePKIAssets等） |
| certlist.go | `cmd/kubeadm/app/phases/certs/certlist.go` | ソース | 証明書定義リストとツリー構造 |
| renewal/ | `cmd/kubeadm/app/phases/certs/renewal/` | ソース | 証明書更新マネージャー |
| copycerts/ | `cmd/kubeadm/app/phases/copycerts/` | ソース | 証明書コピーと証明書キー生成 |
| pkiutil/ | `cmd/kubeadm/app/util/pkiutil/` | ソース | PKIユーティリティ（証明書生成、読み込み、書き込み） |
| constants/ | `cmd/kubeadm/app/constants/` | ソース | 証明書ファイル名、パス等の定数定義 |
| kubeconfig/ | `cmd/kubeadm/app/phases/kubeconfig/` | ソース | kubeconfig生成（CSR生成時に連携） |
