Поделиться через


Включение HTTPS в Spring Boot с помощью сертификатов Azure Key Vault

В этом руководстве показано, как защитить приложения Spring Boot (включая Azure Spring Apps) с помощью TLS/SSL-сертификатов с помощью Azure Key Vault и управляемых удостоверений для ресурсов Azure.

Для рабочих приложений Spring Boot, будь то в облаке или локальной среде, требуется сквозное шифрование сетевого трафика с использованием стандартных протоколов TLS. Большинство сертификатов TLS/SSL, с которыми вы сталкиваетесь, доступны для обнаружения у общедоступного корневого центра сертификации (ЦС). Однако иногда это обнаружение невозможно. Если сертификаты недоступны для обнаружения, приложение должно иметь какой-то способ загрузки таких сертификатов, представить их для входящих сетевых подключений и принять их из исходящих сетевых подключений.

Приложения Spring Boot обычно разрешают TLS, устанавливая сертификаты. Сертификаты устанавливаются в локальное хранилище ключей JVM, на котором выполняется приложение Spring Boot. При использовании Spring в Azure сертификаты не устанавливаются локально. Вместо этого интеграция Spring для Microsoft Azure обеспечивает безопасный и беспрепятственный способ включения TLS с помощью Azure Key Vault и управляемой идентификации для ресурсов Azure.

Диаграмма, показывающая взаимодействие элементов в этом руководстве.

Важный

В настоящее время стартер для сертификатов в Azure Spring Cloud версий 4.x или более поздних не поддерживает TLS/mTLS, он автоматически настраивает клиента сертификатов Key Vault. Таким образом, если вы хотите использовать TLS/mTLS, вы не можете перенести его в версию 4.x.

Необходимые условия

  • Подписка Azure — оформите ее бесплатно.

  • Поддерживаемый пакет средств разработки Java (JDK) с версией 11.

  • Apache Maven версии 3.0 или более поздней.

  • Azure CLI.

  • cURL или аналогичную программу HTTP для тестирования функциональных возможностей.

  • Экземпляр виртуальной машины Azure. Если у вас его нет, используйте команду az vm create и образ Ubuntu, предоставленный UbuntuServer, для создания экземпляра виртуальной машины с включенным управляемым удостоверением, назначаемым системой. Предоставьте роль Contributor управляемому удостоверению, назначаемому системой, затем установите уровень доступа scope для вашей подписки.

  • Экземпляр Azure Key Vault. Если у вас его нет, ознакомьтесь с кратким руководством по . Создание хранилища ключей с помощью портала Azure.

  • Приложение Spring Boot. Если у вас его нет, создайте проект Maven с помощью Spring Initializr. Обязательно выберите Maven Project и в разделе зависимости, добавьте зависимость Spring Web, а затем выберите Java версии 8 или более поздней.

Важный

Для выполнения действий, описанных в этой статье, требуется spring Boot версии 2.5 или более поздней.

Настройка самозаверяющего TLS/SSL-сертификата

Действия, описанные в этом руководстве, применяются к любому СЕРТИФИКАТу TLS/SSL (включая самозаверяющий сертификат), хранящийся непосредственно в Azure Key Vault. Самозаверяющий сертификат не подходит для использования в рабочей среде, но полезен для разработки и тестирования приложений.

В этом руководстве используется самоподписанный сертификат. Чтобы настроить сертификат, см. краткое руководство : Настройка и получение сертификата из Azure Key Vault с помощью портала Azure.

Заметка

После установки сертификата предоставьте виртуальной машине доступ к Key Vault, следуя инструкциям в Назначить политику доступа Key Vault.

Безопасное подключение через TLS/SSL-сертификат

Теперь у вас есть виртуальная машина и экземпляр Key Vault, и виртуальная машина получила доступ к Key Vault. В следующих разделах показано, как безопасно подключаться через TLS/SSL-сертификаты из Azure Key Vault в приложении Spring Boot. В этом руководстве показаны следующие два сценария:

  • Запуск приложения Spring Boot с безопасными входящими подключениями
  • Запуск приложения Spring Boot с безопасными исходящими подключениями

Совет

В следующих шагах код будет упаковен в исполняемый файл и отправлен на виртуальную машину. Не забудьте установить OpenJDK на виртуальной машине.

Запуск приложения Spring Boot с безопасными входящими подключениями

