Integrating applications with Keycloak using self signed certificate via Camel-Quarkus: Simplifying Secure Integrations on OpenShift


Introduction

In today’s cloud-native landscape, identity and access management solutions like Keycloak play a critical role in securing enterprise applications. However, integrating APIs with Keycloak can be challenging, particularly when working with client credentials and handling deployments in environments using self-signed certificates.

In this article, I’ll demonstrate how to:

  1. Build a Camel-Quarkus-based API that generates Keycloak tokens using client ID and secret.
  2. Deploy the solution on OpenShift Container Platform.
  3. Overcome the challenge of injecting a self-signed certificate into your Camel application to support HTTPS connections securely.

This solution addresses a common enterprise scenario where organizations keep their Keycloak instance behind a private network, accessible only within the private network via HTTPS with a self-signed certificate.


Prerequisites

Before we dive into the implementation, ensure you have the following:

  1. Access to a running Openshift Cluster.
  2. A running Keycloak instance with a configured realm and client.
  3. OpenJDK (version >= 17) installed on your local machine.
  4. Maven for building the application.
  5. OpenShift CLI (oc) for deploying and managing resources.
  6. A basic understanding of Camel-Quarkus, Keycloak, and OpenShift.




Deployment Scenario

This article demonstrates a deployment scenario that addresses a common architectural challenge in securing enterprise applications.??

Deployment Scenario Overview?

An OpenShift cluster hosts enterprise applications within a secured private network. To ensure controlled external access, the setup includes:??

1. API Gateway and Public Service: Deployed on a public-facing node but secured behind the corporate firewall, enabling external communication.??

2. Keycloak for Authentication: Deployed within the private network to manage identity and access securely.??

In this architecture, external consumers who need to access private enterprise applications must first generate an OAuth token from the Keycloak server.??

Architectural Challenge?

The primary challenge is that the Keycloak server uses a self-signed certificate for HTTPS communication. This introduces complexities for external consumers attempting to authenticate, as they cannot directly communicate with the Keycloak server within the private network.??

To address this, a service deployed in the DMZ zone (demilitarized zone) acts as an intermediary:??

1. Token Request Handling: External consumers provide their clientId and clientSecret to this service.??

2. Secure Token Retrieval: The service communicates with the private Keycloak server to obtain the OAuth token on behalf of the consumers.??

Proposed Solution

Using Camel-Quarkus, we demonstrate how to:??

  • Implement the intermediary service to securely handle token requests.??
  • Store Keycloak’s self-signed certificate in a .jks (Java Keystore) format as a secret in OpenShift.??
  • Dynamically inject the certificate into the Camel application when communicating with the private Keycloak server.??

This approach ensures:??

  • Seamless Integration: External consumers can request tokens without direct exposure to the Keycloak server.??
  • Enhanced Security: Self-signed certificates remain securely managed within the OpenShift environment.??

By following this architecture, enterprises can achieve a secure, scalable, and effective way to integrate external consumers with private applications using Keycloak and OpenShift.? Refer to the below figures.


Intermediary camel service to talk to an internal Keycloak service running using self signed certificate
Figure 1: An intermediary Camel service is used to talk to a private Keycloak server running on a self signed certificate


Figure 2 : Public consumers can then use the retrieved OAuth token (via the camel service) to access the secure private API

Note: This article outlines the steps involved in implementing the first figure only.

Step 1: Setting Up Keycloak

Keycloak Configuration:

  1. Generate the certificate and key using openssl.?

openssl req -newkey rsa:2048 -nodes -keyout keycloak-server.key.pem -x509 -days 3650 -out  keycloak-server.crt.pem        

Fill the data that is prompted. If you are running locally, use “localhost” as Common name. If you own a domain, you can pass that name as Common name.


2. Download Keycloak from : https://www.keycloak.org/downloads. As of this writing, the latest version is 26.01.

3. Start keycloak using https and use the certificate generated earlier, using the command :?

./bin/kc.sh start-dev --https-port=8081 --https-certificate-file=keycloak-server.crt.pem --https-certificate-key-file=keycloak-server.key.pem        

Note: I am using dev mode for the purposes of demonstration only. Do not use it in production setup.

4. Create a realm (e.g., user1-realm) and a client (e.g., token-generator).


5. Ensure that the response includes the refresh token for the client credential grant.


6. Test the keycloak setup, by issuing the command:

curl -k -X POST -d “grant_type=client_credentials&client_id=<client id>&client_secret=<client_secret>” https://<keycloak-host>:8081/realms/<realm-name>/protocol/openid-connect/token | jq        




Step 2: Developing the Camel-Quarkus API

Project Setup:

Camel-quarkus-rest

Camel-quarkus-jackson

Camel-quarkus-platform-http

camel-quarkus-http

Camel-quarkus-log

  • Click on the “Generate your application” button to download the project skeleton.

  • Import the code in your favourite code editor.

????????

Generate the camel-quarkus skeleton code

Implementation:

  • Write a Camel route that:
  • Exposes a rest API with HTTP post endpoint called “/token”
  • Accepts client_id and client_secret as inputs in json format in body.
  • Makes an HTTP POST request to Keycloak's token endpoint.
  • Returns the generated token as a response.

