From 2b3810606edb6dfec9766fc5dceabd211762d4cc Mon Sep 17 00:00:00 2001 From: vramik Date: Thu, 2 Apr 2020 14:31:24 +0200 Subject: [PATCH] KEYCLOAK-13303 NPE importing realm if authenticatorConfig has null alias --- .../migration/MigrationModelManager.java | 4 +- .../migration/migrators/MigrateTo9_0_4.java | 64 +++++++++++++++++++ .../models/utils/RepresentationToModel.java | 5 ++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java diff --git a/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java b/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java index 5aea8255cd..880390590e 100755 --- a/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java +++ b/server-spi-private/src/main/java/org/keycloak/migration/MigrationModelManager.java @@ -49,6 +49,7 @@ import org.keycloak.migration.migrators.MigrateTo6_0_0; import org.keycloak.migration.migrators.MigrateTo8_0_0; import org.keycloak.migration.migrators.MigrateTo8_0_2; import org.keycloak.migration.migrators.MigrateTo9_0_0; +import org.keycloak.migration.migrators.MigrateTo9_0_4; import org.keycloak.migration.migrators.Migration; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -88,7 +89,8 @@ public class MigrationModelManager { new MigrateTo6_0_0(), new MigrateTo8_0_0(), new MigrateTo8_0_2(), - new MigrateTo9_0_0() + new MigrateTo9_0_0(), + new MigrateTo9_0_4() }; public static void migrate(KeycloakSession session) { diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java new file mode 100644 index 0000000000..a1e63628e8 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo9_0_4.java @@ -0,0 +1,64 @@ +/* + * Copyright 2020 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.migration.migrators; + +import java.util.UUID; +import org.jboss.logging.Logger; +import org.keycloak.migration.ModelVersion; +import org.keycloak.models.AuthenticatorConfigModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.representations.idm.RealmRepresentation; + +public class MigrateTo9_0_4 implements Migration { + + public static final ModelVersion VERSION = new ModelVersion("9.0.4"); + + private static final Logger LOG = Logger.getLogger(MigrateTo9_0_4.class); + + @Override + public ModelVersion getVersion() { + return VERSION; + } + + @Override + public void migrate(KeycloakSession session) { + session.realms().getRealms().stream().forEach(this::checkAuthConfigNullAlias); + } + + @Override + public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) { + } + + protected void checkAuthConfigNullAlias(RealmModel realm) { + realm.getAuthenticatorConfigs().stream() + .filter(this::hasNullAlias) + .forEach((config) -> this.setRandomAlias(realm, config)); + } + + private boolean hasNullAlias(AuthenticatorConfigModel config) { + return config.getAlias() == null; + } + + private void setRandomAlias(RealmModel realm, AuthenticatorConfigModel config) { + config.setAlias(UUID.randomUUID().toString()); + realm.updateAuthenticatorConfig(config); + LOG.debugf("Generated random alias for authenticator config with id %s.", config.getId()); + } + +} diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index 42ef2e1c6d..9fffa323bb 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -714,6 +714,11 @@ public class RepresentationToModel { DefaultAuthenticationFlows.migrateFlows(newRealm); } else { for (AuthenticatorConfigRepresentation configRep : rep.getAuthenticatorConfig()) { + if (configRep.getAlias() == null) { + // this can happen only during import json files from keycloak 3.4.0 and older + throw new IllegalStateException("Provided realm contains authenticator config with null alias. " + + "It should be resolved by adding alias to the authenticator config before exporting the realm."); + } AuthenticatorConfigModel model = toModel(configRep); newRealm.addAuthenticatorConfig(model); }