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:
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:
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:??
This approach ensures:??
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.
Note: This article outlines the steps involved in implementing the first figure only.
Step 1: Setting Up Keycloak
Keycloak Configuration:
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
????????
Implementation:
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:
openssl pkcs12 -export -in keycloak-server.crt.pem -inkey keycloak-server.key.pem -out keycloak-certificate.p12 -name "keycloak-certificate"
keytool -importkeystore -srckeystore keycloak-certificate.p12? -srcstoretype pkcs12 -destkeystore keycloak-cert.jks
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
curl -X POST \
??-H "Content-Type: application/json" \
??-d '{"client_id":"token-generator","client_secret":"secret"}' \
??https://<OpenShift-Route-URL>/generateToken
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 !!
OpenShift Specialist @Red Hat | Trusted Customer Consultant| DevOps | Multi-Cloud Evangelist
2 个月Very informative