ローカル開発環境の https 化 | blog.jxck.io [1] を読んで、せっかく自前ドメインを持っているので同じことをやってみたので備忘録として残していく。
やりたいこと
- ローカルで起動したSpring Bootアプリケーションサーバに証明書のエラーなくHTTPSでアクセスしたい
- 証明書のエラーを回避するために自前のCAを作成したくない
前提
- Spring Boot 3.1.2
手順
証明書のエラーを回避するために、自前ドメインのサブドメインを用意して信頼された証明書を取得する。
サブドメインを登録
まずは、実際のドメインを用意していく。
すでに daisuzz.dev
というドメインを持っているのでサブドメインとして localhost.daisuzz.dev
を用意し、127.0.0.1
と紐づけるAレコードを登録する。
サブドメインの証明書を取得
サブドメインのAレコードが登録できたら、そのサブドメインの証明書を取得する。
今回は、元記事にならって、Let's Encryptで証明書の署名と発行を行いたいため、ACMEクライアントのCertbotを利用する。
ACMEクライアントは、Automated Certificate Management Environmentの略で、公開鍵証明書の取得や更新を自動で行うソフトウェアを指す。Certbotの他には、Goで書かれたLegoやシェルスクリプトとして実装されているacme.shがある。
証明書を発行する際に必要なドメイン認証(Domain Validation)方式はさまざまな方法があるが、今回Aレコードで登録した127.0.0.1
では.well-known
ディレクトリにファイルを用意する認証方式は使えないためTXTレコードを利用した認証方式(DNS認証)を利用する。
DNS認証を利用するために、certbotコマンドのオプションでDNS 認証を指定して証明書を取得する。
$ sudo certbot certonly --manual -d localhost.daisuzz.dev --preferred-challenges dns Saving debug log to /var/log/letsencrypt/letsencrypt.log Requesting a certificate for localhost.daisuzz.dev - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please deploy a DNS TXT record under the name: _acme-challenge.localhost.daisuzz.dev. with the following value: ********************************* (1) Before continuing, verify the TXT record has been deployed. Depending on the DNS provider, this may take some time, from a few seconds to multiple minutes. You can check if it has finished deploying with aid of online tools, such as the Google Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.localhost.daisuzz.dev. Look for one or more bolded line(s) below the line ';ANSWER'. It should show the value(s) you've just added. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press Enter to Continue
コマンドを実行すると、上記のように_acme-challenge.サブドメイン
という名前のTXTレコードを(1)の値で登録するよう表示されるので、登録する。
登録後再度ターミナルに戻ってEnterを押下すると、証明書と秘密鍵が発行される。
Successfully received certificate. Certificate is saved at: <fullchain.pemのpath> Key is saved at: <privkey.pemのpath> This certificate expires on 2023-10-28. These files will be updated when the certificate renews. NEXT STEPS: - This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - If you like Certbot, please consider supporting our work by: * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate * Donating to EFF: https://eff.org/donate-le - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
発行した証明書は3ヶ月で期限が切れるため、定期的にSSL証明書更新を行う必要があるので注意。
PKCS#12ファイルの作成
サブドメインの登録と証明書の発行が完了したので、次はアプリケーション側の設定を行なっていく。 Spring Bootアプリケーションの設定を行う前に、まずはPEM形式で出力された証明書と秘密鍵をPKCS#12形式のファイルにまとめていく。
PKCS#12は、Public Key Cryptography Standards#12 の略で、公開鍵証明書や秘密鍵をパスワードで保護してまとめて保存するためのファイル形式。[2]
Spring BootではPKCS#12形式のファイルを指定する方法が初期から、PEM形式のファイルを指定する方法が2.7からサポートされている。[3]
今回はPKCS#12形式のファイルを指定する方法で設定を行う。
PEM形式の証明書と秘密鍵のファイルをPKCS#12形式ファイルにまとめるためにopenssl
コマンドを利用する。
$ openssl pkcs12 -export -in fullchain.pem -inkey privKey.pem -out keystore.p12
上記コマンドを実行することで keystore.p12
というPKCS#12形式のファイルを作成できる。
Spring Bootアプリケーションの設定
作成したPKCS#12形式のファイルをアプリケーションサーバ起動時に読み込むよう設定する。
server: ssl: key-store-type: PKCS12 key-store: <PKCS#12ファイルのpath> key-store-password: <PKCS#12ファイル作成時に設定したパスワード> port: 443
この状態でアプリケーションを起動して、https://localhost.daisuzz.dev
にアクセスすると証明書エラーなくHTTPS接続できる。
サンプルコードはこちら。 GitHub - daisuzz/sample-spring-ssl
参考
[1] ローカル開発環境の https 化 | blog.jxck.io
[2] RFC 7292 - PKCS #12: Personal Information Exchange Syntax v1.1