Managing custom realm keys in Keycloak programmatically

August 19, 2022 – Samuli Seppänen
Keys are also used Keycloak realms
Keys are used for various purposes in Keycloak realms (https://www.pexels.com/it-it/foto/close-up-chiave-tubolare-hoppe-grigio-115642)

What are Keycloak realm keys?

Keycloak's authentication protocols make use of private and public keys for signing and encrypting, as described in the official documentation. These keys are realm-specific, and by default managed internally in Keycloak. So, when you create a realm using the Keycloak Admin API, kcadm.sh or manually using the Web UI, new keypair(s) get generated automatically. These are called "Managed keys". However, you can also use custom realm keys in Keycloak, which is what this article is about. Using custom realm keys allow you, for example, to use a single keypair in multiple realms.

Internally Keycloak handles realm keys as "components" and stores them the COMPONENT_CONFIGS table in the database. That's why you won't see any "keypair" or "key" methods in the REST API, nor can you find the keys as properties of the realm. While kcadm.sh does have a "get keys" method, keys can only be added, deleted or modifies as components.

The currently used key - managed or custom - is selected based on the priority of all active keys. So, in this context active does not automatically mean that a realm keypair is being used, just that it is has not been explicitly made passive.

Creating custom realm keys

While managed keys are convenient, you can use custom realm keys in Keycloak. The official documentation on how to do this via kcadm and/or the API is missing, so this blog post aims to fill that void. Here we use kcadm.sh, but the process is very similar for raw API calls.

The first step is to create a keypair (borrowed from here):

$ openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048

The next step is to create a JSON payload, which should look like this:

{
  "name" : "rsa-shared",
  "providerId" : "rsa",
  "providerType" : "org.keycloak.keys.KeyProvider",
  "parentId" : "Test",
  "config" : {
    "privateKey": ["-----BEGIN PRIVATE KEY-----\n<private-key-body>\n-----END PRIVATE KEY-----"],
    "certificate" : [],
    "active" : [ "true" ],
    "priority" : [ "123" ],
    "enabled" : [ "true" ],
    "algorithm" : [ "RS256" ]
  }
}

A couple of notes regarding the payload:

  • The name field is the human-readable name of the key
  • The parentId should match the "id" property of the realm the keypair should belong to, which is essentially the realm name.
  • The priority field determines which key Keycloak actually uses at any given time
  • The privateKey as created above contains the whole keypair (private + public).Keycloak automatically extracts the public key from the contents of this parameter. You do not have to, nor should you, define a publicKey field: if you do, you will not be able to modify some of the paraneters under the "config" hash, such as "enabled" or "priority", while modifying "active" does work. This may have to do with the Keycloak config parser choking at "publicKey" and ignoring the values of parameters that come after it.

To apply the payload use

$ /opt/keycloak/bin/kcadm.sh create components -r test -f payload-add-key.json --no-config --server http://localhost:8080/auth --realm master --user admin --password changeme

Getting custom realm key's id

Keycloak uses unique, typically machine-generated identifiers for various resources: this also applies to custom realm keys in Keycloak. According to kcadm.sh documentation you need the key's "Provider ID" to modify or delete it. This is true, but also very confusing: when looking at the keys in JSON you see a property called "providerId", whose value can be "rsa", "rsa-generated" or such. Using that as part of the URL in Admin REST API calls will just fail. Instead, you should use the key's id as part of the URL and ignore its providerId property completely.

To get the ID for a key list all realm keys and check the value of "id" for your custom realm key:

/opt/keycloak/bin/kcadm.sh get keys -r test --no-config --server http://localhost:8080/auth --realm master --user admin --password changeme

Armed with this information you can now update and remove your custom keys.

Modifying custom realm keys

You can modify custom realm keys in Keycloak with kcadm.sh. The first and easier option is to pass the changes as a value to the -s parameter:

/opt/keycloak/bin/kcadm.sh update components/<provider-id> -r test -s 'config.active=["false"]' --no-config --server http://localhost:8080/auth --realm Test --user admin --password changeme

Alternatively you can make the modification(s) using a JSON payload. In fact, when you're working directly with the Admin REST API that's your only option. Note that in that case the payload you use has to include the full representation of the key object. For example:

{ "id":"<provider-id>",
  "name":"rsa-shared",
  "providerId":"rsa",
  "providerType":"org.keycloak.keys.KeyProvider",
  "parentId":"Test",
  "config": {
    "publicKey" : ["-----BEGIN PUBLIC KEY-----\n<public-key-body>\n-----END PUBLIC KEY-----"],
    "privateKey": ["-----BEGIN PRIVATE KEY-----\n<private-key-body>\n-----END PRIVATE KEY-----"],
    "active":["true"],
    "priority":["101"],
    "enabled":["true"],
    "algorithm":["RS256"]
  }
}

Once you've crafter the payload you can update the key object:

/opt/keycloak/bin/kcadm.sh update components/<provider-id> -r test -f update.json --no-config --server http://localhost:8080/auth --realm Test --user admin --password changeme

Removing custom realm keys

To remove a custom realm key from Keycloak delete the component like this:

/opt/keycloak/bin/kcadm.sh delete components/<provider-id> -r test --no-config --server http://localhost:8080/auth --realm master --user admin --password changeme

Ansible module for managing Keycloak realm keys

If you use Ansible for managing Keycloak you can use Puppeteers' keycloak_realm_key module in the puppeteers.keycloak collection. Here's sample usage:

- name: Manage Keycloak realm key
    keycloak_realm_key:
      name: custom
      state: present
      parent_id: master
      provider_id: "rsa"
      auth_keycloak_url: "http://localhost:8080/auth"
      auth_username: keycloak
      auth_password: keycloak
      auth_realm: master
      config:
        private_key: "{{ private_key }}"
        enabled: true
        active: true
        priority: 120
        algorithm: "RS256"

Note that the private key should be string with literal linefeed characters ('\n') instead of actual linefeeds.

Want to talk to an expert?

If you want to reach us, just send us a message or book a free call!
Categories

Tags

#aad #Access #acl #alertmanager #ansible #ansible module development #Apache #API #augeas #authentication #authorization #authz #automation #automatization #aws #azure #backup #bash #bitbucket #buildbot #cache #centos #cloud #cloud-init #cloudflare #cloudfront #cluster #connectionsJpa #control repo #custom fact #database #debian #devops #digital sovereignty #DNS #docker #domain mode #duplo #edenred #ejabberd #email #encryption #endpoints #erb #europe #eyaml #fabric #facter #facts #fargate #fedora #file #finnish #foreman #freeipa #git #github #gitlab #gnome #google #grafana #hammer #hiera #HTTparty #IAM #IDM #import #infinispan #Infrastructure as Code #ipmi #irc #jboss #jdk #jenkins #JMESPath #json #kanban #keycloak #librarian-puppet #librenms #linkedin #Linux #Location #loop #marketing #mautic #Mellon #mfa #microsoft #monitoring #mysql #nagios #network-manager #oauth #oauth2 #office365 #open source #openvpn #oxygen #packer #paranormal #pdk #people #php #pkcs7 #pomodoro #Powershell #preseed #presentation #profiles #prometheus #provisioning #puppet #puppet-bolt #puppet-litmus #puppetboard #puppetdb #Puppetfile #puppetserver #puppet types and providers #pxeboot #qemu #quality #r10k #recruitment #redirect #REST #Restrict #Reverse Proxy #robotframework #roles #rspec #ruby #SAML #sem #shell #showsql #snmp #snmpd #software developement #spam #ssh #sso #standardization #systemd #systemd-resolved #teams #terraform #ubuntu #user-data #vagrant #vanity awards #variable #vim #virtualbox #visualstudio #webdevelopment #wildfly #Windows #wireguard #wordpress #workflow #x11 #xmpp #zimbra
We are
 Puppeteers
menucross-circle