Sunday, March 28, 2021

Wildfly: Habilitando HTTPS para suas Aplicações 1

No artigo Segurança com Java: Certificados, fizemos um pequeno apanhado teórico sobre o TLS, vimos o que são TrustStore e KeyStore e vimos também algumas opções sobre gerenciamento de certificados em Java, seja via código ou através do utilitário keytool.


Neste artigo (em 2 partes) criaremos um exemplo prático. Vamos criar um REST endpoint simples, publicá-lo no Wildfly e acessá-lo via HTTPS (TLS). Para tanto precisamos:

  1.  Criar um par de chaves pública/privada e o certificado para o nosso servidor
  2.  Habilitar o sistema de TLS e HTTPS listener do Wildfly com base nas chaves criadas no passo anterior
A versão do Wildfly utilizada neste exemplo é a 23. A do Java é 11.

1 Criando o par de chaves e o certificado para o servidor

Usamos o keytool para gerar as chaves:


keytool -genkeypair -alias localhost -keyalg RSA -keysize 2048 -validity 365 -keystore server.keystore


O comando anterior cria um arquivo chamado server.keystore que contem uma chave privada e um certificado válido por 365 dias o qual contem a chave pública que será apresentado aos clientes das aplicações publicadas no servidor. O domínio é localhost

Guarde o password para os próximos passos.


2 Configurar o TLS no Wildfly

Há várias formas de se habilitar o TLS para aplicações publicadas no Wildfly. Neste caso o faremos via Elytron, que é um framework de segurança adicionado ao Wildfly. Por meio do Elytron podemos gerenciar configurações de acesso ao próprio servidor e à aplicações nele publicadas. As áreas envolvidas nesse gerenciamento são Autenticação, Autorização, Armazenamento de credenciais e TLS.

Copie o arquivo server.keystore do passo anterior para  JBOSS_HOME/standalone/configuration


Nota: Os comandos que executaremos nos próximos passos serão através do utilitário jboss-cli.sh (ou jboss-cli.bat se o seu ambiente for Windows) localizado em JBOSS_HOME/bin. Execute esse arquivo e depois execute o comando connect.

Agora criamos uma keystore chamada httpsKS dentro do servidor que referencia o nosso arquivo server.keystore:


/subsystem=elytron/key-store=httpsKS:add(path=server.keystore,relative-to=jboss.server.config.dir,credential-reference={clear-text=changeit},type=JKS)


Agora criamos um key-manager para o qual damos o nome httpsKM que referencia a keystore criada no passo anterior:


/subsystem=elytron/key-manager=httpsKM:add(key-store=httpsKS,credential-reference={clear-text=changeit})

Agora configuramos um contexto TLS que vamos chamar de httpsSSC, o qual referencia o httpsKM criado no passo anterior:

/subsystem=elytron/server-ssl-context=httpsSSC:add(key-manager=httpsKM,protocols=["TLSv1.2"])


Como estamos estabelendo essas configuraões de segurança via Elytron, que é um framework novo, precisamos checar se o HTTPS-listener está usando o sitema legado de segurança do Wildfly para configuração do TLS. Execute o seguinte commando:

/subsystem=undertow/server=default-server/https-listener=https:read-attribute(name=security-realm)
{
    "outcome" => "success",
    "result" => "ApplicationRealm"
}

O resultado do comando anterior nos diz que o HTTPS-listener está usando o sistema de segurança legado ApplicationRelam para configuração TLS. 

Undertow não pode referenciar o TLS context no sistema legado e no Elytron ao mesmo tempo. Então temos que remover a referencia para o sistema de segurança legado e atualizar o HTTPS-listener para usar o contexto TLS do Elytron. Para esse procedimento utilizamos a seguinte operação em lote (batch):

batch
/subsystem=undertow/server=default-server/https-listener=https:undefine-attribute(name=security-realm)
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context,value=httpsSSC)
run-batch

Em seguida reiniciamos o Wildfly com o commando reload.  

Procedimento completo no print abaixo:

Pronto!

HTTPS agora está habilitado para todas as aplicações publicadas nesse servidor. Em termos de configuração, os camandos anteriores equivalem a adicionar essas linhas no arquivo standloane.xml:


<subsystem>
        ...
                <tls>
                     <key-stores>
                         <key-store name="demoKeyStore">
                             <credential-reference clear-text="changeit">
                             <implementation type="JKS">
                             <file path="server.keystore" relative-to="jboss.server.config.dir">
                         </file></implementation></credential-reference></key-store>
                     </key-stores>
                     <key-managers>
                         <key-manager key-store="demoKeyStore" name="demoKeyManager">
                             <credential-reference clear-text="changeit">
                         </credential-reference></key-manager>
                     </key-managers>
                     <server-ssl-contexts>
                         <server-ssl-context key-manager="demoKeyManager" name="demoSSLContext" protocols="TLSv1.2">
                     </server-ssl-context></server-ssl-contexts>
                 </tls>
    </subsystem>
...
<subsystem default-security-domain="other" default-server="default-server" default-servlet-container="default" default-virtual-host="default-host" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}" xmlns="urn:jboss:domain:undertow:10.0">
                 <buffer-cache name="default">
                 <server name="default-server">
                     <http-listener enable-http2="true" name="default" redirect-socket="https" socket-binding="http">
                     <https-listener enable-http2="true" name="https" socket-binding="https" ssl-context="demoSSLContext">
                     <host alias="localhost" name="default-host">
                         <location handler="welcome-content" name="/">
                         <http-invoker security-realm="ApplicationRealm">
                     </http-invoker></location></host>
                 </https-listener></http-listener></server>
    
...
</buffer-cache></subsystem> 

Agora podemos acessar o console em https://localhost:8443/ e baixar o certificado de localhost. Como o certificado é assinado por nós mesmos, provavelmente seu browser vai emitir um alerta de que não reconhece essa autoridade certificadora. Tal alerta pode ser ignorado. 

Clique no icone do cadeado no canto superior direito, em certificate, depois export certificate: 

Salve este certificado para usarmos em nossa aplicação java que será um cliente desse servidor.




Também podemos checar o certificado atraves do utilitario openssl.


openssl s_client -connect localhost:8443



Na segunda parte deste artigo, publicamos um endpoint no wildfly e o acessamos de forma segura com uma aplicação cliente java que usará o nosso certificado localhost.


       

No comments:

Post a Comment