# Webship における TLS 証明書: 組み込み ACME CA
TLS証明書には2つの役割があります:接続を暗号化することと、クライアントにどの身元と通信しているかを伝えることです。暗号化は強力でも、その対象にとって信頼判断が間違っていることがあります。だからこそ、証明書の自動化は1つの質問から始める必要があります:誰がこのサイトを信頼しなければならないのか?
Webship 1.4.0 は、設定された各サイトごとにその選択を独立して行います。公開ウェブサイトはブラウザが信頼する ACME 証明書を使用でき、内部サービスは Webship に組み込まれたプライベート証明書機関を使用でき、既存の PKI を持つサイトはオペレーターが管理する証明書ファイルを保持できます。これらはすべて、1 つのプライベートキーや 1 つの信頼境界を共有することなく、1 つの Webship プロセスを共有することができます。
サイトごとに選択される4つの自動証明書モード
certificate_mode フィールドは各 [[sites]] エントリに属します。これはグローバルスイッチではありません。
| モード | 信頼できるソース | 最適な適合 | 検証パス | | --- | --- | --- | --- | | per_site | 公共のブラウザおよびオペレーティングシステムの信頼ストア | 正確なホスト名を持つ公共サイト | TLS-ALPN-01を使用した公共ACME | | フリート | 公共のブラウザおよびオペレーティングシステムの信頼ストア | 明示的に登録されたドメインの下にある大規模なサードおよびフォースレベルの名前のセット | DNS-01を使用した公共のACMEおよび安定した証明書シャード | | 組み込み | オペレーターによってインストールされたプライベートWebshipルート | 内部サービス、管理されたデバイス、プライベートフリート、およびテスト環境 | 処理中の発行;外部のチャレンジなし | | 共有 | 公共のブラウザおよびオペレーティングシステムの信頼済みストア | 意図的に1つの公開マルチSANグループを使用するレガシー展開 | TLS-ALPN-01を使用した公開ACME |
デフォルトは per_site です。これは、サイトの正確な名前に対して1つの公開証明書を取得します。フリートモードは、多くの深いサブドメインに対応するスケーラブルな公開オプションです。埋め込みモードは、Webship のプライベートなインプロセス CA を使用します。共有モードは互換性のために引き続き利用可能ですが、デフォルトではありません。
[sites.tls] の下の完全な証明書とキーは、そのサイトの自動発行よりも常に優先されます。
「組み込みACME CA」とは何を意味するか
設定セクションの名前は[acme_ca]ですが、組み込みのCAは公開されているネットワークアクセス可能なACMEサービスではありません。ディレクトリエンドポイントを公開せず、リモート登録を受け付けず、レジストラAPIを呼び出さず、制御証明チャレンジも実行しません。
その代わりに、Webshipはプライベート発行のすべての経路をひとつのプロセスに保持します:
- そのサイトは certificate_mode = "embedded" を選択します。
- Webshipは、設定された状態ディレクトリ内でプライベートルートIDをロードまたは作成します。
- Webshipはサイトの新しい秘密鍵を生成します。
- 組み込みルートは、その正確な名前のためのリーフ証明書に署名します。
- Webshipは、ライブTLSリゾルバにインストールする前に、完了したIDを検証します。
- その後、その証明書はそのサイトのすべての有効なプロトコルで使用可能になります。
ACMEスタイルのネットワークチャレンジはWebship自身にしか証明されないため、埋め込みパスには意図的にネットワークプロトコルがありません。[acme_ca] セクションはプライベートPKIの状態であり、ルートがどこにあるかと、発行されたリーフ証明書がどのくらいの期間有効であるかを定義します。
1つのサイトに組み込み証明書を設定する
これはプライベートサイトの最小形です:
~~~toml listen = "0.0.0.0:443"
[tls] unknown_sni = "拒否"
[自動_tls] 有効 = 真 cache_dir = "/var/lib/webship/acme"
[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90
[[サイト]] ドメイン = "service.internal.example" root = "/srv/service" certificate_mode = "embedded"
[サイト.プロトコル] h1 = 真 h2 = true h3 = true ~~~
ルートIDは、埋め込みサイトが初めて必要とする際に遅延的に作成されます。Webship は root_key を state_dir に制限付き権限で保持します。ルート証明書の有効期間は10年であり、リーフの有効期間は leaf_validity_days によって制御されます。
両方のストレージ場所を本番状態として扱う:
- ACMEキャッシュは自動で管理されるサイトの識別情報を保持します。
- 組み込みCAの状態ディレクトリは、プライベートルートIDを保持します。
- サービス アカウントはアクセスが必要ですが、アプリケーション ユーザーには必要ありません。
- バックアップは機密性とファイルの権限を保持しなければなりません。
- 本番、開発、テストは別々のルートおよび別々のディレクトリを使用するべきです。
ルートディレクトリを削除しても「TLSはリセットされません」。それは新しい信頼のアンカーを作成するだけです。古いルートを信頼しているクライアントは、信頼ストアが更新されるまで、置き換えによって発行された証明書を拒否します。
私的信託は意図的である
組み込みCAからの証明書は、パブリックブラウザやオペレーティングシステムによって自動的には信頼されません。それらが信頼されるようになるのは、オペレーターがエクスポートされたWebshipルート証明書をクライアントの信頼ストアにインストールした後です。
それにより、組み込みモードは次のような場合に適しています:
- デバイス管理を通じて登録された、会社管理のノートパソコンと電話;
- 明示的なCAバンドルを使用した内部サービス間トラフィック;
- プライベート家電と管理されたエッジフリート;
- 実際のTLS動作を行う必要がある開発およびテスト環境;
- 公共のCAに依存できない切断されたネットワーク。
これは、訪問者が管理されていないブラウザを使用する一般的な公開ウェブサイトには適したモードではありません。正確な公開名には public per_site 発行を使用し、大規模な公開サブドメインセットには fleet 発行を使用し、意図的なレガシーのマルチ SAN 配置には shared のみを使用するか、すでに信頼された PKI からの手動ファイルを使用してください。
ルート証明書はクライアントにのみ配布してください。ルートの秘密鍵を配布してはいけません。その鍵を持っていると、すべての登録クライアントに信頼されるIDを発行する権限を持つことになります。
公開証明書とプライベート証明書は共存できます
Webship 1.4.0は、同じリスナーで証明書戦略を混在させることができます:
~~~toml listen = "0.0.0.0:443"
[tls] unknown_sni = "reject"
[自動_tls] 有効 = 真 directory_url = "https://acme-v02.api.letsencrypt.org/directory" cache_dir = "/var/lib/webship/acme" contacts = ["mailto:ops@example.com"] 利用規約に同意する = true
[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90
[[サイト]] ドメイン = "www.example.com" root = "/srv/public" certificate_mode = "サイトごと"
[[サイト]] ドメイン = "control.internal.example" root = "/srv/control" certificate_mode = "embedded"
[[サイト]] ドメイン = "payments.example.com" root = "/srv/payments"
[sites.tls] cert = "/etc/webship/payments-fullchain.pem" key = "/etc/webship/payments-private-key.pem" ~~~
ここで、www.example.com は独自のパブリック ACME 証明書を受け取ります。control.internal.example は組み込み CA からプライベート証明書を受け取ります。payments.example.com は明示的なファイルが優先されるため、オペレーターの外部 PKI のままです。
公開ACMEディレクトリは埋め込みサイトでは無視されます。埋め込みルートは公開サイトに署名することはありません。マニュアルサイトはどちらの自動ワークフローにも自動的に登録されることはありません。
H1、H2、H3、およびWebTransport用の1つの証明書リゾルバー
証明書の選択は、HTTPリクエストが存在する前にTLSハンドシェイク中に行われます。WebshipはClientHelloのサーバー名を使用してサイトの識別を選択し、その後アプリケーションプロトコルを交渉します。
- HTTP/1.1 と HTTP/2 は TCP 上で TLS を使用します。
- HTTP/3とWebTransportは、UDP上のQUIC内でTLSを使用します。
- 1つの有効なサイトの識別は、すべての有効なプロトコルに対応できます。
- HTTP/3はUDP到達性も必要とします;H1とH2はTCP経路を使用します。
- Alt-Svc は TCP フォールバックを維持しながら H3 を広告することができます。
TCP、TLS、およびQUICは同じサイト認識のアイデンティティモデルを使用します。正確な名前が優先され、ワイルドカード証明書が設定されている場合は最も長い有効なワイルドカードが勝ち、未知の名前付きSNIは、無関係なデフォルト証明書を受け取る代わりに拒否されることがあります。
未認識のホスト名で閉じる必要がある場合、マルチサイトリスナーで unknown_sni = "reject" を使用します。本番展開前に、認識された名前、未認識の名前、および期待される no-SNI の動作をテストしてください。
提供の間隔なしで埋め込まれたアイデンティティを回転させる
Webshipは、認証されたループバックバインドのMCPサーバーを通じて、証明書の状態と制御された変更を公開します:
- webship.tls.get_status は、アクティブな証明書の解決者と更新状態を報告します。
- webship.tls.reissue_certificate は、自動管理されているサイトが埋め込みモードを使用している場合にのみ、そのサイトの証明書を即座に再発行します。
- webship.tls.reload は、通常の保護された TLS 経路を通じて証明書の状態をリロードします。
- webship.acme_ca.status は、プライベート CA が選択されているかどうか、その状態ディレクトリ、リーフの有効期間、発行数、取り消し数、および最近のドメインサンプルを報告します。
- webship.sites.apply は、固定された構成バージョンに対してサイトを追加または削除します。
組み込み型の再発行の場合、Webshipは代替を作成して検証した後、それをサービスに切り替えます。新しいIDが準備できるまで、現在有効なIDは引き続き使用されます。代替がインストールされた後でのみ、引退したIDが記録されます。
即時再発行操作は、意図的に公開 per_site 証明書を拒否します。公開の更新は、プライベートの進行中署名と混同されるのではなく、公開 ACME ライフサイクル内に留まる必要があります。共有モードのメンバーシップも再起動で凍結されます。なぜなら、複数 SAN のグループを変更すると、ID 境界が再構築されるからです。
MCPは特権制御面です。ループバックで保持し、TLSと強力なベアラートークンを要求し、リモート管理には認証済みトンネルを使用し、すべての変更を監査してください。
重要な失敗の境界
安全な証明書システムは、正しい方向に失敗しなければならない。
- 新しく設定された組み込みサイトは、発行が保留中の間、他のサイトの識別情報を受け取りません。
- 無効な置換は、正常に動作している証明書の上にはインストールされません。
- 明示的な手動ファイルは、そのサイトの自動所有を防ぎます。
- 不明な名前付きSNIは、HTTPルーティング前に拒否される可能性があります。
- 組み込みのCAは非公開のままで、リモート登録エンドポイントを持ちません。
- 公開および組み込みのアイデンティティは、自動TLS状態内で別々のキャッシュパスを使用します。
埋め込み済みのCAが初期化されていないという警告は、Webshipが構成されたステートディレクトリを準備できなかったことを意味します。影響を受けるサイトにトラフィックを送る前に、所有権、権限、永続性、またはストレージの利用可能性を修正してください。他の環境のルートキーをコピーしてエラーを回避しないでください。
生産チェックリスト
埋め込みモードを有効にする前:
- そのサイトを信頼しなければならないすべての顧客層を特定する。
- ルート証明書をエクスポートおよびインストールするための管理されたプロセスを作成します。
- 本番、開発、テスト用にそれぞれ別のルートステートを使用してください。
- 組み込みCAの状態ディレクトリと自動TLSキャッシュを維持して保護します。
- Webship を、必要なキー素材へのアクセスのみを持つ専用サービスアカウントで実行してください。
- 信頼境界を明示する必要があるすべてのサイトで certificate_mode を選択してください。
- 未知のSNIポリシーを設定してテストします。
- H1、H2、H3 を意図的に有効にし、TCP と UDP の両方の経路を確認してください。
- 本番環境外で、再発行、再起動、バックアップ、復元、およびクライアント信頼性の検証を実施する。
- 展開の前に webship --check-config を実行し、その後、実際のクライアントから発行者、名前、有効性、チェーン、交渉されたプロトコルを確認してください。
まず信頼を選び、次に自動化を選ぶ
組み込みのCAは、プライベートインフラストラクチャにおける外部の証明書サービスの依存を排除します。これはプライベートルートをグローバルに信頼されるものにするわけではなく、オペレーターのPKIの責任を取り除くものでもありません。
Webshipは、鍵の生成、署名、検証、インストール、ローテーション、およびプロトコル全体での証明書選択を自動化します。オペレーターは依然として、ルートの管理、クライアントの登録、環境の分離、バックアップ、復旧、および公開または非公開の信頼パスを使用するかどうかの決定を所有しています。
その分離が特徴です。独立したサーバーは、公開CAを装うことなくプライベートTLSを自動化することができ、公開サイトも同じプロセスでブラウザに信頼されるサイトごとの発行やフリート発行を利用できます。
本番展開前に、バージョン管理された Webship 1.4.0 ドキュメント を読んでください。RFC 5280 は証明書のプロファイルと検証を定義し、RFC 6066 は TLS サーバー名通知を定義し、RFC 8446 は TLS 1.3 を定義し、RFC 8555 は公開 ACME を定義し、RFC 9525 はサービスの識別確認を定義します。