Example Route Code:

restConfiguration().bindingMode(RestBindingMode.json);
rest("/token")
.post().type(input.class)
.to("direct:getToken");

from("direct:getToken")
  .removeHeaders("*")
.process(exchange->{
            input customerInput = exchange.getIn().getBody(input.class);
            exchange.getIn().setHeader("client_id", customerInput.getClientid());
            exchange.getIn().setHeader("client_secret", customerInput.getClientsecret());
        })

        .setHeader(Exchange.HTTP_METHOD, constant("POST"))
        .setHeader(Exchange.CONTENT_TYPE, constant("application/x-www-form-urlencoded"))
        .setBody(simple("grant_type=client_credentials&client_id=${header.client_id}&client_secret=${header.client_secret}"))
        .to(configureSsl.setupSSLContext(getCamelContext(), ssoTokenEndpointURL))

        .process(exchange->{
            byte[] ssoResponseBytes = (byte[]) exchange.getIn().getBody();
                String ssoResponseBytesToStrings = new String(ssoResponseBytes, StandardCharsets.UTF_8);
                exchange.getIn().setBody(ssoResponseBytesToStrings, String.class);
        })

        .unmarshal()
        .json(JsonLibrary.Jackson, SsoResponse.class)

        .setHeader(Exchange.CONTENT_TYPE, constant("application/json"));        




Step 3: Handling Self-Signed Certificates

Challenge: Self-signed certificates are not trusted by default. Without proper handling, your application will face SSL handshake failures.

Solution:

  1. Download the generated self signed certificate pem file and key file used for keycloak server.
  2. Convert them to PKCS12 format

openssl pkcs12 -export -in keycloak-server.crt.pem -inkey keycloak-server.key.pem -out keycloak-certificate.p12 -name "keycloak-certificate"        

  1. Import it into a Java keystore:

keytool -importkeystore -srckeystore keycloak-certificate.p12? -srcstoretype pkcs12 -destkeystore keycloak-cert.jks        

  1. Configure the Camel context to load the keystore:

KeyStoreParameters keyStoreParameters = new KeyStoreParameters();
            keyStoreParameters.setResource(resource);
            keyStoreParameters.setPassword(password);

            KeyManagersParameters keyManagersParameters = new KeyManagersParameters();
            keyManagersParameters.setKeyStore(keyStoreParameters);
            keyManagersParameters.setKeyPassword(password);

            TrustManagersParameters trustManagersParameters = new TrustManagersParameters();
            trustManagersParameters.setKeyStore(keyStoreParameters);

            SSLContextParameters sslContextParameters = new SSLContextParameters();
            sslContextParameters.setKeyManagers(keyManagersParameters);
            sslContextParameters.setTrustManagers(trustManagersParameters);
            System.out.println("sslContextParameters "+ sslContextParameters);

            HttpComponent httpComponent = camelContext.getComponent("https", HttpComponent.class);
            httpComponent.setSslContextParameters(sslContextParameters);        




Step 4: Deploying to OpenShift

Deploying on OpenShift:

In this article, I will be using S2I technology to build and deploy the camel-quarkus application on Openshift Sandbox. For details of the S2I process, refer to the Red Hat documentation

For details on Openshift Sandbox, you can check out this link.

Check if the pods are up or not.

bash-3.2$ oc get pods
NAME                                 READY   STATUS    RESTARTS   AGE
camel-with-quarkus-5f679454d-msclm   1/1     Running   0          95s        

For creating a reusable code, I have created 3 properties in the camel code and populated them from environment variables as shown below.


Now let us create a secret using the .jks file created earlier, so that we can inject it in the camel-quarkus pod.

oc create secret generic keycloak-cert —from-file=keycloak-cert.jks=/Users/sumit/Downloads/keycloak-26.1.0/keycloak-cert.jks —type opaque        

Now we will mount this secret in the path mentioned in the TRUSTSTORE_FILE environment variable, so that the pod can make this file available to our camel code.




Step 5: Testing the API on OpenShift

  • Use tools like Postman or curl to invoke the API:

curl -X POST \
??-H "Content-Type: application/json" \
??-d '{"client_id":"token-generator","client_secret":"secret"}' \
??https://<OpenShift-Route-URL>/generateToken        

  • Validate the token returned by the API.




Conclusion

With Camel-Quarkus and OpenShift, integrating with Keycloak becomes a streamlined process, even in scenarios involving self-signed certificates. This approach enables enterprises to securely implement identity and access management without exposing Keycloak endpoints to the internet.

You can find the code repo for the implementation mentioned here at https://github.com/summu1985/camel-with-quarkus/tree/selfsigned-cert

Until next time, Happy Coding !!




Akshay Poddar

OpenShift Specialist @Red Hat | Trusted Customer Consultant| DevOps | Multi-Cloud Evangelist

2 个月

Very informative

要查看或添加评论,请登录

Sumit Mukherjee的更多文章

社区洞察

其他会员也浏览了