Когда tls/SSL-сертификат для входящего подключения поступает из Azure Key Vault, настройте приложение, выполнив следующие действия.

  1. Добавьте следующие зависимости в файл pom.xml:

    <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId>
       <version>3.14.0</version>
    </dependency>
    
  2. Настройте учетные данные Key Vault в файле конфигурации application.properties.

    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 Значение аргумента --name, который вы передали az keyvault certificate create.
    server.ssl.key-store-type Должен быть AzureKeyVault.
    server.ssl.trust-store-type Должен быть AzureKeyVault.
    server.port Локальный TCP-порт, на котором выполняется прослушивание HTTPS-подключений.
    azure.keyvault.uri Свойство vaultUri в возвращаемом JSON от az keyvault create. Вы сохранили это значение в переменной среды.

    Единственным свойством, характерным для Key Vault, является azure.keyvault.uri. Приложение запущено на виртуальной машине, которой предоставлено системно назначенное управляемое удостоверение для доступа к Key Vault. Поэтому приложению также предоставлен доступ.

    Эти изменения позволяют приложению Spring Boot загрузить TLS/SSL-сертификат. На следующем шаге вы позволите приложению выполнить принять действие для TLS/SSL-сертификата, как упоминалось в начале руководства.

  3. Измените файл класса запуска, чтобы он получил следующее содержимое.

    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);
        }
    
    }
    

    Вызов System.exit(0) из неавторентированного вызова REST GET предназначен только для демонстрационных целей. Не используйте System.exit(0) в реальном приложении.

    Этот код иллюстрирует представленное действие, упомянутое в начале этого руководства. В следующем списке приведены некоторые сведения об этом коде:

    • Теперь на классе SsltestApplication, созданном Spring Initializr, присутствует аннотация @RestController.
    • Существует метод, аннотированный с @GetMapping, с value для вызываемого HTTP-вызова.
    • Метод inbound возвращает приветствие, когда браузер обращается с HTTPS-запросом к пути /ssl-test. Метод inbound иллюстрирует, как сервер представляет TLS/SSL-сертификат браузеру.
    • Метод exit приводит к выходу JVM при вызове. Этот метод удобен для упрощения выполнения примера в контексте этого руководства.
  4. Выполните следующие команды, чтобы скомпилировать код и упаковать его в исполняемый JAR-файл.

    mvn clean package
    
  5. Убедитесь, что группа безопасности сети, созданная в <your-resource-group-name>, разрешает входящий трафик через порты 22 и 8443 с вашего IP-адреса. Сведения о настройке правил группы безопасности сети для разрешения входящего трафика см. в разделе Работа с правилами безопасности раздела Создание, изменение или удаление группы безопасности сети.

  6. Поместите исполняемый JAR-файл на виртуальную машину.

    cd target
    sftp azureuser@<your VM public IP address>
    put *.jar
    

    Теперь, когда вы создали приложение Spring Boot и отправили его на виртуальную машину, выполните следующие действия, чтобы запустить его на виртуальной машине и вызвать конечную точку REST с curl.

  7. Используйте SSH для подключения к виртуальной машине, а затем запустите исполняемый JAR-файл.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  8. Откройте новую оболочку Bash и выполните следующую команду, чтобы убедиться, что сервер представляет TLS/SSL-сертификат.

    curl --insecure https://<your VM public IP address>:8443/ssl-test
    
  9. Вызовите путь exit, чтобы убить сервер и закрыть сетевые сокеты.

    curl --insecure https://<your VM public IP address>:8443/exit
    

Теперь, когда вы видели загрузку и представление действий с самозаверяющимся TLS/SSL-сертификатом, внесите тривиальные изменения в приложение, чтобы увидеть действие принятия.

Запуск приложения Spring Boot с безопасными исходящими подключениями

В этом разделе вы измените код в предыдущем разделе, чтобы TLS/SSL-сертификат для исходящих подключений был получен из Azure Key Vault. Поэтому загрузки, присутствующихи принять действия удовлетворены из Azure Key Vault.

  1. Добавьте зависимость клиента Apache HTTP в файл pom.xml:

    <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
       <version>4.5.13</version>
    </dependency>
    
  2. Добавьте новую конечную точку REST с именем ssl-test-outbound. Эта конечная точка открывает сокет 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);
        }
    
    }
    
  3. Выполните следующие команды, чтобы скомпилировать код и упаковать его в исполняемый JAR-файл.

    mvn clean package
    
  4. Отправьте приложение еще раз с помощью той же команды sftp из предыдущей статьи.

    cd target
    sftp <your VM public IP address>
    put *.jar
    
  5. Запустите приложение на виртуальной машине.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  6. После запуска сервера убедитесь, что сервер принимает TLS/SSL-сертификат. В той же оболочке Bash, где вы выпустили предыдущую команду curl, выполните следующую команду.

    curl --insecure https://<your VM public IP address>:8443/ssl-test-outbound
    

    Должно появиться сообщение Outbound TLS is working!!.

  7. Вызовите путь exit, чтобы убить сервер и закрыть сетевые сокеты.

    curl --insecure https://<your VM public IP address>:8443/exit
    

Теперь вы наблюдали простую иллюстрацию действий загрузки, присутствияи принятия с использованием самозаверяющего сертификата TLS/SSL, хранящегося в Azure Key Vault.

Развертывание в Azure Spring Apps

Теперь, когда у вас есть приложение Spring Boot, работающее локально, пришло время переместить его в рабочую среду. Azure Spring Apps упрощает развертывание приложений Spring Boot в Azure без каких-либо изменений кода. Служба управляет инфраструктурой приложений Spring, чтобы разработчики могли сосредоточиться на коде. Azure Spring Apps предоставляет управление жизненным циклом с помощью комплексного мониторинга и диагностики, управления конфигурацией, обнаружения служб, интеграции CI/CD, сине-зелёных развертываний и другими функциями. Сведения о развертывании приложения в Azure Spring Apps см. в статье Развертывание первого приложения в Azure Spring Apps.

Дальнейшие действия

Чтобы узнать больше о Spring и Azure, перейдите в центр документации Spring в Azure.