diff --git a/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java b/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java index ffdf02dd6e..095d214467 100644 --- a/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java +++ b/federation/sssd/src/main/java/cx/ath/matthew/LibraryLoader.java @@ -31,7 +31,7 @@ public class LibraryLoader { private static final String VERSION = "0.0.8"; private static boolean loadSucceeded; - public static void load() { + public static LibraryLoader load() { for (String path : PATHS) { try { System.load(String.format("%s/%s.so.%s", path, LIBRARY_NAME, VERSION)); @@ -45,5 +45,11 @@ public class LibraryLoader { if (!loadSucceeded) LOGGER.log(Level.WARNING, "libunix_dbus_java not found\n" + "Please, make sure you have the package libunix-dbus-java installed."); + + return new LibraryLoader(); + } + + public boolean succeed() { + return loadSucceeded; } } diff --git a/federation/sssd/src/main/java/org/freedesktop/DBus.java b/federation/sssd/src/main/java/org/freedesktop/DBus.java index 1aa180a4ab..b7a16877ae 100644 --- a/federation/sssd/src/main/java/org/freedesktop/DBus.java +++ b/federation/sssd/src/main/java/org/freedesktop/DBus.java @@ -30,18 +30,22 @@ import java.util.List; import java.util.Map; public interface DBus extends DBusInterface { - public static final int DBUS_NAME_FLAG_ALLOW_REPLACEMENT = 0x01; - public static final int DBUS_NAME_FLAG_REPLACE_EXISTING = 0x02; - public static final int DBUS_NAME_FLAG_DO_NOT_QUEUE = 0x04; - public static final int DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1; - public static final int DBUS_REQUEST_NAME_REPLY_IN_QUEUE = 2; - public static final int DBUS_REQUEST_NAME_REPLY_EXISTS = 3; - public static final int DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4; - public static final int DBUS_RELEASE_NAME_REPLY_RELEASED = 1; - public static final int DBUS_RELEASE_NAME_REPLY_NON_EXISTANT = 2; - public static final int DBUS_RELEASE_NAME_REPLY_NOT_OWNER = 3; - public static final int DBUS_START_REPLY_SUCCESS = 1; - public static final int DBUS_START_REPLY_ALREADY_RUNNING = 2; + + String BUSNAME = "org.freedesktop.DBus"; + String OBJECTPATH = "/org/freedesktop/DBus"; + + int DBUS_NAME_FLAG_ALLOW_REPLACEMENT = 0x01; + int DBUS_NAME_FLAG_REPLACE_EXISTING = 0x02; + int DBUS_NAME_FLAG_DO_NOT_QUEUE = 0x04; + int DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1; + int DBUS_REQUEST_NAME_REPLY_IN_QUEUE = 2; + int DBUS_REQUEST_NAME_REPLY_EXISTS = 3; + int DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4; + int DBUS_RELEASEME_REPLY_RELEASED = 1; + int DBUS_RELEASE_NAME_REPLY_NON_EXISTANT = 2; + int DBUS_RELEASE_NAME_REPLY_NOT_OWNER = 3; + int DBUS_START_REPLY_SUCCESS = 1; + int DBUS_START_REPLY_ALREADY_RUNNING = 2; /** * All DBus Applications should respond to the Ping method on this interface @@ -527,4 +531,4 @@ public interface DBus extends DBusInterface { } } } -} +} \ No newline at end of file diff --git a/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java b/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java index 8791170caf..6152d26a25 100644 --- a/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java +++ b/federation/sssd/src/main/java/org/freedesktop/sssd/infopipe/InfoPipe.java @@ -32,6 +32,8 @@ import java.util.Map; public interface InfoPipe extends DBusInterface { String OBJECTPATH = "/org/freedesktop/sssd/infopipe"; + String BUSNAME = "org.freedesktop.sssd.infopipe"; + @DBusMemberName("GetUserAttr") Map getUserAttributes(String user, List attr); @@ -39,4 +41,4 @@ public interface InfoPipe extends DBusInterface { @DBusMemberName("GetUserGroups") List getUserGroups(String user); -} +} \ No newline at end of file diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java index 6a287a7ad8..3140e9e48a 100755 --- a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java +++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java @@ -19,6 +19,7 @@ package org.keycloak.federation.sssd; import org.jboss.logging.Logger; import org.keycloak.Config; +import org.keycloak.federation.sssd.api.Sssd; import org.keycloak.federation.sssd.impl.PAMAuthenticator; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; @@ -26,6 +27,7 @@ import org.keycloak.models.UserFederationProvider; import org.keycloak.models.UserFederationProviderFactory; import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserFederationSyncResult; +import org.keycloak.provider.EnvironmentDependentProviderFactory; import java.util.Date; import java.util.HashSet; @@ -35,7 +37,7 @@ import java.util.Set; * @author Bruno Oliveira * @version $Revision: 1 $ */ -public class SSSDFederationProviderFactory implements UserFederationProviderFactory { +public class SSSDFederationProviderFactory implements UserFederationProviderFactory, EnvironmentDependentProviderFactory { private static final String PROVIDER_NAME = "sssd"; private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class); @@ -99,4 +101,8 @@ public class SSSDFederationProviderFactory implements UserFederationProviderFact return new PAMAuthenticator(username, factors); } -} + @Override + public boolean isSupported() { + return Sssd.isAvailable(); + } +} \ No newline at end of file diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java index a5bb57a308..fd9dc6752e 100644 --- a/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java +++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java @@ -17,6 +17,8 @@ package org.keycloak.federation.sssd.api; +import cx.ath.matthew.LibraryLoader; +import org.freedesktop.DBus; import org.freedesktop.dbus.DBusConnection; import org.freedesktop.dbus.Variant; import org.freedesktop.dbus.exceptions.DBusException; @@ -35,8 +37,6 @@ import java.util.Vector; */ public class Sssd { - public static final String BUSNAME = "org.freedesktop.sssd.infopipe"; - public static User user() { return SingletonHolder.USER_OBJECT; } @@ -45,6 +45,7 @@ public class Sssd { return SingletonHolder.INFOPIPE_OBJECT; } + public static void disconnect() { SingletonHolder.DBUS_CONNECTION.disconnect(); } @@ -67,10 +68,10 @@ public class Sssd { static { try { DBUS_CONNECTION = DBusConnection.getConnection(DBusConnection.SYSTEM); - INFOPIPE_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, InfoPipe.OBJECTPATH, InfoPipe.class); - USER_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, User.OBJECTPATH, User.class); + INFOPIPE_OBJECT = DBUS_CONNECTION.getRemoteObject(InfoPipe.BUSNAME, InfoPipe.OBJECTPATH, InfoPipe.class); + USER_OBJECT = DBUS_CONNECTION.getRemoteObject(InfoPipe.BUSNAME, User.OBJECTPATH, User.class); } catch (DBusException e) { - e.printStackTrace(); + logger.error("Failed to obtain D-Bus connection", e); } } } @@ -108,4 +109,24 @@ public class Sssd { } return userGroups; } + + public static boolean isAvailable(){ + boolean sssdAvailable = false; + try { + if (LibraryLoader.load().succeed()) { + DBusConnection connection = DBusConnection.getConnection(DBusConnection.SYSTEM); + DBus dbus = connection.getRemoteObject(DBus.BUSNAME, DBus.OBJECTPATH, DBus.class); + sssdAvailable = Arrays.asList(dbus.ListNames()).contains(InfoPipe.BUSNAME); + if (!sssdAvailable) { + logger.debugv("SSSD is not available in your system. Federation provider will be disabled."); + } else { + sssdAvailable = true; + } + connection.disconnect(); + } + } catch (DBusException e) { + logger.error("Failed to check the status of SSSD", e); + } + return sssdAvailable; + } } diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java index a1521bd659..3965f714d8 100755 --- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java +++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java @@ -205,6 +205,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr logger.debugv("Loaded SPI {0} (provider = {1})", spi.getName(), provider); } + } else { for (ProviderFactory factory : pm.load(spi)) { Config.Scope scope = Config.scope(spi.getName(), factory.getId()); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java index 7a939c3518..8cef8a1bbc 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserFederationTest.java @@ -51,7 +51,7 @@ public class UserFederationTest extends AbstractAdminTest { @Test public void testProviderFactories() { List providerFactories = userFederation().getProviderFactories(); - Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable", "sssd"); + Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable"); // Builtin provider without properties UserFederationProviderFactoryRepresentation ldapProvider = userFederation().getProviderFactory("ldap"); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/PlainTextPasswordProviderFactory.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/PlainTextPasswordProviderFactory.java index dd281d17f8..cdb324ca5c 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/PlainTextPasswordProviderFactory.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/PlainTextPasswordProviderFactory.java @@ -21,15 +21,12 @@ import org.keycloak.hash.PasswordHashProvider; import org.keycloak.hash.PasswordHashProviderFactory; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; -import org.keycloak.provider.EnvironmentDependentProviderFactory; - -import java.io.File; /** * @author Bill Burke * @version $Revision: 1 $ */ -public class PlainTextPasswordProviderFactory implements PasswordHashProviderFactory, EnvironmentDependentProviderFactory { +public class PlainTextPasswordProviderFactory implements PasswordHashProviderFactory { @Override public PasswordHashProvider create(KeycloakSession session) { return new PlainTextPasswordProvider(); @@ -54,10 +51,4 @@ public class PlainTextPasswordProviderFactory implements PasswordHashProviderFac public String getId() { return "text"; } - - // TODO REMOVE THIS - @Override - public boolean isSupported() { - return !new File("/tmp/disable-text-hash").exists(); - } }