Keycloak is an open source identity provider (IdP) with single-sign on (SSO) capabilities. It supports the most widely used enterprise authentication protocols, namely OpenID Connect (OIDC), OAuth 2.0, and SAML. With Keycloak, users sign in once and share the same identity across multiple applications and platforms in a transparent manner. On the other hand, applications defer authentication to Keycloak using a standard protocol without managing the authentication flow themselves.
This article will guide you through setting up Keycloak and using it on Fedora Linux with SSL/TLS enabled using Podman.
Keycloak boasts several advantages over competing solutions such as Dex and Authentik:
- Officially governed by the Cloud Native Computing Foundation (CNCF) as an Incubating project
- Offers an user-friendly web interface with extensive features for simplified administration
- Supports multi-tenancy out of the box via the concept of realms
- Offers direct integration with a multitude of IdP backends such as Active Directory and GitHub
- Supports the enforcement of multi-factor authentication (MFA) for both individual users and realms
The steps described in this article will guide you through setting up Keycloak on Fedora Linux with SSL/TLS enabled using Podman. Once our Keycloak server is up and running, we will:
- Create the first realm example-com representing our organization
- Enforce mandatory MFA for all users in our realm
- Create the first user johndoe representing an employee in our organization
- Create the first client keycloak-spa corresponding to the Keycloak demo single-page application (SPA)
- Log in to the Keycloak realm via the demo application to validate the configuration
System requirements
To get started you will need a physical or virtual machine running Fedora Workstation with the following specifications:
- Minimum 4G of RAM (8G+ recommended)
- Minimum 2 vCPU cores (4+ vCPU recommended)
- Sufficient available storage – a few GB should suffice
Generating certificates for SSL/TLS
Applications deferring authentication to Keycloak will exchange sensitive credentials during the authentication process. As such, never run Keycloak with plain HTTP in production as it transmits credentials in plaintext over the network. Instead, generate the necessary SSL/TLS certificates, add a custom root certificate authority (CA) to the system trust, and start Keycloak with HTTPs using the certificates to ensure a secure, encrypted connection.
Installing the OpenSSL command line tool
Install the OpenSSL package used for generating SSL/TLS certificates:
sudo dnf install --refresh -y openssl
Next, create the directory $HOME/ssl/ for these certificates and enter it:
mkdir -p "$HOME/ssl/" pushd "$HOME/ssl/"
Generating the CA certificate-key pair
Now generate a CA key and certificate for internal use within the organization example.com. We will use the CA key to sign certificate signing requests (CSRs) resulting in SSL/TLS certificates used to encrypt HTTPs traffic for internal websites and services. The CA certificate are also used to verify the validity of the SSL/TLS certificates presented by internal websites and services. CAs serve as an anchor of trust so their certificates should be long lived, e.g. with a validity period of 10 years.
openssl req \ -x509 \ -new \ -nodes \ -keyout my-custom-ca.key \ -sha256 \ -days 3650 \ -out my-custom-ca.crt \ -subj '/CN=My custom CA/DC=localhost'
This creates a CA key my-custom-ca.key and the corresponding CA certificate my-custom-ca.crt.
Inspect the CA certificate with the following command:
$ openssl x509 -text -noout -in my-custom-ca.crt Certificate: Data: Version: 3 (0x2) Serial Number: 76:56:b9:13:b4:85:f4:36:0d:d0:2a:18:d3:de:f3:2f:25:76:f5:b0 Signature Algorithm: sha256WithRSAEncryption Issuer: CN = My custom CA, DC = localhost Validity Not Before: Feb 25 02:11:46 2024 GMT Not After : Feb 22 02:11:46 2034 GMT Subject: CN = My custom CA, DC = localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:ba:0b:7e:fb:88:e6:6f:f3:c2:3b:cc:3c:5d:18: cf:bc:c1:ff:e3:98:3a:52:2c:82:dc:d7:14:75:8a: 58:fc:26:d7:97:9e:ee:73:c0:56:79:77:5b:97:96: 5c:f9:6a:d1:0c:bc:96:4d:e3:48:4c:e8:91:77:1e: 58:22:23:b2:7d:50:2e:2e:5d:c5:7a:85:0e:e4:b4: 73:64:5d:85:2a:81:fe:e1:04:3d:6a:5d:0f:99:4b: e8:82:7b:c4:06:36:3f:67:b7:19:08:1b:56:28:d0: b1:0d:f5:52:55:06:88:97:87:a5:be:ba:11:a2:eb: a4:da:6d:c7:3e:1f:5d:46:1f:da:a3:26:19:0a:ea: 42:67:8e:ab:7a:77:d5:db:c0:24:d1:c7:10:86:b9: ef:0a:ad:3f:22:8d:17:f5:26:1e:38:23:ba:5f:7c: 6b:f6:e8:41:1f:ed:6a:a6:77:3e:f6:55:ef:06:08: f3:a8:f3:a3:4f:9b:d4:2c:fe:b0:62:c1:1d:8e:c0: 6f:97:d9:e4:ec:a7:e6:6d:62:31:8a:f7:3e:9a:4f: 3b:92:c4:04:b6:2c:9b:b2:4d:b8:bc:8a:72:c1:67: 9f:8a:60:cf:a5:7f:84:75:a3:c9:48:60:dd:6a:b9: e4:ec:91:3f:6d:cc:ec:a3:8a:44:ea:1c:62:01:92: 09:2d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 69:0F:42:C2:FC:D7:BB:79:D3:B6:5A:31:D9:A9:B0:3C:DA:C3:78:1D X509v3 Authority Key Identifier: 69:0F:42:C2:FC:D7:BB:79:D3:B6:5A:31:D9:A9:B0:3C:DA:C3:78:1D X509v3 Basic Constraints: critical CA:TRUE Signature Algorithm: sha256WithRSAEncryption Signature Value: 8d:15:51:ae:d6:67:6f:18:b2:88:30:c2:91:a8:25:16:3c:97: 19:f1:c6:d4:4a:95:0f:ec:21:97:f8:aa:ec:78:5d:22:66:4e: 84:a6:e3:61:be:bd:a2:b3:6a:48:f7:0e:95:f5:95:02:14:63: 28:cc:c8:6d:07:86:3d:9d:f1:f5:8b:5c:a9:4f:d2:98:0d:1a: 26:cd:3e:ef:8c:e7:0c:e6:10:31:94:ad:c3:6c:83:82:d9:7e: fe:c7:85:c4:40:d7:36:7a:fb:6e:79:f9:c4:64:77:59:d6:6c: f5:24:36:fd:f4:2a:97:ec:58:0c:c2:6c:16:87:d6:4f:7e:88: 9d:16:c8:fa:5f:aa:44:52:3b:36:99:34:64:e2:b9:a8:1b:e8: f2:94:95:ab:ae:12:42:ab:11:4d:9b:e5:c3:5c:85:07:2c:1e: 7e:2e:ef:88:ad:44:eb:90:a0:b1:28:c5:a6:4f:0e:1c:47:6a: 34:da:a0:5a:1a:9a:a9:b0:fe:77:f1:e3:99:90:59:47:4b:52: d2:e5:5d:9b:46:6e:04:fe:4f:87:75:13:ab:0a:a8:74:c4:c8: 80:54:cd:6b:db:4a:ee:86:bc:5c:32:9e:5f:29:8b:50:3f:0c: ab:32:49:ff:ce:36:9c:cd:e4:4c:78:da:ce:a1:4d:a5:a3:84: 51:41:52:49
Look out for the following fields when inspecting a CA certificate:
- Issuer: the subject of the authority who issued the certificate. In the case of a root CA, this is the CA itself
- Subject: who this certificate represents
- X509v3 extensions: metadata indicating the nature of the certificate (CA:TRUE) and associated identity information
Be accustomed to inspecting certificates with the command shown above as it is useful for troubleshooting when certificates do not function as expected, e.g. when your browser warns that a certificate is invalid even though you already trust the root CA that signed it.
Before we proceed, add the CA certificate to the system trust. This ensures that any certificates issued by this CA are recognized as valid and trustworthy.
sudo trust anchor --store my-custom-ca.crt sudo update-ca-trust
Generating a CSR for our Keycloak instance
Now generate a CSR for the Keycloak instance which will be exposed on https://localhost:8443/.
openssl req \ -new \ -newkey rsa:2048 \ -nodes \ -keyout localhost.key \ -sha256 \ -out localhost.csr \ -subj '/CN=My custom certificate/DC=localhost' \ -addext 'subjectAltName=DNS:localhost' \ -addext 'basicConstraints=critical,CA:FALSE' \ -addext 'keyUsage=digitalSignature' \ -addext 'extendedKeyUsage=serverAuth'
This generates a certificate key localhost.key and the corresponding CSR localhost.csr. The CSR is then handed over to the CA for signing which generates an SSL/TLS certificate for use in the Keycloak instance.
Inspect the CSR with a similar command:
$ openssl req -text -noout -in localhost.csr Certificate Request: Data: Version: 1 (0x0) Subject: CN = My custom certificate, DC = localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:dc:15:3a:92:03:aa:26:c9:1f:b2:a7:fb:3a:70: 6a:64:cc:f7:2e:68:88:3b:44:88:d7:f7:59:86:4c: 94:c5:88:65:4d:4c:2c:f5:e3:6d:02:8b:e9:16:b8: fc:b1:7b:e1:ca:dd:17:12:75:7e:3b:97:78:01:bd: e9:e4:a2:9c:c3:62:74:e6:32:00:6a:3f:9a:4d:e6: d5:46:b0:c3:79:40:d3:8c:18:6c:41:0b:b8:6f:84: 15:bf:37:29:7f:46:d9:5d:0f:2a:d9:06:21:1d:17: 64:fb:ec:9f:c1:62:0e:e5:df:48:cf:c9:0e:ea:3e: 47:4e:dd:00:95:ac:38:fb:03:bf:8b:13:34:57:49: 01:26:05:06:d5:dc:39:34:12:2e:2b:f5:a7:3a:d1: 03:94:ce:5c:2b:28:67:2e:2d:09:85:b6:53:0a:f3: 9b:00:62:29:d5:84:df:e0:b4:a9:0a:81:a1:f3:0a: e3:fc:71:5d:fe:d7:c7:8b:f7:e5:bb:e6:51:0a:5f: d5:06:5d:7f:cf:48:28:96:b6:d0:a4:60:6f:f5:08: 0f:ce:6f:a3:8f:c4:b7:db:c0:79:33:1b:02:e8:ad: 95:fc:df:b9:6a:ef:31:f2:1c:11:3c:56:4a:4c:07: 1e:53:24:d6:36:2a:e3:3e:4f:3b:b8:64:68:56:70: 81:29 Exponent: 65537 (0x10001) Attributes: Requested Extensions: X509v3 Subject Alternative Name: DNS:localhost X509v3 Basic Constraints: critical CA:FALSE X509v3 Key Usage: Digital Signature X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: ce:e7:20:cd:f4:86:86:0e:66:95:4d:59:1c:8b:94:9e:8b:dd: 97:ac:96:8e:bd:ea:96:c7:e4:2f:a8:af:fa:71:e9:aa:ce:85: f1:bd:62:a5:8f:5b:07:f1:25:f0:c9:0f:b1:9e:ef:85:af:fc: cd:1b:09:e0:c5:41:0b:26:67:35:32:9e:8a:c8:b5:97:14:d6: 74:e6:dc:9b:de:bf:06:b1:10:28:29:33:c0:48:7c:93:28:29: 1b:92:43:ae:0c:2c:37:d0:ba:ac:bc:92:c9:61:e8:d1:ba:67: ab:36:ee:cb:ad:bc:df:7e:12:92:e4:95:34:a9:4c:c0:8d:3b: 90:01:37:b0:bf:9b:41:94:52:a6:a9:a2:9b:87:f8:11:bf:80: 4e:68:6a:37:11:82:12:50:56:f1:e8:fb:2c:1e:5d:e2:7f:27: f9:18:f0:32:e0:d8:75:e6:e2:be:4d:62:10:5d:ac:cb:fd:22: 65:3d:84:74:cf:f6:34:78:ea:85:29:49:52:b2:5d:96:ff:40: cb:e7:cb:4d:0a:c3:da:8b:af:92:5d:51:74:98:49:7a:66:da: 33:ef:5e:95:ca:f0:7a:2b:19:bd:82:56:2f:c1:08:8e:33:37: 7a:76:88:cb:81:9c:56:77:dc:ac:6c:b4:a0:c2:8d:ff:8e:6e: a6:7e:dd:4f
Here, pay attention to the requested extensions, in particular the X509v3 Subject Alternative Name which defines the DNS domain name(s) for which the signed certificate will be valid.
Signing our CSR with the CA key
Pass this CSR over to the CA for signing. SSL/TLS certificates should be renewed on a regular basis so set the validity period to a shorter interval, e.g. 1 year.
openssl x509 \ -req \ -days 365 \ -in localhost.csr \ -CA my-custom-ca.crt \ -CAkey my-custom-ca.key \ -out localhost.crt \ -set_serial 01 \ -sha256 \ -copy_extensions copy
The -copy-extensions copy option preserves the CSR requested extensions in the signed certificate localhost.crt. Confirm this is the case:
$ openssl x509 -text -noout -in localhost.crt Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: CN = My custom CA, DC = localhost Validity Not Before: Feb 25 03:31:09 2024 GMT Not After : Feb 24 03:31:09 2025 GMT Subject: CN = My custom certificate, DC = localhost Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:dc:15:3a:92:03:aa:26:c9:1f:b2:a7:fb:3a:70: 6a:64:cc:f7:2e:68:88:3b:44:88:d7:f7:59:86:4c: 94:c5:88:65:4d:4c:2c:f5:e3:6d:02:8b:e9:16:b8: fc:b1:7b:e1:ca:dd:17:12:75:7e:3b:97:78:01:bd: e9:e4:a2:9c:c3:62:74:e6:32:00:6a:3f:9a:4d:e6: d5:46:b0:c3:79:40:d3:8c:18:6c:41:0b:b8:6f:84: 15:bf:37:29:7f:46:d9:5d:0f:2a:d9:06:21:1d:17: 64:fb:ec:9f:c1:62:0e:e5:df:48:cf:c9:0e:ea:3e: 47:4e:dd:00:95:ac:38:fb:03:bf:8b:13:34:57:49: 01:26:05:06:d5:dc:39:34:12:2e:2b:f5:a7:3a:d1: 03:94:ce:5c:2b:28:67:2e:2d:09:85:b6:53:0a:f3: 9b:00:62:29:d5:84:df:e0:b4:a9:0a:81:a1:f3:0a: e3:fc:71:5d:fe:d7:c7:8b:f7:e5:bb:e6:51:0a:5f: d5:06:5d:7f:cf:48:28:96:b6:d0:a4:60:6f:f5:08: 0f:ce:6f:a3:8f:c4:b7:db:c0:79:33:1b:02:e8:ad: 95:fc:df:b9:6a:ef:31:f2:1c:11:3c:56:4a:4c:07: 1e:53:24:d6:36:2a:e3:3e:4f:3b:b8:64:68:56:70: 81:29 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Alternative Name: DNS:localhost X509v3 Basic Constraints: critical CA:FALSE X509v3 Key Usage: Digital Signature X509v3 Extended Key Usage: TLS Web Server Authentication X509v3 Subject Key Identifier: F0:5D:A9:79:38:3B:83:EA:D0:C6:CF:91:0E:6F:67:72:DE:45:3A:04 X509v3 Authority Key Identifier: A1:EA:2F:AB:B1:95:AE:9C:56:48:1C:B5:6B:42:8A:61:2C:0B:DB:18 Signature Algorithm: sha256WithRSAEncryption Signature Value: c1:b0:c6:89:64:76:b1:ab:2e:bc:c7:fd:bd:d2:31:9f:20:8d: c0:8e:1d:d7:70:f1:a6:72:7d:49:23:33:f3:f5:e6:2d:eb:20: f4:c5:ea:a1:f2:1b:24:a2:ad:b9:b6:c9:03:66:03:dd:1b:41: f2:21:c7:ed:31:21:63:21:56:2d:a1:5d:31:cd:91:85:8f:ef: a3:84:b0:34:59:ba:30:2b:da:ec:c5:55:8e:5d:c9:a6:da:e4: 24:9e:76:b5:ca:83:46:fb:91:33:43:26:53:93:5c:2f:52:c0: 23:ce:63:3f:ab:1e:46:89:cf:6c:3c:a4:26:80:76:b1:d6:85: d6:84:9a:db:6b:93:fe:3b:51:1a:2e:b8:8b:c7:76:c0:e1:bd: 2d:cb:1d:de:fe:13:a4:57:18:76:b9:76:dd:5a:6f:79:49:cf: ed:44:b8:4b:97:ac:81:87:55:1c:0b:30:3b:84:ae:27:8a:97: bc:72:c8:96:65:f1:bd:63:85:0e:4c:d7:9d:4e:e4:9d:4d:b0: a1:8c:13:53:6a:a3:ba:cf:eb:ae:08:28:b2:5a:ec:0a:f4:e0: 23:14:2f:c0:35:8b:da:a4:31:42:61:c9:2d:f9:57:3e:16:36: 09:6c:59:37:3b:2e:06:2c:ee:9b:2c:66:fd:38:92:47:8c:2e: b8:5e:7c:19
Now leave the $HOME/ssl/ directory:
popd
Deploying the Keycloak instance with Podman
Set an initial administrator username and password. You should replace the examples below with more secure defaults:
export KEYCLOAK_ADMIN="admin" # replace me! export KEYCLOAK_ADMIN_PASSWORD="P@ssw0rd" # replace me!
Now fetch the latest Keycloak image from Quay.io and run it:
podman run \ --rm \ -d \ -p 8443:8443 \ -e KEYCLOAK_ADMIN="${KEYCLOAK_ADMIN}" \ -e KEYCLOAK_ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD}" \ -v "$HOME/ssl/:/ssl/:U,Z,ro" \ --name keycloak \ quay.io/keycloak/keycloak:latest \ start \ --hostname=localhost \ --https-certificate-file=/ssl/localhost.crt \ --https-certificate-key-file=/ssl/localhost.key
The Keycloak instance binds to port 8443 and uses the certificate and key generated in a previous step for SSL/TLS encryption, bind-mounted into the container read-only with the correct ownership and SELinux context (U,Z,ro).
Visit https://localhost:8443/ in a web browser and click on “Administration Console” which presents a login portal. Enter the administrator credentials in the login portal and click “Sign In” which brings us to the administrator console.
Notice that we are in the master realm. The master realm exists by default in Keycloak and should only be used to manage other realms. A realm in Keycloak is a tenant which represents different things depending on the context:
- In a service provider context where a Keycloak instance is accessible to enterprise customers as a managed service, a tenant is an independent organization with its own identity and access management (IAM)
- In an organizational context where a Keycloak instance is deployed for internal usage within the organization, a tenant is a department or organizational unit (OU) sharing a common base IdP such as the top-level corporate Active Directory domain
Creating a realm for the organization
Now create a realm for the example.com organization.
Click on the dropdown to the top left and select “Create realm”.
Fill in example-com as the realm name and click “Create”.
Observe that we are now in the administration console for the example-com realm.
Enforcing mandatory MFA for all users in the realm
MFA is the practice of adding a second layer of authentication and is widely employed by organizations. Instead of solely verifying what a person “knows” (the password), MFA also verifies what a person “has” to gain confidence in securely associating a natural entity with a digital identity. This is something such as a time-based one-time password (TOTP) generated by a mobile hardware or software device. This provides an additional layer of protection for accounts which may have their password compromised, though an account with a compromised password should change their password immediately in any case.
Keycloak supports enforcing mandatory MFA at both the user and realm level. Suppose the organization’s IT security policy mandates that all corporate accounts be secured via MFA. This policy can then be satisfied by enabling OTP as a required action at the realm level. We’ll also enforce that passwords be changed at initial login so only the account owner knows their own password.
Navigate to the menu to the left and click “Authentication”, then select “Required actions” and ensure both “Configure OTP” and “Update Password” are enabled as default actions.
Creating an account for John Doe
John Doe has just joined the organization as a developer. As part of the onboarding process, let’s create an account for John Doe.
Select “Users > Add User”.
Fill in the username johndoe and any other fields as desired, then click “Create”.
Navigate to the “Credentials” tab and click “Set password”.
Fill in a suitable initial password for John Doe and click “Save”.
Click “Save password” to confirm the action.
Congratulations, you have created an account for John Doe and set an initial password!
Creating a client for the Keycloak SPA demo application
Platforms and applications integrating with Keycloak do so via clients. A client represents an application from Keycloak’s perspective.
Let’s test the Keycloak instance using an application. Fortunately, the Keycloak project conveniently provides a demo application so we don’t have to write our own. But first, we need to create a client for the app.
Select “Clients > Create client”.
Preserve the client type as “OpenID Connect” and fill in the client ID as keycloak-spa, then click “Next”.
Ensure “Standard flow” is checked and click “Next”.
Now fill in the following details and click “Save”:
- Valid redirect URLs: https://www.keycloak.org/app/*
- Web origins: https://www.keycloak.org (without a trailing slash)
Congratulations, you have set up your first client on Keycloak!
Installing the Authenticator MFA app on Flathub
Before proceeding to log in as John Doe, remember that mandatory MFA is enabled so we’ll need an app to set it up during our first login.
Keycloak explicitly supports the following TOTP applications which can be installed on a mobile device:
But for a change, let’s see a TOTP app available on Fedora Linux. Authenticator is an open source GNOME application for generating TOTP codes available under the copyleft GPLv3+ license. It is part of the GNOME Circle, readily available on Flathub and integrates well with Fedora Workstation. Just make sure that Flathub is enabled as a repository source in GNOME Software, then find and install the app.
Logging in as John Doe with SSO
Now visit the demo application at https://www.keycloak.org/app/, fill in the configuration and click “Save”:
- Keycloak URL: https://localhost:8443 (without the trailing slash)
- Realm: example-com
- Client: keycloak-spa
Click “Sign in”.
Fill in John Doe’s username and initial password, then click “Sign in”.
You will be prompted to configure MFA authentication based on TOTP. Open your Authenticator app, scan the QR code to add the application, then fill in the generated TOTP password and name the MFA device “Authenticator”. Click “Submit”.
Reset the initial password and ensure it is strong and secure, then click “Submit”.
Congratulations, you are now logged in as John Doe in the Keycloak SPA demo app via your Keycloak instance!
Cleaning up
Stop the Keycloak instance, then delete the SSL/TLS certificates created earlier. The Keycloak container was configured to be deleted automatically once stopped via the –rm flag.
podman stop keycloak sudo rm -rf "$HOME/ssl/"
Concluding remarks and going further
Keycloak is an open source, enterprise-ready IdP supporting the most widely used authentication protocols. This enables it to readily integrate with a wide range of applications and platforms, including enterprise-grade orchestration platforms such as Kubernetes. Furthermore, it can be readily deployed to a wide range of environments, including on traditional servers / VMs, as a standalone container with Podman (and Docker), and on container orchestration platforms such as Kubernetes and OpenShift.
We have barely scratched the surface of Keycloak configuration in this lab. Keycloak can act directly as an IdP backend, as in this lab, or act as a connector to existing enterprise IdP backends, such as LDAP and Active Directory. Furthermore, by associating users with groups and roles, platforms integrating with Keycloak for authentication can apply role-based access control (RBAC) to enterprise identities for a scalable method of managing access to resources in a centralized manner.
RG
Nice article Donald! I must say I struggled a bit with openssl and those crazy extensions but your commands were much clearer from what I was doing. I think it is worth adding that keycloak is the upstream version of the red hat sso. There were also some breaking changes starting version 18/20 onwards. As for the trust command… I was expecting chrome and mozilla to have their own ca-store… So how did this work… I need to verify and probably reproduce.
Donald Sebastian Leung
Thank you for your suggestions and glad you enjoyed the article 🙂 I find the OpenSSL commands arcane as well, and it doesn’t help that most sources out there cram all the command-line arguments in a single line which makes the entire command extremely difficult to parse (-:
Regarding the Firefox / Chrome CA trust, I believe that they are configured to use the OS-level system trust for native package formats like rpm and deb, but for portable packages like Flatpak (and Snap), they can’t access the OS-level system trust by default so use their own CA trust database
Donald Sebastian Leung
Speaking of the breaking change in versions 18/20 onwards, we’ve deployed the Red Hat build of Keycloak (RHBK) on OpenShift using the certified operator in a PoC setting at our workplace, but soon realized that there’s no supported option to inject custom CA certificates for secure LDAPS connections to Active Directory with the current Quarkus distribution of Keycloak, at least not without building a custom container image, so we finally settled for Dex as our OIDC authentication solution for our production Kubernetes cluster which supports our particular use case (OIDC connector to Active Directory backend) 😉
Marcelo Sales
Nice article, congratulations. I wanted to further enrich this article with some information that may be useful.
The first point would be the system requirements. To accomplish what you demonstrate in this article, this infrastructure would not be necessary. It could run everything with 1 vCPU and 512MB of RAM. Perhaps what you mentioned as recommended is for some productive environment and this has to be studied and analyzed according to the requirements.
The second case is about connectivity with LDAPS. Surely Keycloak supports connection to LDAPS. There are several use cases for Keycloak acting as an identity federator through OIDC. Even using the operator, it is possible to map a volume with a truststore configured via keycloak start parameters; it is not necessarily necessary to customize an image to achieve this objective. And speaking of customizing the image, this is one of the best features I see in Keycloak, its immense customization and extension capacity. From a security point of view, it makes perfect sense to customize images with additional features since in this sense, each corporation has its own parameters and requirements.
Donald Sebastian Leung
Thank you for your input and suggestions, glad you enjoyed the article 🙂
The minimum system requirements suggested in this article assume that the Keycloak container is running directly on a Fedora Workstation installation complete with a GNOME desktop environment. In our experience, modern editions of Fedora Workstation with the default GNOME desktop environment require at least 4G of RAM to run smoothly without locking up. Of course, if the container is run within a headless Fedora Server installation then 1G of RAM should be enough. For production deployments, we recommend deploying on an existing Kubernetes or OpenShift cluster using the Keycloak operator which automates much of the configuration and setup.
Regarding LDAPS support with a custom CA, we might have missed something since we’re not all that familiar with Quarkus or the Java ecosystem in general, but it would be helpful if the option for configuring a custom CA for LDAPS connections was exposed directly via the Keycloak CR under a single key, perhaps a reference to a secret containing the CA certificate like with Dex, or the process of doing so more clearly documented on the official website since we assume it’s a common requirement in enterprises. Though I agree that most medium to large enterprises with complex requirements will likely need to customize the Keycloak image for their specific use cases either way.
Tom
Would be nice to break down those openssl commands, and maybe use a config file. I always struggle with the openssl swiss army knife, but I was/am trying to create the certificate signed by an existing authority. Not sure I did it all right, but “start-dev” instead of a “start” enabled me to get things up and running (probably because the parent certificate wasnt in the trust store for keycloak’s container).
I appreciate the great article – it allowed me to get a OIDC server up and running so I can continue development on some software!
Donald Sebastian Leung
Thanks for your suggestions and glad you managed to get Keycloak up and running with the instructions presented in this article 🙂
Indeed, the OpenSSL swiss army knife is its own beast and it was only until very recently that I started to really understand what some of those command-line options mean and how they work (-: