Compartilhar via


Habilitar HTTPS no Spring Boot com certificados do Azure Key Vault

Este tutorial mostra como proteger seus aplicativos Spring Boot (incluindo o Azure Spring Apps) com certificados TLS/SSL usando o Azure Key Vault e identidades gerenciadas para recursos do Azure.

Os aplicativos Spring Boot de nível de produção, seja na nuvem ou no local, exigem criptografia de ponta a ponta para o tráfego de rede usando protocolos TLS padrão. A maioria dos certificados TLS/SSL que você encontrar são detectáveis de uma AC (autoridade de certificação raiz) pública. Às vezes, no entanto, essa descoberta não é possível. Quando os certificados não são detectáveis, o aplicativo deve ter alguma maneira de carregar esses certificados, apresentá-los a conexões de rede de entrada e aceitá-los de conexões de rede de saída.

Normalmente, os aplicativos spring boot habilitam o TLS instalando os certificados. Os certificados são instalados no repositório de chaves local da JVM que está executando o aplicativo Spring Boot. Com o Spring no Azure, os certificados não são instalados localmente. Em vez disso, a integração do Spring para Microsoft Azure fornece uma maneira segura e sem atritos de habilitar o TLS com a ajuda do Azure Key Vault e da identidade gerenciada para recursos do Azure.

Diagrama mostrando a interação de elementos neste tutorial.

Importante

Atualmente, o Spring Cloud Azure Certificate starter versão 4.x ou superior não dá suporte ao TLS/mTLS, eles configuram apenas automaticamente o cliente de certificado do Key Vault. Portanto, se você quiser usar o TLS/mTLS, não poderá migrar para a versão 4.x.

Pré-requisitos

  • Uma assinatura do Azure – crie uma gratuitamente.

  • Um JDK (Kit de Desenvolvimento do Java) com suporte na versão 11.

  • Apache Maven versão 3.0 ou superior.

  • CLI do Azure.

  • cURL ou um utilitário HTTP semelhante para testar a funcionalidade.

  • Uma instância de VM (máquina virtual) do Azure. Se você não tiver um, use o comando az vm create e a imagem do Ubuntu fornecida pelo UbuntuServer para criar uma instância de VM com uma identidade gerenciada atribuída pelo sistema habilitada. Conceda a função Contributor à identidade gerenciada atribuída pelo sistema e, em seguida, defina o scope de acesso para a sua assinatura.

  • Uma instância do Azure Key Vault. Se você não tiver um, consulte Início Rápido: Criar um cofre de chaves usando o portal do Azure.

  • Um aplicativo Spring Boot. Se você não tiver um, crie um projeto Maven com o Spring Initializr. Selecione Projeto Maven e, em Dependências, adicione a dependência Spring Web, depois selecione a versão 8 ou superior do Java.

Importante

O Spring Boot versão 2.5 ou superior é necessário para concluir as etapas neste artigo.

Definir um certificado TLS/SSL autoassinado

As etapas neste tutorial se aplicam a qualquer certificado TLS/SSL (incluindo autoassinado) armazenado diretamente no Azure Key Vault. Certificados autoassinados não são adequados para uso em produção, mas são úteis para aplicativos de desenvolvimento e teste.

Este tutorial usa um certificado autoassinado. Para definir o certificado, consulte Início Rápido: Definir e recuperar um certificado do Azure Key Vault usando o portal do Azure.

Nota

Depois de definir o certificado, conceda à VM acesso ao Key Vault seguindo as instruções em Atribuir uma política de acesso do Key Vault.

Proteger a conexão por meio do certificado TLS/SSL

Agora você tem uma VM e uma instância do Key Vault e concedeu acesso ao Key Vault para a VM. As seções a seguir mostram como se conectar com segurança por meio de certificados TLS/SSL do Azure Key Vault no aplicativo Spring Boot. Este tutorial demonstra os dois cenários a seguir:

  • Executar um aplicativo Spring Boot com conexões de entrada seguras
  • Executar um aplicativo Spring Boot com conexões de saída seguras

Dica

Nas etapas a seguir, o código será empacotado em um arquivo executável e carregado na VM. Não se esqueça de instalar do OpenJDK na VM.

Executar um aplicativo Spring Boot com conexões de entrada seguras

Quando o certificado TLS/SSL para a conexão de entrada for proveniente do Azure Key Vault, configure o aplicativo seguindo estas etapas:

  1. Adicione as seguintes dependências ao arquivo pom.xml:

    <dependency>
       <groupId>com.azure.spring</groupId>
       <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId>
       <version>3.14.0</version>
    </dependency>
    
  2. Configure as credenciais do Key Vault no arquivo de configuração 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>
    

    Esses valores permitem que o aplicativo Spring Boot execute a ação carregar para o certificado TLS/SSL, conforme mencionado no início do tutorial. A tabela a seguir descreve os valores da propriedade.

    Propriedade Descrição
    server.ssl.key-alias O valor do argumento --name que você passou para az keyvault certificate create.
    server.ssl.key-store-type Deve ser AzureKeyVault.
    server.ssl.trust-store-type Deve ser AzureKeyVault.
    server.port A porta TCP local na qual escutar as conexões HTTPS.
    azure.keyvault.uri A propriedade vaultUri do JSON de retorno de az keyvault create. Você salvou esse valor em uma variável de ambiente.

    A única propriedade específica ao Key Vault é azure.keyvault.uri. O aplicativo está em execução em uma VM cuja identidade gerenciada atribuída pelo sistema recebeu acesso ao Key Vault. Portanto, o aplicativo também recebeu acesso.

    Essas alterações permitem que o aplicativo Spring Boot carregue o certificado TLS/SSL. Na próxima etapa, você permitirá que o aplicativo execute a ação accept do certificado TLS/SSL, conforme mencionado no início do tutorial.

  3. Edite o arquivo de classe de inicialização para que ele tenha o conteúdo a seguir.

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

    Chamar System.exit(0) de dentro de uma chamada REST GET não autenticada é apenas para fins de demonstração. Não use System.exit(0) em um aplicativo real.

    Esse código ilustra a ação present mencionada no início deste tutorial. A lista a seguir realça alguns detalhes sobre este código:

    • Agora há uma anotação @RestController na classe SsltestApplication gerada pelo Spring Initializr.
    • Há um método anotado com @GetMapping, com um value para a chamada HTTP que você faz.
    • O método inbound simplesmente retorna uma saudação quando um navegador faz uma solicitação HTTPS para o caminho /ssl-test. O método inbound ilustra como o servidor apresenta o certificado TLS/SSL para o navegador.
    • O método exit faz com que a JVM saia quando invocada. Esse método é uma conveniência para facilitar a execução do exemplo no contexto deste tutorial.
  4. Execute os comandos a seguir para compilar o código e empacotá-lo em um arquivo JAR executável.

    mvn clean package
    
  5. Verifique se o grupo de segurança de rede criado em <your-resource-group-name> permite o tráfego de entrada nas portas 22 e 8443 do seu endereço IP. Para saber mais sobre como configurar regras de grupo de segurança de rede para permitir o tráfego de entrada, consulte o Trabalhar com regras de segurança seção de Criar, alterar ou excluir um grupo de segurança de rede.

  6. Coloque o arquivo JAR executável na VM.

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

    Agora que você criou o aplicativo Spring Boot e o carregou na VM, use as etapas a seguir para executá-lo na VM e chamar o ponto de extremidade REST com curl.

  7. Use o SSH para se conectar à VM e, em seguida, execute o JAR executável.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  8. Abra um novo shell do Bash e execute o comando a seguir para verificar se o servidor apresenta o certificado TLS/SSL.

    curl --insecure https://<your VM public IP address>:8443/ssl-test
    
  9. Invoque o caminho exit para matar o servidor e fechar os soquetes de rede.

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

Agora que você viu as ações load e present com um certificado TLS/SSL autoassinado, fará algumas alterações pequenas no aplicativo para ver também a ação accept.

Executar um aplicativo Spring Boot com conexões de saída seguras

Nesta seção, você modificará o código na seção anterior para que o certificado TLS/SSL para conexões de saída venha do Azure Key Vault. Portanto, as ações load, present e accept são satisfeitas no Azure Key Vault.

  1. Adicione a dependência do cliente Apache HTTP ao arquivo pom.xml:

    <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
       <version>4.5.13</version>
    </dependency>
    
  2. Adicione um novo ponto de extremidade REST chamado ssl-test-outbound. Esse ponto de extremidade abre um soquete TLS para si mesmo e verifica se a conexão TLS aceita o certificado TLS/SSL. Substitua a parte anterior da classe de inicialização pelo código a seguir.

    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. Execute os comandos a seguir para compilar o código e empacotá-lo em um arquivo JAR executável.

    mvn clean package
    
  4. Carregue o aplicativo novamente usando o mesmo comando sftp mencionado anteriormente neste artigo.

    cd target
    sftp <your VM public IP address>
    put *.jar
    
  5. Execute o aplicativo na VM.

    set -o noglob
    ssh azureuser@<your VM public IP address> "java -jar *.jar"
    
  6. Depois que o servidor estiver em execução, verifique se o servidor aceita o certificado TLS/SSL. No mesmo shell do Bash em que você emitiu o comando curl anterior, execute o comando a seguir.

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

    Você deve ver a mensagem Outbound TLS is working!!.

  7. Invoque o caminho exit para matar o servidor e fechar os soquetes de rede.

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

Agora você observou uma ilustração simples das ações load, present e accept com um certificado TLS/SSL autoassinado armazenado no Azure Key Vault.

Implantar no Azure Spring Apps

Agora que você tem o aplicativo Spring Boot em execução localmente, é hora de movê-lo para produção. Azure Spring Apps facilita o deployment de aplicativos Spring Boot no Azure sem a necessidade de alterar o código. O serviço gerencia a infraestrutura de aplicativos Spring para que os desenvolvedores possam se concentrar em seu código. O Azure Spring Apps fornece gerenciamento de ciclo de vida usando monitoramento e diagnóstico abrangentes, gerenciamento de configuração, descoberta de serviço, integração de CI/CD, implantações azul-verde e muito mais. Para implantar seu aplicativo no Azure Spring Apps, consulte Implantar seu primeiro aplicativo no Azure Spring Apps.

Próximas etapas

Para saber mais sobre o Spring e o Azure, prossiga para o centro de documentação do Spring on Azure.