Merge pull request #1010 from mposolda/krb-deleg-cred
Configurable KDC encryption types, Mongo fix
This commit is contained in:
commit
d1fbe1fd30
7 changed files with 49 additions and 13 deletions
|
@ -28,6 +28,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoUserEntity",
|
"org.keycloak.models.mongo.keycloak.entities.MongoUserEntity",
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity",
|
"org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity",
|
||||||
"org.keycloak.models.entities.IdentityProviderEntity",
|
"org.keycloak.models.entities.IdentityProviderEntity",
|
||||||
|
"org.keycloak.models.entities.ClientIdentityProviderMappingEntity",
|
||||||
"org.keycloak.models.entities.RequiredCredentialEntity",
|
"org.keycloak.models.entities.RequiredCredentialEntity",
|
||||||
"org.keycloak.models.entities.CredentialEntity",
|
"org.keycloak.models.entities.CredentialEntity",
|
||||||
"org.keycloak.models.entities.FederatedIdentityEntity",
|
"org.keycloak.models.entities.FederatedIdentityEntity",
|
||||||
|
@ -36,7 +37,8 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
|
||||||
"org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity",
|
"org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity",
|
||||||
"org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
|
"org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
|
||||||
"org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
|
"org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
|
||||||
"org.keycloak.models.entities.UserFederationProviderEntity"
|
"org.keycloak.models.entities.UserFederationProviderEntity",
|
||||||
|
"org.keycloak.models.entities.ProtocolMapperEntity"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
|
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
|
||||||
|
|
|
@ -23,7 +23,7 @@ package org.keycloak.models.entities;
|
||||||
public class ClientIdentityProviderMappingEntity {
|
public class ClientIdentityProviderMappingEntity {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private Boolean retrieveToken;
|
private boolean retrieveToken;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
|
@ -33,11 +33,11 @@ public class ClientIdentityProviderMappingEntity {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isRetrieveToken() {
|
public boolean isRetrieveToken() {
|
||||||
return this.retrieveToken;
|
return this.retrieveToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRetrieveToken(Boolean retrieveToken) {
|
public void setRetrieveToken(boolean retrieveToken) {
|
||||||
this.retrieveToken = retrieveToken;
|
this.retrieveToken = retrieveToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,14 +29,12 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
|
||||||
protected final T clientEntity;
|
protected final T clientEntity;
|
||||||
private final RealmModel realm;
|
private final RealmModel realm;
|
||||||
protected KeycloakSession session;
|
protected KeycloakSession session;
|
||||||
private final RealmProvider model;
|
|
||||||
|
|
||||||
public ClientAdapter(KeycloakSession session, RealmModel realm, T clientEntity, MongoStoreInvocationContext invContext) {
|
public ClientAdapter(KeycloakSession session, RealmModel realm, T clientEntity, MongoStoreInvocationContext invContext) {
|
||||||
super(invContext);
|
super(invContext);
|
||||||
this.clientEntity = clientEntity;
|
this.clientEntity = clientEntity;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.model = session.realms();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -326,13 +324,14 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
|
public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
|
||||||
List<ClientIdentityProviderMappingEntity> stored = getMongoEntityAsClient().getIdentityProviders();
|
List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingModel model : identityProviders) {
|
for (ClientIdentityProviderMappingModel model : identityProviders) {
|
||||||
ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
|
ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
|
||||||
|
|
||||||
entity.setId(model.getIdentityProvider());
|
entity.setId(model.getIdentityProvider());
|
||||||
entity.setRetrieveToken(model.isRetrieveToken());
|
entity.setRetrieveToken(model.isRetrieveToken());
|
||||||
|
stored.add(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
getMongoEntityAsClient().setIdentityProviders(stored);
|
getMongoEntityAsClient().setIdentityProviders(stored);
|
||||||
|
|
|
@ -910,7 +910,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
mapping.setConsentRequired(entity.isConsentRequired());
|
mapping.setConsentRequired(entity.isConsentRequired());
|
||||||
mapping.setConsentText(entity.getConsentText());
|
mapping.setConsentText(entity.getConsentText());
|
||||||
Map<String, String> config = new HashMap<String, String>();
|
Map<String, String> config = new HashMap<String, String>();
|
||||||
if (entity.getConfig() != null) config.putAll(config);
|
if (entity.getConfig() != null) config.putAll(entity.getConfig());
|
||||||
mapping.setConfig(config);
|
mapping.setConfig(config);
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.keycloak.protocol;
|
package org.keycloak.protocol;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
@ -14,6 +15,9 @@ import java.util.List;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractLoginProtocolFactory implements LoginProtocolFactory {
|
public abstract class AbstractLoginProtocolFactory implements LoginProtocolFactory {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(AbstractLoginProtocolFactory.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Config.Scope config) {
|
public void init(Config.Scope config) {
|
||||||
}
|
}
|
||||||
|
@ -27,6 +31,7 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
|
||||||
for (RealmModel realm : realms) addDefaults(realm);
|
for (RealmModel realm : realms) addDefaults(realm);
|
||||||
session.getTransaction().commit();
|
session.getTransaction().commit();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
logger.error("Can't add default mappers to realm", e);
|
||||||
session.getTransaction().rollback();
|
session.getTransaction().rollback();
|
||||||
} finally {
|
} finally {
|
||||||
session.close();
|
session.close();
|
||||||
|
|
|
@ -16,6 +16,7 @@ public class EmbeddedServersFactory {
|
||||||
|
|
||||||
private static final String DEFAULT_KERBEROS_REALM = "KEYCLOAK.ORG";
|
private static final String DEFAULT_KERBEROS_REALM = "KEYCLOAK.ORG";
|
||||||
private static final int DEFAULT_KDC_PORT = 6088;
|
private static final int DEFAULT_KDC_PORT = 6088;
|
||||||
|
private static final String DEFAULT_KDC_ENCRYPTION_TYPES = "aes128-cts-hmac-sha1-96, des-cbc-md5, des3-cbc-sha1-kd";
|
||||||
|
|
||||||
private String baseDN;
|
private String baseDN;
|
||||||
private String bindHost;
|
private String bindHost;
|
||||||
|
@ -23,6 +24,7 @@ public class EmbeddedServersFactory {
|
||||||
private String ldifFile;
|
private String ldifFile;
|
||||||
private String kerberosRealm;
|
private String kerberosRealm;
|
||||||
private int kdcPort;
|
private int kdcPort;
|
||||||
|
private String kdcEncryptionTypes;
|
||||||
|
|
||||||
|
|
||||||
public static EmbeddedServersFactory readConfiguration() {
|
public static EmbeddedServersFactory readConfiguration() {
|
||||||
|
@ -40,6 +42,7 @@ public class EmbeddedServersFactory {
|
||||||
|
|
||||||
this.kerberosRealm = System.getProperty("kerberos.realm");
|
this.kerberosRealm = System.getProperty("kerberos.realm");
|
||||||
String kdcPort = System.getProperty("kerberos.port");
|
String kdcPort = System.getProperty("kerberos.port");
|
||||||
|
this.kdcEncryptionTypes = System.getProperty("kerberos.encTypes");
|
||||||
|
|
||||||
if (baseDN == null || baseDN.isEmpty()) {
|
if (baseDN == null || baseDN.isEmpty()) {
|
||||||
baseDN = DEFAULT_BASE_DN;
|
baseDN = DEFAULT_BASE_DN;
|
||||||
|
@ -56,6 +59,9 @@ public class EmbeddedServersFactory {
|
||||||
kerberosRealm = DEFAULT_KERBEROS_REALM;
|
kerberosRealm = DEFAULT_KERBEROS_REALM;
|
||||||
}
|
}
|
||||||
this.kdcPort = (kdcPort == null || kdcPort.isEmpty()) ? DEFAULT_KDC_PORT : Integer.parseInt(kdcPort);
|
this.kdcPort = (kdcPort == null || kdcPort.isEmpty()) ? DEFAULT_KDC_PORT : Integer.parseInt(kdcPort);
|
||||||
|
if (kdcEncryptionTypes == null || kdcEncryptionTypes.isEmpty()) {
|
||||||
|
kdcEncryptionTypes = DEFAULT_KDC_ENCRYPTION_TYPES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,6 +83,6 @@ public class EmbeddedServersFactory {
|
||||||
ldifFile = DEFAULT_KERBEROS_LDIF_FILE;
|
ldifFile = DEFAULT_KERBEROS_LDIF_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new KerberosEmbeddedServer(baseDN, bindHost, bindPort, ldifFile, kerberosRealm, kdcPort);
|
return new KerberosEmbeddedServer(baseDN, bindHost, bindPort, ldifFile, kerberosRealm, kdcPort, kdcEncryptionTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package org.keycloak.testutils.ldap;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.security.auth.kerberos.KerberosPrincipal;
|
import javax.security.auth.kerberos.KerberosPrincipal;
|
||||||
|
|
||||||
|
@ -20,6 +22,8 @@ import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler;
|
||||||
import org.apache.directory.server.ldap.handlers.sasl.plain.PlainMechanismHandler;
|
import org.apache.directory.server.ldap.handlers.sasl.plain.PlainMechanismHandler;
|
||||||
import org.apache.directory.server.protocol.shared.transport.UdpTransport;
|
import org.apache.directory.server.protocol.shared.transport.UdpTransport;
|
||||||
import org.apache.directory.shared.kerberos.KerberosTime;
|
import org.apache.directory.shared.kerberos.KerberosTime;
|
||||||
|
import org.apache.directory.shared.kerberos.KerberosUtils;
|
||||||
|
import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +35,7 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
||||||
|
|
||||||
private final String kerberosRealm;
|
private final String kerberosRealm;
|
||||||
private final int kdcPort;
|
private final int kdcPort;
|
||||||
|
private final String kdcEncryptionTypes;
|
||||||
|
|
||||||
private KdcServer kdcServer;
|
private KdcServer kdcServer;
|
||||||
|
|
||||||
|
@ -43,8 +48,9 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected KerberosEmbeddedServer(String baseDN, String bindHost, int bindPort, String ldifFile, String kerberosRealm, int kdcPort) {
|
protected KerberosEmbeddedServer(String baseDN, String bindHost, int bindPort, String ldifFile, String kerberosRealm, int kdcPort, String kdcEncryptionTypes) {
|
||||||
super(baseDN, bindHost, bindPort, ldifFile);
|
super(baseDN, bindHost, bindPort, ldifFile);
|
||||||
|
this.kdcEncryptionTypes = kdcEncryptionTypes;
|
||||||
this.kerberosRealm = kerberosRealm;
|
this.kerberosRealm = kerberosRealm;
|
||||||
this.kdcPort = kdcPort;
|
this.kdcPort = kdcPort;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +60,7 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
log.info("Creating KDC server. kerberosRealm: " + kerberosRealm + ", kdcPort: " + kdcPort);
|
log.info("Creating KDC server. kerberosRealm: " + kerberosRealm + ", kdcPort: " + kdcPort + ", kdcEncryptionTypes: " + kdcEncryptionTypes);
|
||||||
createAndStartKdcServer();
|
createAndStartKdcServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +99,8 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
||||||
kdcConfig.setMaximumTicketLifetime(60000 * 1440);
|
kdcConfig.setMaximumTicketLifetime(60000 * 1440);
|
||||||
kdcConfig.setMaximumRenewableLifetime(60000 * 10080);
|
kdcConfig.setMaximumRenewableLifetime(60000 * 10080);
|
||||||
kdcConfig.setPaEncTimestampRequired(false);
|
kdcConfig.setPaEncTimestampRequired(false);
|
||||||
|
Set<EncryptionType> encryptionTypes = convertEncryptionTypes();
|
||||||
|
kdcConfig.setEncryptionTypes(encryptionTypes);
|
||||||
|
|
||||||
kdcServer = new NoReplayKdcServer(kdcConfig);
|
kdcServer = new NoReplayKdcServer(kdcConfig);
|
||||||
kdcServer.setSearchBaseDn(this.baseDN);
|
kdcServer.setSearchBaseDn(this.baseDN);
|
||||||
|
@ -122,6 +130,24 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Set<EncryptionType> convertEncryptionTypes() {
|
||||||
|
Set<EncryptionType> encryptionTypes = new HashSet<EncryptionType>();
|
||||||
|
String[] configEncTypes = kdcEncryptionTypes.split(",");
|
||||||
|
|
||||||
|
for ( String enc : configEncTypes ) {
|
||||||
|
enc = enc.trim();
|
||||||
|
for ( EncryptionType type : EncryptionType.getEncryptionTypes() ) {
|
||||||
|
if ( type.getName().equalsIgnoreCase( enc ) ) {
|
||||||
|
encryptionTypes.add( type );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptionTypes = KerberosUtils.orderEtypesByStrength(encryptionTypes);
|
||||||
|
return encryptionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replacement of apacheDS KdcServer class with disabled ticket replay cache.
|
* Replacement of apacheDS KdcServer class with disabled ticket replay cache.
|
||||||
*
|
*
|
||||||
|
@ -151,12 +177,10 @@ public class KerberosEmbeddedServer extends LDAPEmbeddedServer {
|
||||||
@Override
|
@Override
|
||||||
public void save(KerberosPrincipal serverPrincipal, KerberosPrincipal clientPrincipal, KerberosTime clientTime,
|
public void save(KerberosPrincipal serverPrincipal, KerberosPrincipal clientPrincipal, KerberosTime clientTime,
|
||||||
int clientMicroSeconds) {
|
int clientMicroSeconds) {
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue