Skip to content

rchafik/streaming

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Expondo um OCI Streaming privado com Load Balancer Layer 7 e SDK Java

Como configurar um Load Balancer (Layer 7) para expor um Streaming privado na OCI e exemplos em Java para produzir e consumir mensagens utilizando SDK da OCI.

IMPORTANTE: Este blog foi desenvolvido exclusivamente para fins educacionais e de estudo. Ele fornece um ambiente para que aprendizes possam experimentar e adquirir experiência prática em um cenário controlado. É importante destacar que as configurações e práticas de segurança utilizadas neste laboratório podem não ser adequadas para cenários do mundo real. As considerações de segurança para aplicações reais costumam ser muito mais complexas e dinâmicas. Portanto, antes de implementar qualquer uma das técnicas ou configurações demonstradas aqui em um ambiente de produção, é essencial realizar uma avaliação e revisão de segurança abrangente. Essa revisão deve incluir todos os aspectos de segurança, como controle de acesso, criptografia, monitoramento e conformidade, garantindo que o sistema esteja alinhado com as políticas e padrões de segurança da organização. A segurança deve sempre ser uma prioridade máxima ao fazer a transição de um ambiente de laboratório para uma implementação no mundo real.

caso de uso

Para esse exemplo nós não iremos utilizar a biblioteca do Apache Kafka, nós iremos utilizar a SDK da OCI para Streaming, que vai interagir através da porta 443 e protocolo https (essa informação é importante para configurarmos o backend no Load Balancer).

Objetivos

  • criação de um Streaming e de um Streaming Pool privado;
  • criação e configuração de um Load Balancer OCI de camada 7:
    • configuração do Streaming como backend;
    • extração dos certificados do Streaming privado e como configurar isso no backend do Load Balancer.
  • exemplos de códigos em Java para consumir e produzir mensagens, além dos erros que ocorrem no caso de problemas de configuração do Load Balancer.

Tecnologias e dependências

O projeto usa:

  • Java 17;
  • Maven;
  • OCI Java SDK (common, streaming e cliente HTTP Jersey);
  • Guava;
  • Apache Commons Lang;

Classes do projeto

Producer

Arquivo: src/main/java/com/example/Producer.java

Responsável por publicar mensagens no OCI Streaming.

Principais pontos:

  • necessário informar o OCID do Stream;
  • informar o endpoint do serviço, neste caso será o endereço do Load Balancer;
  • permite duas formas de conexão:
    • autenticação padrão via arquivo de configuração OCI;
    • autenticação usando truststore JKS e SSLContext customizado, porque vamos demonstrar um exemplo utilizando um certificado autoassinado, para nos comunicarmos com o listener do Load Balancer através do protocolo HTTPS;
  • cria 50 mensagens de exemplo com chave e valor;
  • envia o lote com putMessages;
  • exibe no console o resultado de cada envio, incluindo partição, offset e erros.

Consumer

Arquivo: src/main/java/com/example/Consumer.java

Responsável por consumir mensagens do OCI Streaming.

Principais pontos:

  • usa autenticação baseada na configuração padrão OCI;
  • cria um StreamClient apontando para o endpoint do stream;
  • cria um cursor de grupo (group cursor) para o grupo exampleGroup;
  • usa o tipo TrimHorizon, ou seja, começa a leitura desde o início disponível do stream;
  • lê mensagens em lotes de até 25 registros;
  • imprime no console a chave e o valor de cada mensagem lida;
  • atualiza o cursor a cada iteração usando opc-next-cursor.

O método simpleMessageLoop executa 10 ciclos de leitura com pausa de 1 segundo entre as requisições.

Configurações importantes

Hoje o código possui alguns valores fixos diretamente nas classes:

  • OCID do stream;
  • endpoint do OCI Streaming;
  • path da truststore;
  • senha da truststore;
  • perfil OCI DEFAULT.

Para uso em ambiente real, o ideal é externalizar essas configurações para:

  • variáveis de ambiente;
  • arquivo .properties ou .yaml;
  • argumentos de linha de comando;
  • perfis Maven ou configuração centralizada.

Criação de um Streaming e de um Streaming Pool privado

