Added warning when storage contains multi-valued attributes and Keycloak model doesn't support them.

Closes #9714
This commit is contained in:
Alexander Schwartz 2022-01-24 09:12:54 +01:00 committed by Hynek Mlnařík
parent 781ceb24fd
commit 9e257d4a01
3 changed files with 35 additions and 3 deletions

View file

@ -16,6 +16,7 @@
*/
package org.keycloak.models.map.client;
import org.jboss.logging.Logger;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
@ -39,6 +40,7 @@ import java.util.stream.Stream;
*/
public abstract class MapClientAdapter extends AbstractClientModel<MapClientEntity> implements ClientModel {
private static final Logger LOG = Logger.getLogger(MapClientAdapter.class);
private final MapProtocolMapperUtils pmUtils;
public MapClientAdapter(KeycloakSession session, RealmModel realm, MapClientEntity entity) {
@ -286,7 +288,15 @@ public abstract class MapClientAdapter extends AbstractClientModel<MapClientEnti
final Map<String, List<String>> a = attributes == null ? Collections.emptyMap() : attributes;
return a.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
entry -> {
if (entry.getValue().isEmpty()) return null;
if (entry.getValue().isEmpty()) {
return null;
} else if (entry.getValue().size() > 1) {
// This could be caused by an inconsistency in the storage, a programming error,
// or a downgrade from a future version of Keycloak that already supports multi-valued attributes.
// The caller will not see the other values, and when this entity is later updated, the additional values will be lost.
LOG.warnf("Client '%s' realm '%s' has attribute '%s' with %d values, retrieving only the first", getClientId(), getRealm().getName(), entry.getKey(),
entry.getValue().size());
}
return entry.getValue().get(0);
})
);

View file

@ -25,6 +25,8 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jboss.logging.Logger;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
@ -37,6 +39,7 @@ import org.keycloak.models.utils.RoleUtils;
public class MapClientScopeAdapter extends AbstractClientScopeModel<MapClientScopeEntity> implements ClientScopeModel {
private static final Logger LOG = Logger.getLogger(MapClientScopeAdapter.class);
private final MapProtocolMapperUtils pmUtils;
public MapClientScopeAdapter(KeycloakSession session, RealmModel realm, MapClientScopeEntity entity) {
@ -115,7 +118,15 @@ public class MapClientScopeAdapter extends AbstractClientScopeModel<MapClientSco
final Map<String, List<String>> a = attributes == null ? Collections.emptyMap() : attributes;
return a.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
entry -> {
if (entry.getValue().isEmpty()) return null;
if (entry.getValue().isEmpty()) {
return null;
} else if (entry.getValue().size() > 1) {
// This could be caused by an inconsistency in the storage, a programming error,
// or a downgrade from a future version of Keycloak that already supports multi-valued attributes.
// The caller will not see the other values, and when this entity is later updated, the additional values will be lost.
LOG.warnf("ClientScope '%s' realm '%s' has attribute '%s' with %d values, retrieving only the first", getName(), getRealm().getName(), entry.getKey(),
entry.getValue().size());
}
return entry.getValue().get(0);
})
);

View file

@ -24,6 +24,8 @@ import static java.util.Objects.nonNull;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.common.enums.SslRequired;
import org.keycloak.component.ComponentFactory;
@ -64,6 +66,7 @@ import org.keycloak.models.utils.ComponentUtil;
public class MapRealmAdapter extends AbstractRealmModel<MapRealmEntity> implements RealmModel {
private static final Logger LOG = Logger.getLogger(MapRealmAdapter.class);
private static final String ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN = "actionTokenGeneratedByUserLifespan";
private static final String DEFAULT_SIGNATURE_ALGORITHM = "defaultSignatureAlgorithm";
private static final String BRUTE_FORCE_PROTECTED = "bruteForceProtected";
@ -207,7 +210,15 @@ public class MapRealmAdapter extends AbstractRealmModel<MapRealmEntity> implemen
public Map<String, String> getAttributes() {
return entity.getAttributes().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
entry -> {
if (entry.getValue().isEmpty()) return null;
if (entry.getValue().isEmpty()) {
return null;
} else if (entry.getValue().size() > 1) {
// This could be caused by an inconsistency in the storage, a programming error,
// or a downgrade from a future version of Keycloak that already supports multi-valued attributes.
// The caller will not see the other values, and when this entity is later updated, the additional values be will lost.
LOG.warnf("Realm '%s' has attribute '%s' with %d values, retrieving only the first", getId(), entry.getKey(),
entry.getValue().size());
}
return entry.getValue().get(0);
})
);