# SSL/TLS証明書

SSL/TLS証明書はEMQXのセキュリティアーキテクチャの中核をなす要素です。これにより、ネットワーク通信の認証、暗号化、およびデータの整合性が提供されます。EMQXでは、以下のシナリオで安全な接続を確立するためにSSL/TLS証明書が必要です。

- TLS経由のMQTT接続（MQTTS）
- WebSocket Secure（WSS）経由のMQTT接続
- HTTPSサービスおよびダッシュボードアクセス
- TLS対応の外部接続（例：データ統合）

EMQX 6.1以降、証明書は単なるファイルパスではなく再利用可能なリソースとして扱われます。EMQXは以下の2つの証明書管理方式をサポートしています。

1. パスベース証明書（従来型）：設定内でファイルパスを直接参照する方式
2. 管理証明書（EMQX 6.1以降）：名前で参照される再利用可能なリソースとして管理する方式

どちらの方式も標準のPEMエンコードファイルを使用し、EMQXのSSL/TLS実装と完全に互換性があります。

本ページでは以下のトピックを扱います。

- SSL/TLS証明書の取得方法
- EMQXでの証明書管理
- 複数証明書のサポート
- SSL/TLS証明書の更新方法

## SSL/TLS証明書の取得

EMQXで証明書を使用する前に、信頼できるソースから証明書を取得する必要があります。取得方法は環境やセキュリティ要件によって異なります。

### 証明書取得の選択肢

TLS証明書は以下の方法で取得可能です。

- **自己署名証明書**

    独自の認証局（CA）によって発行される証明書です。デフォルトで信頼されないため、テストや管理された環境での利用が推奨されます。

- **信頼されたCAによる証明書の申請または購入**

   公共または企業のCAから取得する証明書で、例として以下があります。

   - [Let's Encrypt](https://letsencrypt.org/)
   - クラウドプロバイダー（例：Huawei Cloud、Tencent Cloud）
   - 商用CA（例：[DigiCert](https://www.digicert.com/)）

   本番環境や企業向けのデプロイでは、OV（組織認証）以上の保証レベルの証明書が一般的に推奨されます。

<!-- **ACMEを用いた自動発行**-->

<!--EMQXはACMEプロトコル（例：Let’s Encrypt）を利用してサーバー証明書を自動取得・更新できます。-->

### 自己署名CA証明書の作成

自己署名証明書はテスト、開発、プライベート環境で有用です。

::: tip 前提条件

[OpenSSL](https://www.openssl.org/)がインストールされていること。

:::

1. 以下のコマンドを実行し、キーペアを生成します。コマンド実行時に秘密鍵を保護するパスワードの入力を求められます。このパスワードは証明書の生成、発行、検証時に必要となるため、安全に保管してください。

   ```bash
   openssl genrsa -des3 -out rootCA.key 2048
   ```

2. 次に、キーペアの秘密鍵を用いてCA証明書を生成します。コマンド実行時に証明書の識別名（DN）を設定するよう求められます。

   ```bash
   openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.crt
   ```

### サーバー証明書の発行

先ほど生成したCA証明書を使い、EMQXのリスナーがクライアントに自身の正当性を証明するためのサーバー証明書を発行します。サーバー証明書は通常、ホスト名、サーバー名、またはドメイン名（例：[www.emqx.com](https://www.emqx.com/en)）に対して発行されます。サーバー証明書の生成にはCAの秘密鍵（rootCA.key）、CA証明書（rootCA.crt）、およびサーバーの証明書署名要求（CSR）（server.csr）が必要です。

1. サーバー証明書用のキーペアを生成します。

   ```bash
   openssl genrsa -out server.key 2048
   ```

2. サーバーのキーペアを用いてCSRを作成します。CSRはCAの秘密鍵で署名され、証明書の公開鍵ファイルが生成されてユーザーに発行されます。コマンド実行時に証明書の識別名（DN）を設定するよう求められます。

   ```bash
   openssl req -new -key server.key -out server.csr
   ```

   以下のような情報入力が求められます。各項目の意味は以下の通りです。

   ```bash
   You are about to be asked to enter information that will be incorporated
   into your certificate request.
   What you are about to enter is what is called a Distinguished Name or a DN.
   There are quite a few fields but you can leave some blank
   For some fields there will be a default value,
   If you enter '.', the field will be left blank.
   -----
   Country Name (2 letter code) [AU]: # 国または地域
   State or Province Name (full name) [Some-State]: # 州または都道府県
   Locality Name (eg, city) []: # 市区町村
   Organization Name (eg, company) [Internet Widgets Pty Ltd]: # 組織名（会社名）、例：EMQ
   Organizational Unit Name (eg, section) []: # 部署名、例：EMQX
   Common Name (e.g. server FQDN or YOUR name) []: # サーバーのFQDN（例：mqtt.emqx.com）
   ...
   ```

3. CSRを使ってサーバー証明書を生成し、有効期間を365日に設定します。

   ```bash
   openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 365
   ```

   これで以下の証明書セットが揃います。

   ```bash
   .
   ├── rootCA.crt
   ├── rootCA.key
   ├── rootCA.srl
   ├── server.crt
   ├── server.csr
   └── server.key
   ```

### クライアント証明書の発行

クライアント証明書は双方向（相互）TLS認証に使用されます。

発行手順はサーバー証明書とほぼ同様ですが、以下が異なります。

- Common Name（CN）はクライアントを一意に識別する（例：ユーザー名やクライアントID）必要があります。
- 証明書は同じCA証明書で署名されるため、クライアント証明書も上記CA証明書で署名可能です。

## EMQXにおける証明書管理

証明書を取得した後、EMQXでは2つの方法で証明書を管理・参照できます。

### パスベース証明書

パスベース証明書は、リスナーやコネクターのSSLオプションで以下のようにファイルパスを明示的に指定して設定します。

- `certfile`
- `keyfile`
- `cacertfile`

パスベース証明書の特徴：

- 証明書ファイルはユーザーまたは外部ツールが完全に管理します。
- リスナーは証明書ファイルを直接参照します。
- 証明書の更新は通常、ディスク上のファイル置換で行います。

EMQXはテスト用に`etc/certs`ディレクトリにサンプル証明書を提供しています。

パスベース証明書は引き続き完全にサポートされ、すべてのEMQXバージョンで互換性があります。

### 管理証明書

EMQX 6.1以降、管理証明書というTLS証明書ファイルを集中管理し、複数コンポーネントで再利用可能な仕組みを導入しました。

管理証明書は以下のリソースで参照・再利用できます。

- MQTT SSLリスナー
- WSSリスナー
- HTTPS / ダッシュボードリスナー
- TLS対応コネクター（例：データ統合）

管理証明書はダッシュボードまたはREST APIで作成・管理でき、EMQXのデータディレクトリ`data/certs2/`に保存されます。

内部的には、EMQXはErlang/OTPのSSLライブラリと連携する際にパスベースのPEMパスを使用し、以下を実現しています。

- 既存のTLS動作との完全な後方互換性
- 証明書の自動リロード
- 証明書更新時にリスナーやコネクターの再起動不要

#### 管理証明書バンドル

管理証明書バンドルは、TLS関連ファイルの論理的なセットを表します。内容は以下を含みます。

- サーバー証明書
- 秘密鍵
- 任意のCA証明書

各バンドルは名前と任意のネームスペースで識別され、複数のリスナーやコネクターから参照可能です。

管理証明書は再利用可能なリソースであり、バンドルを更新するとそれを参照するすべてのリスナーやコネクターに自動的に反映されます。

#### 証明書フォーマットとファイル構成

EMQXの管理証明書はPEMエンコードファイルを引き続き使用しており、従来のTLS証明書展開方式と一貫しています。

PEMファイルの利点：

- **可視性**：`openssl`などの標準ツールで簡単に検査・検証可能
- **互換性**：Erlang/OTPのSSLライブラリがネイティブにサポートし、
  - ファイルベースの証明書キャッシュ
  - 更新された証明書ファイルの自動リロード

##### 証明書ファイル構成

管理証明書バンドルは、証明書名とネームスペースで識別されるディレクトリとしてディスクに保存されます。

例：

```
mqtt.example.com
tenant1/certs1
```

バンドル内に含まれるファイル例：

| ファイル名           | 必須 | 説明                                         |
| -------------------- | ---- | -------------------------------------------- |
| `key.pem`            | 必須 | 秘密鍵                                       |
| `chain.pem`          | 必須 | 証明書チェーン（ルートCAを除く）             |
| `ca.pem`             | 任意 | ピア検証に使用するルートCAバンドル             |
| `key-password.pem`   | 任意 | 秘密鍵が暗号化されている場合の復号パスワード   |

#### SNIによる複数証明書の利用

同一リスナーに複数の管理証明書バンドルが設定されている場合、EMQXはTLS拡張のServer Name Indication（SNI）に基づき動的に証明書を選択します。

##### SNIの利用方法

- 各管理証明書参照は任意で`sni`値を指定できます。
- TLSハンドシェイク時に以下が行われます。
  1. クライアントがSNIホスト名を送信
  2. EMQXが設定済み証明書エントリとSNIを照合
  3. 一致するものがあれば該当バンドルを使用
  4. 一致しなければリストの最初の証明書をデフォルトとして使用

この仕組みにより、単一リスナーで同一IP・ポート上に複数ドメインやテナントの異なるTLS証明書を安全に提供できます。

##### 例

```hocon
listeners.ssl.default {
  bind = "0.0.0.0:8883"

  ssl_options {
    managed_certs = [
      {
        bundle_name = "default-cert"
        sni = "example.com"
      },
      {
        bundle_name = "example-cert-1"
        sni = "mqtt.example.com"
      }
    ]
  }
}
```

## 管理証明書バンドルの作成と管理

このセクションでは、ダッシュボードおよびREST APIを用いた管理証明書バンドルの作成・管理方法を説明します。作成後、証明書バンドルは選択可能になり、複数のリスナーやコネクターで再利用できます。

### ダッシュボードからの証明書バンドル作成

ダッシュボードから直接管理証明書バンドルを作成できます。

1. **管理** -> **証明書** に移動します。

2. **+ 作成** をクリックします。

3. **管理証明書の作成**パネルで以下を入力します。

   - **名前**（必須）：管理証明書バンドルの一意の名前

   - **ネームスペース**：管理証明書バンドルをグローバルネームスペースか特定テナントネームスペースに作成するかを制御します。

     デフォルトではオフで、グローバル（`global`）ネームスペースに作成されます。有効にするとテナントネームスペースを選択してその中に作成可能です。

     - グローバル管理者は`global`または任意のテナント（非グローバル）ネームスペースに作成可能
     - ネームスペーススコープのユーザーは自身のネームスペース内のみ作成可能

   - **TLS証明書**（必須）：PEM形式のサーバー証明書。証明書内容を直接貼り付けるか、ファイルをアップロードできます。必要に応じて完全な証明書チェーンを含めてください。

   - **TLS秘密鍵**（必須）：サーバー証明書に対応するPEM形式の秘密鍵。内容を直接貼り付けるかファイルアップロード可能。

   - **秘密鍵パスワード**：秘密鍵が暗号化されている場合のパスフレーズ（任意）。

   - **CA証明書**：PEM形式の認証局証明書（任意）。双方向TLS認証やCA証明書を必要とするコネクターでの再利用時に通常必要です。

4. **作成**をクリックして管理証明書バンドルを保存します。

### ダッシュボードでの証明書バンドル管理

作成した証明書バンドルはダッシュボードの証明書一覧に表示され、管理可能です。

- 上部のネームスペースドロップダウンでグローバルネームスペースと特定テナントネームスペースを切り替えられます。選択に応じて一覧が自動更新されます。
- 各証明書バンドルは**名前**と利用可能な**操作**が表示されます。

この画面から以下が可能です。

- 選択したネームスペース内の証明書バンドルの閲覧
- 証明書バンドルの編集（証明書内容、秘密鍵、CA証明書の更新）
- 不要になった証明書バンドルの削除

#### 証明書バンドルの削除

EMQX 6.1.4以降、証明書バンドルがいずれかの設定で参照されている場合、削除できません。

1. **削除**をクリックすると、**削除の確認**ダイアログが表示されます。
2. **キャンセル**でダイアログを閉じるか、**確認**で削除を実行します。
3. **確認**をクリックすると以下のいずれかが発生します。
   - 依存関係がなければ証明書バンドルが削除されます。
   - 依存関係がある場合は削除が拒否され、**使用中のバンドル**ダイアログに参照している設定が表示されます。**ページへ移動**をクリックして該当設定を更新または削除後に再試行するか、**キャンセル**でダイアログを閉じて削除を中止します。

管理証明書バンドルはディスクに保存され、EMQXによって自動的にリロードされます。更新時にEMQXの再起動は不要です。

![certificate_bundle_list](./assets/certificate_bundle_list.png)

### REST APIによる証明書バンドル管理

ダッシュボードに加え、EMQXはTLS証明書ファイル管理用のREST APIを提供しています。API経由で作成した管理証明書はダッシュボード作成と同等で、リスナーやコネクターから同様に参照可能です。

#### 証明書ファイルのアップロード

証明書ファイルをアップロードして管理証明書バンドルを作成または更新します。

対応ファイル種別：

- `key`：秘密鍵
- `chain`：証明書チェーン（ルートCA除く）
- `ca`：CA証明書バンドル
- `key-password`：秘密鍵復号用パスワード

指定ネームスペースに証明書ファイルをアップロード：

```
POST /certs/ns/:namespace/name/:name?file=key|chain|ca|key-password
```

グローバルネームスペースに証明書ファイルをアップロード：

```
POST /certs/global/name/:name?file=key|chain|ca|key-password
```

#### 証明書バンドル一覧取得

ネームスペース内の管理証明書バンドル一覧を取得：

```
GET /certs/ns/:namespace/list
```

グローバルネームスペースの管理証明書バンドル一覧を取得：

```
GET /certs/global/list
```

#### 証明書バンドルの削除

EMQX 6.1.4以降、全ネームスペースのいずれかの設定が参照している管理証明書バンドルや個別ファイルの削除は拒否され、`400 BAD_REQUEST`エラーが返されます。

ネームスペースから管理証明書バンドル全体を削除：

```text
DELETE /certs/ns/:namespace/name/:name
```

グローバルネームスペースから管理証明書バンドル全体を削除：

```text
DELETE /certs/global/name/:name
```

バンドル内の個別ファイルを削除する場合は同じエンドポイントに`kind`クエリパラメータでファイル種別を指定します。依存関係チェックはバンドル全体と個別ファイルの両方に適用されます。

`force_delete`クエリパラメータはAPIスキーマから削除されており、依存関係チェックを回避できません。既存クライアントが`force_delete=true`を送信しても無視され、通常の削除リクエストとして処理されます。

削除がブロックされた場合、`400`レスポンスの本文に`referencing_configs`フィールドが含まれ、どの設定がバンドルを参照しているかネームスペースごとに示されます。例：

```json
{
  "code": "BAD_REQUEST",
  "message": "Cannot delete file or bundle while configurations are depending on it",
  "referencing_configs": {
    "global": [
      ["connectors", "http", "my-connector"]
    ]
  }
}
```

削除を再試行する前に、`referencing_configs`に記載されたすべての設定を更新または削除し、バンドルの参照を解除してください。

<!--## ACMEによる自動証明書発行（管理証明書のみ）

EMQXはACMEプロトコル（例：Let’s Encrypt）を用いたサーバーTLS証明書の自動発行・更新をサポートします。この機能は、クライアントが公開ドメイン名を使ってTLSで直接EMQXに接続するデプロイ向けであり、ロードバランサーでTLS終端する場合やプライベート・内部ホスト名のみの場合には適しません。

ACMEはEMQX管理者が設定ファイルで有効化・設定し、ダッシュボードやネームスペーススコープユーザーは利用できません。

ACMEはMQTTS、HTTPS/Dashboard、WSSリスナーで使うサーバー証明書にのみ適用され、クライアント証明書には適用されません。

### ACMEと管理証明書の連携

ACMEは管理証明書と直接連携します。

ACME有効時：

1. EMQXがACMEクライアントとして設定されたACME CAに証明書を要求
2. 証明書は期限切れ前に自動更新
3. 生成されたファイルは管理証明書ディレクトリに書き込まれ、バンドルは以下を含む
   - `key.pem`
   - `chain.pem`
   - `acc-key.pem`（該当時）
4. EMQXは自動的に管理証明書バンドルを作成

ACME発行証明書は手動アップロードの管理証明書と同様に動作し、ユーザーはリスナー設定時に生成済みの管理証明書バンドルを選択または参照するだけで済みます。

### 設定ファイルによるACME有効化

この操作には以下が必要です。

- EMQXホストへのアクセス
- EMQX設定ファイルの編集権限
- デプロイの管理権限

設定例：

```hocon
## ACME CAディレクトリURL（例：Let's Encrypt）
acme.directory_url = "https://acme-v02.api.letsencrypt.org/directory"

## ACMEアカウント登録用連絡先メール
acme.contact_email = "admin@example.com"

## 証明書に含めるドメイン
## ドメイン所有権はHTTP-01チャレンジで検証
acme.domains = ["mqtt1.example.com", "mqtt2.example.com"]

## 発行証明書の保存ディレクトリ
## 管理証明書と連携
acme.cert_dir = "${EMQX_MANAGED_CERTS_DIR}"
```

-->

## SSL/TLS証明書の更新

SSL/TLS証明書は有効期限切れ前に更新し、安全な接続を維持する必要があります。EMQXでの証明書更新方法は管理方式によって異なります。

### パスベース証明書の更新

パスベース証明書は設定内でファイルパス（例：`certfile`、`keyfile`、`cacertfile`）で直接参照されています。

更新手順：

1. `./etc`または`/etc/emqx/etc`ディレクトリ内の既存証明書、秘密鍵、CAファイルを新しいものに置き換えます。
2. 設定で参照されているファイルパスは変更しないようにします。

EMQXは更新された証明書ファイルを自動的にリロードします。

- 証明書ファイルは定期的にチェック・リロードされます。
- デフォルトでは120秒ごとにリロードされます。
- 多くの場合、リスナーの再起動は不要です。

### 管理証明書の更新

管理証明書は証明書バンドルを修正することで更新します。

更新方法：

- ダッシュボードまたは管理証明書APIを使い、既存の管理証明書バンドルに新しい証明書、秘密鍵、またはCA証明書をアップロードします。

更新後：

- 管理証明書を参照するすべてのリスナーやTLS対応コンポーネントは自動的に更新済み証明書を使用します。
- リスナーやEMQXの再起動は不要です。

管理証明書は再利用可能な設計であり、バンドル更新は参照先すべてに影響します。

<!--### ACMEによる自動更新（管理証明書のみ）

ACME発行の管理証明書について：

- EMQXは期限切れ前に証明書を自動更新します。
- 更新された証明書ファイルは管理証明書ディレクトリに書き込まれます。
- 対応する管理証明書バンドルも自動的に更新されます。

ACME有効化・設定後：

- 手動アップロードは不要です。
- リスナーは同じ管理証明書バンドルを参照し続けます。
- 証明書ローテーションはサービス停止なしで行われます。-->

## 次のステップ

SSL/TLS証明書を取得したら、クライアントのSSL/TLS接続を有効化できます。

- [SSL/TLS接続の有効化](./emqx-mqtt-tls.md)