Navegue no Menu Principal -> Analytics & AI -> Messaging -> Streaming.

Vamos começar pela criação de um Stream pool privado:

stream pool privado

Podemos deixar as demais informações conforme abaixo:

stream pool privado

Agora que já temos o nosso Stream Pool Privado configurado, vamos para criação do Stream. Navegue no Menu Principal -> Analytics & AI -> Messaging -> Streaming -> Streams, clique no botão Create stream.

create stream

Selecione o Stream Pool Privado que criamos anteriormente, deixe as demais informações como estão e clique no botão create:

create stream

Precisamos coletar algumas informações do Stream criado, para os próximos passos

  • o atributo OCID;
  • o atributo Messages endpoint;

Atenção:

  • Essas informações serão utilizadas no código Java e na configuração do Load Balancer.
  • Por se tratar de conexão privada, você pode escolher:
    • utilizar um Bastion para que você consiga acessar esse ambiente privado;
    • criar uma VM que tenha IP público, para se conectar via chave privada, e por sua vez, essa VM ter acesso ao Stream criado;
    • utilizar o Cloud Shell da console OCI.

Testando o Código Java apontando diretamente para o Stream

vamos testar primeiro apontando para o Stream, para isolar problema de código vs. problema de rede/LB

Altere nas classes abaixo, os seguintes atributos:

  • ociStreamOcid: informe o OCID do Stream que foi coletado no passo anterior;
  • ociMessageEndpoint: utilize o valor que consta em Messages endpoint do seu Stream.

Classes Java:

Produza e consuma as mensagens. Valide se não há erros nos logs de execução.

Atenção: Neste momento, deixe o atributo usarJks = false;, depois abordaremos isso.

Load Balancer: a hora da verdade

Vamos considerar o caso de uso! Normalmente queremos utilizar Streaming para produzir e consumir mensagens, usando porta TCP e querendo muita performance. Em alguns casos, precisamos estabelecer perímetros de segurança e evitar a exposição de protocolos nativos de mensageria na internet. Para o nosso caso, vamos utilizar uma abordagem diferente, expor um Stream privado através de um Load Balancer via protocolo HTTPS e na porta 443, usando a SDK da OCI, que nos ajuda a implementar esse cenário.

Lembrete: podemos associar um WAF no Load Balancer da OCI, para deixarmos tudo ainda mais seguro!

Criando e Configurando um Load Balancer

Navegue no Menu Principal -> Networking -> Load balancers -> Load balancers -> Clique no botão Create load balancer

The load balancer service provides layer 4 and layer 7 (TCP and HTTP) load balancing that routes network traffic in a more complex manner. Load balancing improves resource utilization, facilitates scaling, and helps to ensure high availability.

create load balancer

Observações:

  • Vamos utilizar um Load Balancer privado;
  • Garanta que a VCN e Subnet escolhida para criar seu Load Balancer tenha as devidas liberações para se conectar no Stream;
  • Além disso, onde seu código Java for executado, também precisará de conectividade ao Load Balancer que será criado!

Vamos manter essas informações conforme sugeridas:

create load balancer

create load balancer

Vamos agora configurar o Backend do Load Balancer:

backend

Vamos manter as informações default, e após criação, vamos editar para informar o IP do Message EndPoint do Stream para o BackEnd. Vamos detalhar mais sobre isso nos próximos passos!

Para configurar o health check policy vamos utilizar:

  • Protocol: TCP
  • Port: 443

health check policy

As demais informações manteremos como estão:

backend

Vamos iniciar as configurações do Listener do Load Balancer:

  • Neste momento vamos configurar o protocolo como HTTP;
  • Nosso listener vai utilizar a porta 443;
  • Não iremos configurar nenhum certificado neste momento, apenas vamos deixar a informação padrão.

setup listener

Na configuração de Logs vamos criar neste momento apenas o Log de Erro:

logs

Não iremos ativar o Access Logs, vamos manter como está:

logs

Vamos revisar as configurações e submeter as informações para iniciar a criação do nosso Load Balancer.

Quando o Load Balancer for criado o mesmo terá um IP privado atribuído e o campo Overall health = Incomplete:

load balancer criado

