daisuzz.log

ローカルで起動したSpring BootアプリケーションサーバにHTTPSで接続する

ローカル開発環境の 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

[3] Securing Spring Boot Applications With SSL