6

I'm using Keycloak to manage authentification of my app.

And using docker to build my keycloak image for both Dev and Prod environment.

Every time I build my docker image I import a new realm.json file and I have to modify manually the configuration to work with the corresponding environment ("Dev" & "Prod").

The idea is simply to use **system environment variable ** in the realm.json. I have tried to use {MY_ENV_VARIABLE} and {env.MY_ENV_VARIABLE} but nothing seem to work.

  • "modify manually the configuration", which configuration do you mean? the realm json? – dreamcrash Nov 14 '20 at 17:41
  • Yes, all we can found in the realm.json file (Realms, Clients, Mapper, Scopes ...). For now, I am willing to config clients RootUrl's, RedirectUris & WebOrigins with environment variables – Mehdi Ben Salha Nov 14 '20 at 18:00
  • I had similar issue, what I have done was to use a template realm.json, with the fields that are configurable, lets say "RootUrl's" : "", than I have a script that copies that template and replaces automatically the tags like with the correct contend. – dreamcrash Nov 14 '20 at 18:10
  • I did the same thing with Shell to replace values and it works, but we usually work with env variables and I do not want to add extra logical layer. Are you saying that is NO WAY to use env variables in realm.json? – Mehdi Ben Salha Nov 14 '20 at 18:30
  • I think you will always have to inject then, so you have the extra layer, I don't think that the variables will be automatically changed. Have you had a look at this https://levelup.gitconnected.com/injecting-environment-variables-into-static-files-ea21c2d4bdbd – dreamcrash Nov 14 '20 at 19:02

2 Answers2

4

It is possible to use environment variables in realm.json. The syntax is the usual "${VARIABLE_NAME}".

Docs: https://www.keycloak.org/server/importExport

Irmin Okic
  • 66
  • 6
  • This substitution only works when Keycloak is started as `kc start/start-dev --import-realm`. It won't work if you run a standalone `kc import` command. – ZhekaKozlov Aug 22 '23 at 10:20
1

It doesn't work what @Irmin said. How I managed this: Implement you custom 'dir' provider:

factory : CustomDirProviderFactory implements ImportProviderFactory {

provider: public class CustomDirProvider implements ImportProvider {

And there override method called

public void importRealm(KeycloakSessionFactory factory, final String realmName, final Strategy strategy) throws IOException {

There before Realmreporesentation import, you can replace values from you json file:

// Import realm first
    FileInputStream is = new FileInputStream(realmFile);
    final RealmRepresentation realmRep = JsonSerialization.readValue(replacePlaceHolders(enabledClient, clientSecret, is).getBytes(), RealmRepresentation.class);

replacing variables:

private String replacePlaceHolders(String enabledClient, String clientSecret, FileInputStream is) throws IOException {
    Charset charset = StandardCharsets.UTF_8;
    String context = new String(is.readAllBytes(), charset);
    context = context.replaceAll("\\$\\{" + ENV_VAR_ENABLE_CLIENTS + "}", enabledClient);
    context = context.replaceAll("\\$\\{" + ENV_VAR_CLIENT_SECRET + "}", clientSecret);
    return context;
}

Of course add this file in resource folder and locate your provider:

resources/META-INF/services/org.keycloak.exportimport.ImportProviderFactory

In run jvm settings (in my compose) add this:

-Dkeycloak.migration.provider=custom-dir  (provider ID)
Djordje
  • 54
  • 6