Precisamos acessar o mesmo e navegar até a aba Backend sets, que estará com o campo Health = Incomplete. Depois vamos clicar no link do Backend set que está criado:

backend set

Estamos na configuração do Backend set do Load Balancer, e vamos navegar até a aba Backends, e clicar no botão Add backends:

add backend

Precisamos informar o IP associado ao endpoint privado do Stream. Nos passos anteriores, coletamos o atributo Messages endpoint do Stream. Vamos usar o comando telnet para identificar o IP, informando o host e a porta 443:

telnet a4irodirgieq.streaming.sa-saopaulo-1.oci.oraclecloud.com 443
Trying 10.0.10.222...
Connected to a4irodirgieq.streaming.sa-saopaulo-1.oci.oraclecloud.com.

Informamos o IP coletado no campo abaixo, usamos a porta 443, e depois clicamos no botão Add:

add backend

Temos que aguardar o Load Balancer ficar com o atributo Health = Ok:

health ok

Agora vamos aos testes, mas antes vamos coletar algumas informações do Load Balancer:

  • IP address, que fica na aba Details;
  • Protocolo e Port, que ficam na aba Listener.

Juntando todas as informações, temos o seguinte endereço para acessarmos o nosso Load Balancer:

http://10.0.10.127:443

Atenção: neste momento estamos usando o protocolo HTTP no Listener e porta 443.

Vamos alterar a classe Producer: src/main/java/com/example/Producer.java, mudando o atributo ociMessageEndpoint para o endereço do nosso Load Balancer:

 final String ociMessageEndpoint = "http://10.0.10.127:443";

Ao executar a classe vamos encontrar alguns erros:

logs de erro do Load Balancer (habilite o mesmo no Load Balancer):
errorLog":{"errorDetails":"Backend 10.0.10.222 closed connection abruptly","type":"backEnd"}

logs de execução da sua classe Java
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center></center>
</body>
</html>

Atenção

Aqui está um ponto muito importante: temos que extrair alguns certificados do Stream e importá-los no Load Balancer, para usarmos no Back End, porque ao comunicarmos com Stream via Load Balancer, temos que manter internamente a comunicação como HTTPS.

Vamos extrair os certificados necessários do Stream, informando o fqdn completo e a porta 443:

openssl s_client -connect a4irodirgieq.streaming.sa-saopaulo-1.oci.oraclecloud.com:443 -showcerts

Você encontrará uma cadeia de certificados (texto que inicia com -----BEGIN CERTIFICATE----- e termina com -----END CERTIFICATE-----).

O primeiro certificado normalmente corresponde ao certificado do serviço, e os demais fazem parte da cadeia de CA/intermediários. O primeiro será o SSL certificate e o outro será o CA certificate. Vamos importar ambos no Load Balancer.

Ao entrar no Load Balancer criado, acessaremos a aba Certificates and ciphers e depois vamos na opção Load balancer managed certificates, e clicaremos no botão Add Certificate:

add certificate

Informe o nome do certificado a ser criado. Utilize a opção "Paste SSL certificate" e cole o primeiro certificado que extraímos do Stream. Habilite a opção Specify CA certificate, use "Paste CA certificate" e cole o outro certificado:

create certificate

Depois de criar o certificado, vamos na aba Backend sets e clicar em Edit, opção do botão "...":

create certificate

Habilite a opção Use SSL, e no campo Certificate resource, escolha a opção Load balancer managed certificate. Vamos escolher o certificado que acabamos de criar e depois em Save Changes:

set certificate

Vamos executar a classe Producer: src/main/java/com/example/Producer.java e podemos notar que não há mais erros, as mensagens foram publicadas com sucesso:

Publishing 50 messages to stream ocid1.stream.oc1.sa-saopaulo-1.xxx.
Published message to partition 0, offset 600.
Published message to partition 0, offset 601.
Published message to partition 0, offset 602.
Published message to partition 0, offset 603.
Published message to partition 0, offset 604.
Published message to partition 0, offset 605.
Published message to partition 0, offset 606.
Published message to partition 0, offset 607.
Published message to partition 0, offset 608.
Published message to partition 0, offset 609.
Published message to partition 0, offset 610.
Published message to partition 0, offset 611.
Published message to partition 0, offset 612.
Published message to partition 0, offset 613.
Published message to partition 0, offset 614.
Published message to partition 0, offset 615.
Published message to partition 0, offset 616.
Published message to partition 0, offset 617.
Published message to partition 0, offset 618.
Published message to partition 0, offset 619.
Published message to partition 0, offset 620.
Published message to partition 0, offset 621.
Published message to partition 0, offset 622.
Published message to partition 0, offset 623.
Published message to partition 0, offset 624.
Published message to partition 0, offset 625.
Published message to partition 0, offset 626.
Published message to partition 0, offset 627.
Published message to partition 0, offset 628.
Published message to partition 0, offset 629.
Published message to partition 0, offset 630.
Published message to partition 0, offset 631.
Published message to partition 0, offset 632.
Published message to partition 0, offset 633.
Published message to partition 0, offset 634.
Published message to partition 0, offset 635.
Published message to partition 0, offset 636.
Published message to partition 0, offset 637.
Published message to partition 0, offset 638.
Published message to partition 0, offset 639.
Published message to partition 0, offset 640.
Published message to partition 0, offset 641.
Published message to partition 0, offset 642.
Published message to partition 0, offset 643.
Published message to partition 0, offset 644.
Published message to partition 0, offset 645.
Published message to partition 0, offset 646.
Published message to partition 0, offset 647.
Published message to partition 0, offset 648.
Published message to partition 0, offset 649.

O importante é lembrar que ao configurar o roteamento para o back end, caso o mesmo seja HTTPS, você precisará importar os certificados, para estabelecer de forma segura a conexão.

Configurar o Listener do Load Balancer para HTTPS

Até o momento usamos o nosso Load Balancer com Listener utilizando o protocolo HTTP. Nosso objetivo é utilizar o protocolo HTTPS e para isso, temos alguns procedimentos:

  • gerar um certificado autoassinado;
  • configurar o certificado autoassinado no Listener do Load Balancer;
  • fazer ajustes no código Java para utilizar um JKS com o certificado gerado, criando uma relação de confiança entre a aplicação e o ambiente com certificado autoassinado.

Para gerar o certificado autoassinado:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout chave.key -out certificado.crt \
-subj "/C=BR/ST=SP/L=SaoPaulo/O=OracleLab/CN=10.0.10.127"

Atenção Utilizei o IP privado do Load Balancer no atributo CN (common name) no certificado. O ideal é incluir subjectAltName com o IP/DNS. O código contorna isso usando NoopHostnameVerifier. Isso deve ser usado apenas em ambiente de testes.

Ao final desta execução, teremos dois arquivos gerados:

  • chave.key: chave privada;
  • certificado.crt: certificado

Vamos voltar ao Load Balancer e criar um novo certificado. Ao entrar no Load Balancer criado, acessaremos a aba Certificates and ciphers e depois vamos na opção Load balancer managed certificates, e clicaremos no botão Add Certificate.

Informe o nome do certificado a ser criado. Utilize a opção "Paste SSL certificate" e cole o conteúdo do arquivo certificado.crt. Não vamos habilitar a opção Specify CA certificate. Habilite a opção Specify private key, use "Paste private key" e cole o conteúdo do arquivo chave.key. Ao final, clique no botão "Add certificate".

listener certificate

Precisamos alterar o Listener do Load Balancer. Na aba Listeners, clique no botão "..." e depois em "Edit":

edit listener

Neste momento, vamos:

  • alterar Protocol para HTTPS;
  • manter Port igual 443;
  • em Certificate resource utilizar Load balancer managed certificate e selecionar o certificado criado anteriormente para o listener do Load Balancer (não utilize o certificado criado para o backend set)

Clique em "Save changes":

edit listener

O seu Listener estará desta forma:

listener https

Agora nosso endereço para acessar o Load Balancer ficou desta forma, assim como o atributo ociMessageEndpoint nas Classes Java:

https://10.0.10.127

 final String ociMessageEndpoint = "https://10.0.10.127";

Se executarmos o código vamos ter o seguinte erro porque nosso certificado é auto assinado:

