Compartilhar via


Habilitar HTTPS no Spring Boot com certificados do Azure Key Vault

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

Os aplicativos Spring Boot de nível de produção, sejam eles na nuvem ou locais, exigem criptografia de ponta a ponta para tráfego de rede usando protocolos TLS padrão. A maioria dos certificados TLS/SSL encontrados é detectável por meio 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 precisa ter alguma forma de carregar esses certificados, apresentá-los a conexões de rede de entrada e aceitá-los nas conexões de rede de saída.

Os aplicativos Spring Boot geralmente 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 o Microsoft Azure fornece um modo seguro e fácil de habilitar o TLS com a ajuda do Azure Key Vault e da identidade gerenciada para recursos do Azure.

Diagrama que mostra a interação dos elementos neste tutorial.

Importante

Atualmente, o início do Spring Cloud Azure Certificate 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.

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

  • Uma instância de máquina virtual (VM) 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 Azure Key Vault 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

É necessário o Spring Boot versão 2.5 ou posterior 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. Os certificados autoassinados não são adequados para uso na 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.

Observação

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 o 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 dependências a seguir no 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 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 load 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 da 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);
        }
    
    }
    

    A chamada a System.exit(0) em uma chamada GET REST não autenticada serve 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 seguinte lista 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ê fará.
    • 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 da amostra 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 no <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 as regras do grupo de segurança de rede para permitir o tráfego de entrada, confira a seção Trabalhar com regras de segurança em 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 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 encerrar 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ê modifica o código na seção anterior para que o certificado TLS/SSL para conexões de saída seja proveniente 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 ele 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 encerrar 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 dos aplicativos do Spring para que os desenvolvedores possam se concentrar no 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ços, integração de CI/CD, implantações em “blue-green” e muito mais. Para implantar seu aplicativo nos Aplicativos Spring do Azure, consulte Implantar seu primeiro aplicativo nos Aplicativos Spring do Azure.

Próximas etapas

Para saber mais sobre o Spring e o Azure, continue no Spring no Centro de Documentação do Azure.