Spring Boot と Let's Encrypt でHTTPS

# はじめに

Spring Boot でHTTPS対応のWebアプリを作ります。アプリケーションサーバーは、Spring Bootのアプリ内に自動的に組み込まれるTomcatを使用します。
サーバー証明書はLet's Encryptを使用してインターネットで信頼される正式な証明書を作成します。

なお、HTTPSを利用するには自サーバーがインターネットからアクセスできる必要がありますので、ドメイン名(FQDN)が必要です。私の場合、試験用に使用したサーバーでは以下のDDNSを利用しています。

[私的MyDNS.JP](https://www.mydns.jp/)
https://www.mydns.jp/

※　AWSでEC2のサーバーを立ち上げるとパブリックIPアドレスに紐づいたドメイン名が与えられますが、Let's Encryptのポリシーによりこの名前で証明書を作成することはできません。

### 開発環境

Open JDK 14.0.1 (※)
Spring Boot 4 4.6.2.RELEASE
開発PC Windows 10 Pro 1909
サーバー　AWS EC2 マシンイメージAmazon Linux AMI 2018.03.0 
※開発用PCとサーバーのJDKは合わせるのが大事。

# サーバー証明書の作成

HTTPSでサーバーを建てるためにサーバー証明書を作成します。
まず、AWSのEC2を使用してWebサーバーを構築します。

## EC2サーバーの構築

　1. AWSコンソールにサインインし、サービスからEC2を選択します。
　2. インスタンスを作成します。Amazon マシンイメージは「Amazon Linux AMI 2018.03.0(HVM), SSD Volume Type」にします。スペックは最低限でOK。
　3. サーバーを作成した際にキーペアのダウンロードを忘れないように。

Tera Termでサーバーにログインします。ユーザー名はec2-user、パスワードは要りません。
RSAキーとして、3.手順でダウンロードした鍵ファイルを指定します。
<img width="349" alt="qiita0605_1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/09a053a3-4c7d-6100-15ea-d5562d2fdfe0.png">

ログインしたら、パッケージをアップデートしておきましょう。

```
sudo yum -y update
```

Apache HTTP Serverをインストールします。

```
sudo yum -y install httpd mod_ssl
sudo service httpd start
```
Apacheのルートフォルダをec2-userがアクセスできるようにしておきます。

```
sudo chown ec2-user /var/www/html/
```

## OpenJDKのインストール

まず、PCでOpenJDKのサイトに行ってLinux用の.tar.gzをダウンロードします。

![qiita0605_9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/2f2b765e-fc59-a646-745b-c41e9b9e07d6.png)

ダウンロードした openjdk-14.0.1_linux-x64_bin.tar.gz をサーバーにアップロードします。Tera Termにドラッグ&ドロップすればアップロードできます。

解凍します。

```
tar zxvf openjdk-14.0.1_linux-x64_bin.tar.gz
```

OpenJDKにPATHを通すため　/etc/profile.d/env.sh を作成します。

```
# /etc/profile.d/env.sh
export PATH=/home/ec2-user/jdk-14.0.1/bin:$PATH
```

PATHの設定を適用するためにサーバーへログインしなおしてください。

## DDNSの登録

サーバーのアドレスをDDNSにアップロードします。
MyDNSの場合は、wgetでサイトにアクセスすることでアップロードできます。無料アカウントの登録が必要です。詳しくは[MyDNSのサイト](https://www.mydns.jp/)をご確認ください。

```
wget -O - 'http://mydns123456:mypassword@www.mydns.jp/login.html'
```

## アクセスリストの設定

EC2にデフォルトで設定されているセキュリティグループの設定では、SSHのみが許可されています。HTTP/HTTPSを許可しましょう。

インスタンスペインで作成したインスタンスを選択し、「セキュリティグループ」のリンク(launch-wizard-1とか)をクリックします。
「インバウンドルールの編集」を選択し、「ルールを追加」をクリック、HTTPとHTTPSを任意の場所から許可します。
![qiita0605_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/b4305ac6-237b-eae1-1e02-0f509e373756.png)

## Let's Encrypt ツールのインストール

gitとsocatをインストールします。

```
sudo yum -y install git socat
```

Let's Encrypt の自動化シェル acme.sh をインストールします。

```
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install
```

## 証明書の作成

以下のコマンドで証明書を作成します。(ドメイン名は偽物です)

```
./acme.sh --issue -d my.domain.jp -w /var/www/html
```

![qiita0605_3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/9d26954c-3968-3c93-1d79-c505894217b5.png)

生成した証明書をpkcs12形式にパックします。

```
openssl pkcs12 -export -in ~/.acme.sh/my.domain.jp/my.domain.jp.cer -inkey ~/.acme.sh/my.domain.jp/my.domain.jp.key -out ~/my.domain.jp.p12
```

パスワードの入力を求められるので、パスワードを設定します。このパスワードはSpring Bootの設定で必要になるので必ず記録しておいてください。

/home/ec2-user/my.domain.jp.p12　が作成されたはずなので、これをダウンロードします。Tera TermのSCP機能を使うのが簡単だと思います。

 1. Tera Termの「ファイル」－「SSH SCP」を選択する
 2. 下段のFrom: にmy.domain.jp.p12 と入力する
 3. 下段のTo: をユーザーのデスクトップ等わかりやすいところに変更する
 4. 「Receive」をクリックする

以上で、Let's Encryptによる証明書のPKCS12ファイルが作成できました。

# Spring Bootアプリの作成

Spring BootでWebアプリを作ります。ここでは、HTTPS化の説明が目的ですのでサイト自体はいたってシンプルなものにします。

## プロジェクトの作成

Spring Tool Suite を起動し、「File」－「New」－「Spring Starter Project」選択します。
<img width="559" alt="qiita0605_4.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/a77870a2-32de-351c-12c4-d4a31da562bb.png">

Dependencies は 「Spring Web」 だけで大丈夫です。

<img width="559" alt="qiita0605_5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/d4e88a44-e2e9-49df-fa77-3d3b435155ec.png">

サンプルページを作成します。

src/main/resources/static/index.html を作成します。

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTTPS Sample</title>
</head>
<body>
<h1>Let's Encrypt!</h1>
</body>
</html>
```

## HTTPSを有効化する

src/main/resources/application.properties に以下の内容を記述します。

```properties
server.port=443
server.ssl.key-store=my.domain.jp.p12
server.ssl.key-store-password=MyPassword
server.ssl.keyStoreType=PKCS12
```
サーバーからダウンロードしたmy.domain.jp.p12ファイルをプロジェクトのルートフォルダにコピーします。

![qiita0605_6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/5e333a39-b708-c10c-0f7d-a62a0abe5c1c.png)

# ローカル動作確認

Spring Boot アプリを起動します。
「Run」→「Run as」→「Spring Boot App」で起動してください。
証明書はDDNSで設定したFQDNにしていますから、localhostでアクセスするとこの警告が表示されます。警告を無視して強行すればページが表示されますが、ここではこの警告まで見られれば十分です。

![qiita0605_7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/9fef863b-eb15-de07-bf09-c741f14567ba.png)

# サーバーへのアップロード

AWSのサーバーでサイトを動かすにはSpring Bootで作成したプログラムをjarファイルにしてアップロードする必要があります。

Spring Tool Suiteで「Run」→「Run as」→「Maven install」を実行します。

「target」フォルダの中に「SampleHTTPS-0.0.1-SNAPSHOT.jar」ができます。

![qiita0605_8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/590699de-e3c3-9d78-000d-d92a32938869.png)

ファイルを右クリック→「Show in」→「System Explorer」でエクスプローラを開き、Tera Termにドラッグ&ドロップします。

プロジェクトフォルダ(targetの一つ上の階層)にある **my.domain.jp.p12** も必要なので、同じようにTera Termにドラッグ&ドロップしてアップロードします。

# サーバー上での起動

サーバーでApacheが動いているとSpring Bootで作成したアプリとポートが競合してしまうので停止します。

```
sudo service httpd stop
sudo chkconfig httpd off
```

java プログラムを起動します。ただし、443ポートはec2-userでbindすることができないのでsuしてから実行します。

```
sudo su
java -jar SampleHTTPS-0.0.1-SNAPSHOT.jar
```

![qiita0605_11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/5032d4e7-ce35-3173-990c-fd57abbf310f.png)

起動出来たら、サイトを表示してみましょう。
表示されるページはただのテキストですが、鍵マークが表示されてHTTPSが有効になっていることが判ります。証明書を表示してみると、Let's Encryptで証明書が発行されていることが判ります。

![qiita0605_12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/572e3529-3aea-0fcb-63f6-0319218e1767.png)

![qiita0605_10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570192/45fdcd2f-da74-11f3-b4ed-80b52340eeb5.png)

長くなってしまいましたが、以上です。

# 参考にしたサイト

[Spring bootでSSL（HTTPS）を有効にする](https://qiita.com/keigohtr/items/001b84838fefcc170ea2)

Let's Encryptの公式
https://letsencrypt.org/ja/docs/client-options/
からの、acme.shのgithub
https://github.com/acmesh-official/acme.sh