Exception in thread "main" com.oracle.bmc.model.BmcException: (-1, , true) javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target (outbound opc-request-id: 8399EAE78093406D94BCC80CF4987C7F)
        at com.oracle.bmc.http.internal.ClientCall.lambda$callAsyncImpl$23(ClientCall.java:1080)
        at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934)
        at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911)
        at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
        at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
        at org.glassfish.jersey.client.JerseyInvocation$InvocationResponseCallback.failed(JerseyInvocation.java:1063)
        at org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:250)
        at org.glassfish.jersey.client.ClientRuntime.processFailure(ClientRuntime.java:245)
        at org.glassfish.jersey.client.ClientRuntime.access$100(ClientRuntime.java:62)
        at org.glassfish.jersey.client.ClientRuntime$2.lambda$failure$1(ClientRuntime.java:181)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
        at org.glassfish.jersey.client.ClientRuntime$2.failure(ClientRuntime.java:181)
        at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:545)
        at org.glassfish.jersey.client.ClientRuntime.lambda$null$6(ClientRuntime.java:185)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:288)
        at org.glassfish.jersey.client.ClientRuntime.lambda$createRunnableForAsyncProcessing$7(ClientRuntime.java:159)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at java.base/java.lang.Thread.run(Thread.java:842)
Caused by: java.util.concurrent.CompletionException: javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:332)
        at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:347)
        at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:636)
        ... 28 more
Caused by: javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:534)
        at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:541)
        ... 13 more
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:383)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:326)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:481)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:459)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:206)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1421)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72)
        at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:486)
        ... 14 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
        at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
        at java.base/sun.security.validator.Validator.validate(Validator.java:264)
        at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
        at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
        at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:638)
        ... 37 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:148)
        at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:129)
        at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
        at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
        ... 42 more

Para resolver isso temos que criar um arquivo JKS com o certificado que geramos, para que possamos estabelecer uma relação de confiança entre a conexão do código Java com o Load Balancer.

Um arquivo JKS (Java KeyStore) é um repositório binário protegido por senha, específico do Java, usado para armazenar certificados de segurança (públicos) e chaves privadas. Ele é amplamente utilizado em ambientes Java para garantir a autenticidade e a criptografia SSL. Neste exemplo, o JKS será usado como truststore, armazenando o certificado público confiável do listener.

Para criar o arquivo JKS e importar o certificado que geramos para o Listener do Load Balancer, execute o comando:

keytool -importcert \
  -noprompt \
  -alias labStreaming \
  -file certificado.crt \
  -keystore truststore.jks \
  -storepass changeit

Vamos executar a produção de mensagens, mudando os atributos conforme segue:

  • trustStorePath: para o path que está o seu arquivo jks criado no passo anterior;
  • usarJks: alterar para true, para o código utilizar o arquivo JKS criado.

As mensagens serão publicadas com sucesso.

Caso seja necessário consumir mensagens via HTTPS com certificado autoassinado, implemente no Consumer a mesma configuração de SSLContext e truststore usada no Producer.

Conclusão

Neste artigo, mostramos que é possível expor um OCI Streaming privado por meio de um Load Balancer Layer 7, usando a SDK da OCI sobre HTTPS/443, sem depender do protocolo nativo do Kafka. Também vimos que, embora o listener possa receber requisições HTTP ou HTTPS, a comunicação com o backend precisa respeitar o protocolo real do serviço de destino.

O principal aprendizado deste cenário é que, quando o backend utiliza HTTPS, não basta apenas publicar o endpoint no Load Balancer: é necessário configurar corretamente a relação de confiança entre o Load Balancer e o serviço privado, incluindo a importação dos certificados exigidos pelo backend. Foi justamente esse ajuste que eliminou o erro 502 Bad Gateway e permitiu a publicação das mensagens com sucesso.

Também apresentamos um exemplo de como configurar o Listener do Load Balancer com um certificado autoassinado e como ajustar o código Java para utilizar um arquivo JKS, mantendo a comunicação funcionando.

Em ambientes reais, esse padrão pode ser útil quando há exigências de isolamento de rede, controle de exposição e adoção de serviços adicionais de segurança, como WAF, observabilidade e políticas mais rígidas de acesso.

Referências

Autores

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages