add propagation options + simplify auth config

This commit is contained in:
Hugo Renard 2022-05-03 16:20:38 +02:00
parent 4a2cdb5e86
commit 55052475c6
Signed by: hougo
GPG key ID: 3A285FD470209C59
5 changed files with 47 additions and 33 deletions

View file

@ -10,7 +10,6 @@ import org.jboss.logging.Logger;
import org.keycloak.connections.jpa.JpaConnectionProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RoleMapperModel;
import sh.libre.scim.jpa.ScimResource;
public abstract class Adapter<M extends RoleMapperModel, S extends com.unboundid.scim2.common.ScimResource> {

View file

@ -38,12 +38,12 @@ public class ScimClient {
var target = client.target(model.get("endpoint"));
switch (model.get("auth-mode")) {
case "BEARER":
target = target.register(new BearerAuthentication(model.get("auth-bearer-token")));
target = target.register(new BearerAuthentication(model.get("auth-pass")));
break;
case "BASIC_AUTH":
target = target.register(new BasicAuthentication(
model.get("auth-basic-auth-user"),
model.get("auth-basic-auth-pass")));
model.get("auth-user"),
model.get("auth-pass")));
}
scimService = new ScimService(target);

View file

@ -7,6 +7,9 @@ import org.keycloak.models.KeycloakSession;
import sh.libre.scim.storage.ScimStorageProviderFactory;
public class ScimDispatcher {
public static final String SCOPE_USER = "user";
public static final String SCOPE_GROUP = "group";
final private KeycloakSession session;
final private Logger LOGGER = Logger.getLogger(ScimDispatcher.class);
@ -14,10 +17,10 @@ public class ScimDispatcher {
this.session = session;
}
public void run(Consumer<ScimClient> f) {
public void run(String scope, Consumer<ScimClient> f) {
session.getContext().getRealm().getComponentsStream()
.filter((m) -> {
return ScimStorageProviderFactory.ID.equals(m.getProviderId()) && m.get("enabled").equals("true");
return ScimStorageProviderFactory.ID.equals(m.getProviderId()) && m.get("enabled").equals("true") && m.get("propagation-"+scope).equals("true");
})
.forEach(m -> {
LOGGER.infof("%s %s %s %s", m.getId(), m.getName(), m.getProviderId(), m.getProviderType());

View file

@ -35,14 +35,14 @@ public class ScimEventListenerProvider implements EventListenerProvider {
public void onEvent(Event event) {
if (event.getType() == EventType.REGISTER) {
var user = getUser(event.getUserId());
dispatcher.run((client) -> client.create(UserAdapter.class, user));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.create(UserAdapter.class, user));
}
if (event.getType() == EventType.UPDATE_EMAIL || event.getType() == EventType.UPDATE_PROFILE) {
var user = getUser(event.getUserId());
dispatcher.run((client) -> client.replace(UserAdapter.class, user));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.replace(UserAdapter.class, user));
}
if (event.getType() == EventType.DELETE_ACCOUNT) {
dispatcher.run((client) -> client.delete(UserAdapter.class, event.getUserId()));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.delete(UserAdapter.class, event.getUserId()));
}
}
@ -53,14 +53,14 @@ public class ScimEventListenerProvider implements EventListenerProvider {
LOGGER.infof("%s %s", userId, event.getOperationType());
if (event.getOperationType() == OperationType.CREATE) {
var user = getUser(userId);
dispatcher.run((client) -> client.create(UserAdapter.class, user));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.create(UserAdapter.class, user));
}
if (event.getOperationType() == OperationType.UPDATE) {
var user = getUser(userId);
dispatcher.run((client) -> client.replace(UserAdapter.class, user));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.replace(UserAdapter.class, user));
}
if (event.getOperationType() == OperationType.DELETE) {
dispatcher.run((client) -> client.delete(UserAdapter.class, userId));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.delete(UserAdapter.class, userId));
}
}
if (event.getResourceType() == ResourceType.GROUP) {
@ -68,14 +68,14 @@ public class ScimEventListenerProvider implements EventListenerProvider {
LOGGER.infof("%s %s", event.getResourcePath(), event.getOperationType());
if (event.getOperationType() == OperationType.CREATE) {
var group = getGroup(groupId);
dispatcher.run((client) -> client.create(GroupAdapter.class, group));
dispatcher.run(ScimDispatcher.SCOPE_GROUP, (client) -> client.create(GroupAdapter.class, group));
}
if (event.getOperationType() == OperationType.UPDATE) {
var group = getGroup(groupId);
dispatcher.run((client) -> client.replace(GroupAdapter.class, group));
dispatcher.run(ScimDispatcher.SCOPE_GROUP, (client) -> client.replace(GroupAdapter.class, group));
}
if (event.getOperationType() == OperationType.DELETE) {
dispatcher.run((client) -> client.delete(GroupAdapter.class, groupId));
dispatcher.run(ScimDispatcher.SCOPE_GROUP, (client) -> client.delete(GroupAdapter.class, groupId));
}
}
if (event.getResourceType() == ResourceType.GROUP_MEMBERSHIP) {
@ -86,9 +86,9 @@ public class ScimEventListenerProvider implements EventListenerProvider {
var groupId = matcher.group(2);
LOGGER.infof("%s %s from %s", event.getOperationType(), userId, groupId);
var group = getGroup(groupId);
dispatcher.run((client) -> client.replace(GroupAdapter.class, group));
dispatcher.run(ScimDispatcher.SCOPE_GROUP, (client) -> client.replace(GroupAdapter.class, group));
var user = getUser(userId);
dispatcher.run((client) -> client.replace(UserAdapter.class, user));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.replace(UserAdapter.class, user));
}
}
if (event.getResourceType() == ResourceType.REALM_ROLE_MAPPING) {
@ -100,11 +100,11 @@ public class ScimEventListenerProvider implements EventListenerProvider {
LOGGER.infof("%s %s %s roles", event.getOperationType(), type, id);
if (type.equals("users")) {
var user = getUser(id);
dispatcher.run((client) -> client.replace(UserAdapter.class, user));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.replace(UserAdapter.class, user));
} else if (type.equals("groups")) {
var group = getGroup(id);
session.users().getGroupMembersStream(session.getContext().getRealm(), group).forEach(user -> {
dispatcher.run((client) -> client.replace(UserAdapter.class, user));
dispatcher.run(ScimDispatcher.SCOPE_USER, (client) -> client.replace(UserAdapter.class, user));
});
}
}

View file

@ -52,24 +52,32 @@ public class ScimStorageProviderFactory
.type(ProviderConfigProperty.LIST_TYPE)
.label("Auth mode")
.helpText("Select the authorization mode")
.options("NONE", "BEARER", "BASIC_AUTH")
.options("NONE", "BASIC_AUTH", "BEARER")
.defaultValue("NONE")
.add()
.property()
.name("auth-bearer-token")
.type(ProviderConfigProperty.PASSWORD)
.label("Bearer token")
.helpText("Add a bearer token in the authorization header")
.add()
.property()
.name("auth-basic-auth-user")
.name("auth-user")
.type(ProviderConfigProperty.STRING_TYPE)
.label("BasicAuth user")
.label("Auth username")
.helpText("Required for basic authentification.")
.add()
.property()
.name("auth-basic-auth-pass")
.name("auth-pass")
.type(ProviderConfigProperty.PASSWORD)
.label("BasicAuth password")
.label("Auth password/token")
.helpText("Password or token required for basic or bearer authentification.")
.add()
.property()
.name("propagation-user")
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.label("Enable user propagation")
.defaultValue("true")
.add()
.property()
.name("propagation-group")
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.label("Enable group propagation")
.defaultValue("true")
.add()
.property()
.name("sync-import")
@ -120,8 +128,12 @@ public class ScimStorageProviderFactory
RealmModel realm = session.realms().getRealm(realmId);
session.getContext().setRealm(realm);
var client = new ScimClient(model, session);
if (model.get("propagation-user").equals("true")) {
client.sync(UserAdapter.class, result);
}
if (model.get("propagation-group").equals("true")) {
client.sync(GroupAdapter.class, result);
}
client.close();
}