Azure Key Vault 証明書を使用して Spring Boot で HTTPS を有効にする
このチュートリアルでは、Azure Key Vault と Azure リソースのマネージド ID を使用して、TLS/SSL 証明書を使用して Spring Boot (Azure Spring Apps を含む) アプリをセキュリティで保護する方法について説明します。
クラウドでもオンプレミスでも、運用グレードの Spring Boot アプリケーションでは、標準の TLS プロトコルを使用したネットワーク トラフィックに対してエンドツーエンドの暗号化が必要です。 見つかったほとんどの TLS/SSL 証明書は、パブリック ルート証明機関 (CA) から検出できます。 ただし、この検出が不可能な場合もあります。 証明書が検出できない場合、アプリには、そのような証明書を読み込み、受信ネットワーク接続に提示し、送信ネットワーク接続から受け入れる何らかの方法が必要です。
通常、Spring Boot アプリでは証明書をインストールして TLS を有効にします。 証明書は、Spring Boot アプリを実行している JVM のローカル キー ストアにインストールされます。 Spring on Azure では、証明書はローカルにインストールされません。 代わりに、Microsoft Azure の Spring 統合により、Azure Key Vault のヘルプと Azure リソースのマネージド ID を使用して TLS を有効にする安全で摩擦のない方法が提供されます。
重要
現在、Spring Cloud Azure Certificate Starter バージョン 4.x 以降では TLS/mTLS はサポートされていません。Key Vault 証明書クライアントのみを自動構成します。 そのため、TLS/mTLS を使用する場合は、バージョン 4.x に移行できません。
前提 条件
Azure サブスクリプション - 無料アカウントを作成します。
バージョン 11 でサポートされている Java Development Kit (JDK)。
Apache Maven バージョン 3.0 以上。
cURL または同様の HTTP ユーティリティ を使用して機能をテストします。
Azure 仮想マシン (VM) インスタンス。 ない場合は、az vm create コマンドと UbuntuServer によって提供される Ubuntu イメージを使用して、システム割り当てマネージド ID が有効になっている VM インスタンスを作成します。 システム割り当てマネージド ID に
Contributor
ロールを付与し、サブスクリプションへのアクセスscope
を設定します。Azure Key Vault インスタンス。 お持ちでない場合は、「クイック スタート: Azure portalを使用してキー コンテナーを作成する」を参照してください。
Spring Boot アプリケーション。 まだない場合は、Spring Initializrを使用して Maven プロジェクトを作成します。 Maven Project
選択し、 依存関係 の下で、Spring Web 依存関係を追加してから、Java バージョン 8 以降を選択してください。
重要
この記事の手順を完了するには、Spring Boot バージョン 2.5 以降が必要です。
自己署名 TLS/SSL 証明書を設定する
このチュートリアルの手順は、Azure Key Vault に直接格納されている TLS/SSL 証明書 (自己署名を含む) に適用されます。 自己署名証明書は運用環境での使用には適していませんが、開発およびテスト アプリケーションに役立ちます。
このチュートリアルでは、自己署名証明書を使用します。 証明書を設定するには、「クイック スタート: Azure portalを使用して Azure Key Vault から証明書を設定および取得する」を参照してください。
手記
証明書を設定した後、「Key Vault アクセス ポリシーを割り当てる」の手順に従って、Vm に Key Vault へのアクセス権を付与します。
TLS/SSL 証明書を使用したセキュリティで保護された接続
これで、VM と Key Vault インスタンスが作成され、Key Vault へのアクセス権が VM に付与されました。 次のセクションでは、Spring Boot アプリケーションで Azure Key Vault から TLS/SSL 証明書を介して安全に接続する方法について説明します。 このチュートリアルでは、次の 2 つのシナリオについて説明します。
- セキュリティで保護された受信接続を使用して Spring Boot アプリケーションを実行する
- 安全な送信接続を使用して Spring Boot アプリケーションを実行する
ヒント
次の手順では、コードが実行可能ファイルにパッケージ化され、VM にアップロードされます。 OpenJDK を VM にインストールすることを忘れないでください。
セキュリティで保護された受信接続を使用して Spring Boot アプリケーションを実行する
受信接続の TLS/SSL 証明書が Azure Key Vault から取得される場合は、次の手順に従ってアプリケーションを構成します。
pom.xml ファイルに次の依存関係を追加します。
<dependency> <groupId>com.azure.spring</groupId> <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId> <version>3.14.0</version> </dependency>
application.properties 構成ファイルで Key Vault 資格情報を構成します。
server.ssl.key-alias=<the name of the certificate in Azure Key Vault to use> server.ssl.key-store-type=AzureKeyVault server.ssl.trust-store-type=AzureKeyVault server.port=8443 azure.keyvault.uri=<the URI of the Azure Key Vault to use>
これらの値により、Spring Boot アプリは、チュートリアルの冒頭で説明したように、TLS/SSL 証明書の 読み込み アクションを実行できます。 次の表では、プロパティ値について説明します。
財産 説明 server.ssl.key-alias
az keyvault certificate create
に渡した--name
引数の値。server.ssl.key-store-type
AzureKeyVault
である必要があります。server.ssl.trust-store-type
AzureKeyVault
である必要があります。server.port
HTTPS 接続をリッスンするローカル TCP ポート。 azure.keyvault.uri
az keyvault create
から返される JSON のvaultUri
プロパティ。 この値は環境変数に保存しました。Key Vault に固有の唯一のプロパティは
azure.keyvault.uri
です。 アプリは、システム割り当てマネージド ID に Key Vault へのアクセスが許可されている VM で実行されています。 そのため、アプリにもアクセス権が付与されています。これらの変更により、Spring Boot アプリで TLS/SSL 証明書を読み込むことができます。 次の手順では、チュートリアルの冒頭で説明したように、アプリが TLS/SSL 証明書の アクションを受け入れる
を実行できるようにします。 次の内容が含まれるように、スタートアップ クラス ファイルを編集します。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class SsltestApplication { public static void main(String[] args) { SpringApplication.run(SsltestApplication.class, args); } @GetMapping(value = "/ssl-test") public String inbound(){ return "Inbound TLS is working!!"; } @GetMapping(value = "/exit") public void exit() { System.exit(0); } }
認証されていない REST GET 呼び出し内からの
System.exit(0)
の呼び出しは、デモンストレーションのみを目的としています。 実際のアプリケーションではSystem.exit(0)
を使用しないでください。このコードは、このチュートリアルの冒頭で言及された 現在の アクションを示しています。 次の一覧では、このコードに関するいくつかの詳細が強調表示されています。
- Spring Initializr によって生成された
SsltestApplication
クラスに@RestController
注釈が追加されました。 @GetMapping
の注釈がつけられたメソッドがあり、HTTP 呼び出し用のvalue
が使用されています。inbound
メソッドは、ブラウザーが/ssl-test
パスに対して HTTPS 要求を行うときに、単にあいさつ文を返します。inbound
メソッドは、サーバーが TLS/SSL 証明書をブラウザーに提示する方法を示しています。exit
メソッドを使用すると、JVM が呼び出されたときに終了します。 このメソッドは、このチュートリアルのコンテキストでサンプルを簡単に実行できるようにするための便利な方法です。
- Spring Initializr によって生成された
次のコマンドを実行してコードをコンパイルし、実行可能な JAR ファイルにパッケージ化します。
mvn clean package
<your-resource-group-name>
内に作成されたネットワーク セキュリティ グループで、IP アドレスからのポート 22 と 8443 の受信トラフィックが許可されていることを確認します。 受信トラフィックを許可するようにネットワーク セキュリティ グループの規則を構成する方法については、「ネットワーク セキュリティ グループ の作成、変更、または削除セキュリティ規則の操作」セクションを参照してください。 実行可能 JAR ファイルを VM に配置します。
cd target sftp azureuser@<your VM public IP address> put *.jar
Spring Boot アプリをビルドして VM にアップロードしたので、次の手順に従って VM で実行し、
curl
で REST エンドポイントを呼び出します。SSH を使用して VM に接続し、実行可能 JAR を実行します。
set -o noglob ssh azureuser@<your VM public IP address> "java -jar *.jar"
新しい Bash シェルを開き、次のコマンドを実行して、サーバーが TLS/SSL 証明書を提示することを確認します。
curl --insecure https://<your VM public IP address>:8443/ssl-test
exit
パスを呼び出してサーバーを強制終了し、ネットワーク ソケットを閉じます。curl --insecure https://<your VM public IP address>:8443/exit
これで、自己署名 TLS/SSL 認定資格証を使用して読み込みと提示アクションが確認できました。次は、アプリにいくつかの簡単な変更を加えて、受け入れアクションも確認します。
安全な送信接続を使用して Spring Boot アプリケーションを実行する
このセクションでは、送信接続の TLS/SSL 証明書が Azure Key Vault から取得されるように、前のセクションのコードを変更します。 その結果、Azure Key Vault からの '読み込み'、'提示'、および '受け入れ' アクションが満たされます。
pom.xml ファイルに Apache HTTP クライアントの依存関係を追加します。
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
ssl-test-outbound
という名前の新しい rest エンドポイントを追加します。 このエンドポイントは、それ自体に対して TLS ソケットを開き、TLS 接続が TLS/SSL 証明書を受け入れることを確認します。 スタートアップ クラスの前の部分を次のコードに置き換えます。import java.security.KeyStore; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.azure.security.keyvault.jca.KeyVaultLoadStoreParameter; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; @SpringBootApplication @RestController public class SsltestApplication { public static void main(String[] args) { SpringApplication.run(SsltestApplication.class, args); } @GetMapping(value = "/ssl-test") public String inbound(){ return "Inbound TLS is working!!"; } @GetMapping(value = "/ssl-test-outbound") public String outbound() throws Exception { KeyStore azureKeyVaultKeyStore = KeyStore.getInstance("AzureKeyVault"); KeyVaultLoadStoreParameter parameter = new KeyVaultLoadStoreParameter( System.getProperty("azure.keyvault.uri")); azureKeyVaultKeyStore.load(parameter); SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(azureKeyVaultKeyStore, null) .build(); HostnameVerifier allowAll = (String hostName, SSLSession session) -> true; SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, allowAll); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(csf) .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(requestFactory); String sslTest = "https://localhost:8443/ssl-test"; ResponseEntity<String> response = restTemplate.getForEntity(sslTest, String.class); return "Outbound TLS " + (response.getStatusCode() == HttpStatus.OK ? "is" : "is not") + " Working!!"; } @GetMapping(value = "/exit") public void exit() { System.exit(0); } }
次のコマンドを実行してコードをコンパイルし、実行可能な JAR ファイルにパッケージ化します。
mvn clean package
この記事の前半と同じ
sftp
コマンドを使用して、アプリをもう一度アップロードします。cd target sftp <your VM public IP address> put *.jar
VM でアプリを実行します。
set -o noglob ssh azureuser@<your VM public IP address> "java -jar *.jar"
サーバーが実行されたら、サーバーが TLS/SSL 証明書を受け入れることを確認します。 前の
curl
コマンドを発行したのと同じ Bash シェルで、次のコマンドを実行します。curl --insecure https://<your VM public IP address>:8443/ssl-test-outbound
Outbound TLS is working!!
メッセージが表示されます。exit
パスを呼び出してサーバーを強制終了し、ネットワーク ソケットを閉じます。curl --insecure https://<your VM public IP address>:8443/exit
これで、Azure Key Vault に格納されている自己署名 TLS/SSL 証明書を使用して、'読み込み'、'提示'、および '受け入れ' アクションを簡単に確認できました。
Azure Spring Apps へのデプロイ
Spring Boot アプリケーションがローカルで実行されたので、運用環境に移行します。 Azure Spring Apps を
次の手順
Spring と Azure の詳細については、Spring on Azure ドキュメント センターに進んでください。
Spring Cloud Azure Key Vault 証明書のサンプル