Check if SSSD is available via DBUS
This commit is contained in:
parent
36bb94afb8
commit
11245701d2
8 changed files with 64 additions and 33 deletions
|
@ -31,7 +31,7 @@ public class LibraryLoader {
|
||||||
private static final String VERSION = "0.0.8";
|
private static final String VERSION = "0.0.8";
|
||||||
private static boolean loadSucceeded;
|
private static boolean loadSucceeded;
|
||||||
|
|
||||||
public static void load() {
|
public static LibraryLoader load() {
|
||||||
for (String path : PATHS) {
|
for (String path : PATHS) {
|
||||||
try {
|
try {
|
||||||
System.load(String.format("%s/%s.so.%s", path, LIBRARY_NAME, VERSION));
|
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" +
|
if (!loadSucceeded) LOGGER.log(Level.WARNING, "libunix_dbus_java not found\n" +
|
||||||
"Please, make sure you have the package libunix-dbus-java installed.");
|
"Please, make sure you have the package libunix-dbus-java installed.");
|
||||||
|
|
||||||
|
return new LibraryLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean succeed() {
|
||||||
|
return loadSucceeded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,18 +30,22 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface DBus extends DBusInterface {
|
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;
|
String BUSNAME = "org.freedesktop.DBus";
|
||||||
public static final int DBUS_NAME_FLAG_DO_NOT_QUEUE = 0x04;
|
String OBJECTPATH = "/org/freedesktop/DBus";
|
||||||
public static final int DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1;
|
|
||||||
public static final int DBUS_REQUEST_NAME_REPLY_IN_QUEUE = 2;
|
int DBUS_NAME_FLAG_ALLOW_REPLACEMENT = 0x01;
|
||||||
public static final int DBUS_REQUEST_NAME_REPLY_EXISTS = 3;
|
int DBUS_NAME_FLAG_REPLACE_EXISTING = 0x02;
|
||||||
public static final int DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4;
|
int DBUS_NAME_FLAG_DO_NOT_QUEUE = 0x04;
|
||||||
public static final int DBUS_RELEASE_NAME_REPLY_RELEASED = 1;
|
int DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER = 1;
|
||||||
public static final int DBUS_RELEASE_NAME_REPLY_NON_EXISTANT = 2;
|
int DBUS_REQUEST_NAME_REPLY_IN_QUEUE = 2;
|
||||||
public static final int DBUS_RELEASE_NAME_REPLY_NOT_OWNER = 3;
|
int DBUS_REQUEST_NAME_REPLY_EXISTS = 3;
|
||||||
public static final int DBUS_START_REPLY_SUCCESS = 1;
|
int DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4;
|
||||||
public static final int DBUS_START_REPLY_ALREADY_RUNNING = 2;
|
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
|
* All DBus Applications should respond to the Ping method on this interface
|
||||||
|
@ -527,4 +531,4 @@ public interface DBus extends DBusInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,8 @@ import java.util.Map;
|
||||||
public interface InfoPipe extends DBusInterface {
|
public interface InfoPipe extends DBusInterface {
|
||||||
|
|
||||||
String OBJECTPATH = "/org/freedesktop/sssd/infopipe";
|
String OBJECTPATH = "/org/freedesktop/sssd/infopipe";
|
||||||
|
String BUSNAME = "org.freedesktop.sssd.infopipe";
|
||||||
|
|
||||||
|
|
||||||
@DBusMemberName("GetUserAttr")
|
@DBusMemberName("GetUserAttr")
|
||||||
Map<String, Variant> getUserAttributes(String user, List<String> attr);
|
Map<String, Variant> getUserAttributes(String user, List<String> attr);
|
||||||
|
@ -39,4 +41,4 @@ public interface InfoPipe extends DBusInterface {
|
||||||
@DBusMemberName("GetUserGroups")
|
@DBusMemberName("GetUserGroups")
|
||||||
List<String> getUserGroups(String user);
|
List<String> getUserGroups(String user);
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ package org.keycloak.federation.sssd;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.federation.sssd.api.Sssd;
|
||||||
import org.keycloak.federation.sssd.impl.PAMAuthenticator;
|
import org.keycloak.federation.sssd.impl.PAMAuthenticator;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
@ -26,6 +27,7 @@ import org.keycloak.models.UserFederationProvider;
|
||||||
import org.keycloak.models.UserFederationProviderFactory;
|
import org.keycloak.models.UserFederationProviderFactory;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserFederationSyncResult;
|
import org.keycloak.models.UserFederationSyncResult;
|
||||||
|
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -35,7 +37,7 @@ import java.util.Set;
|
||||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class SSSDFederationProviderFactory implements UserFederationProviderFactory {
|
public class SSSDFederationProviderFactory implements UserFederationProviderFactory, EnvironmentDependentProviderFactory {
|
||||||
|
|
||||||
private static final String PROVIDER_NAME = "sssd";
|
private static final String PROVIDER_NAME = "sssd";
|
||||||
private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class);
|
private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class);
|
||||||
|
@ -99,4 +101,8 @@ public class SSSDFederationProviderFactory implements UserFederationProviderFact
|
||||||
return new PAMAuthenticator(username, factors);
|
return new PAMAuthenticator(username, factors);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
return Sssd.isAvailable();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package org.keycloak.federation.sssd.api;
|
package org.keycloak.federation.sssd.api;
|
||||||
|
|
||||||
|
import cx.ath.matthew.LibraryLoader;
|
||||||
|
import org.freedesktop.DBus;
|
||||||
import org.freedesktop.dbus.DBusConnection;
|
import org.freedesktop.dbus.DBusConnection;
|
||||||
import org.freedesktop.dbus.Variant;
|
import org.freedesktop.dbus.Variant;
|
||||||
import org.freedesktop.dbus.exceptions.DBusException;
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
|
@ -35,8 +37,6 @@ import java.util.Vector;
|
||||||
*/
|
*/
|
||||||
public class Sssd {
|
public class Sssd {
|
||||||
|
|
||||||
public static final String BUSNAME = "org.freedesktop.sssd.infopipe";
|
|
||||||
|
|
||||||
public static User user() {
|
public static User user() {
|
||||||
return SingletonHolder.USER_OBJECT;
|
return SingletonHolder.USER_OBJECT;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ public class Sssd {
|
||||||
return SingletonHolder.INFOPIPE_OBJECT;
|
return SingletonHolder.INFOPIPE_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void disconnect() {
|
public static void disconnect() {
|
||||||
SingletonHolder.DBUS_CONNECTION.disconnect();
|
SingletonHolder.DBUS_CONNECTION.disconnect();
|
||||||
}
|
}
|
||||||
|
@ -67,10 +68,10 @@ public class Sssd {
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
DBUS_CONNECTION = DBusConnection.getConnection(DBusConnection.SYSTEM);
|
DBUS_CONNECTION = DBusConnection.getConnection(DBusConnection.SYSTEM);
|
||||||
INFOPIPE_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, InfoPipe.OBJECTPATH, InfoPipe.class);
|
INFOPIPE_OBJECT = DBUS_CONNECTION.getRemoteObject(InfoPipe.BUSNAME, InfoPipe.OBJECTPATH, InfoPipe.class);
|
||||||
USER_OBJECT = DBUS_CONNECTION.getRemoteObject(BUSNAME, User.OBJECTPATH, User.class);
|
USER_OBJECT = DBUS_CONNECTION.getRemoteObject(InfoPipe.BUSNAME, User.OBJECTPATH, User.class);
|
||||||
} catch (DBusException e) {
|
} catch (DBusException e) {
|
||||||
e.printStackTrace();
|
logger.error("Failed to obtain D-Bus connection", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,4 +109,24 @@ public class Sssd {
|
||||||
}
|
}
|
||||||
return userGroups;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
||||||
|
|
||||||
logger.debugv("Loaded SPI {0} (provider = {1})", spi.getName(), provider);
|
logger.debugv("Loaded SPI {0} (provider = {1})", spi.getName(), provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (ProviderFactory factory : pm.load(spi)) {
|
for (ProviderFactory factory : pm.load(spi)) {
|
||||||
Config.Scope scope = Config.scope(spi.getName(), factory.getId());
|
Config.Scope scope = Config.scope(spi.getName(), factory.getId());
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class UserFederationTest extends AbstractAdminTest {
|
||||||
@Test
|
@Test
|
||||||
public void testProviderFactories() {
|
public void testProviderFactories() {
|
||||||
List<UserFederationProviderFactoryRepresentation> providerFactories = userFederation().getProviderFactories();
|
List<UserFederationProviderFactoryRepresentation> providerFactories = userFederation().getProviderFactories();
|
||||||
Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable", "sssd");
|
Assert.assertNames(providerFactories, "ldap", "kerberos", "dummy", "dummy-configurable");
|
||||||
|
|
||||||
// Builtin provider without properties
|
// Builtin provider without properties
|
||||||
UserFederationProviderFactoryRepresentation ldapProvider = userFederation().getProviderFactory("ldap");
|
UserFederationProviderFactoryRepresentation ldapProvider = userFederation().getProviderFactory("ldap");
|
||||||
|
|
|
@ -21,15 +21,12 @@ import org.keycloak.hash.PasswordHashProvider;
|
||||||
import org.keycloak.hash.PasswordHashProviderFactory;
|
import org.keycloak.hash.PasswordHashProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class PlainTextPasswordProviderFactory implements PasswordHashProviderFactory, EnvironmentDependentProviderFactory {
|
public class PlainTextPasswordProviderFactory implements PasswordHashProviderFactory {
|
||||||
@Override
|
@Override
|
||||||
public PasswordHashProvider create(KeycloakSession session) {
|
public PasswordHashProvider create(KeycloakSession session) {
|
||||||
return new PlainTextPasswordProvider();
|
return new PlainTextPasswordProvider();
|
||||||
|
@ -54,10 +51,4 @@ public class PlainTextPasswordProviderFactory implements PasswordHashProviderFac
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return "text";
|
return "text";
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO REMOVE THIS
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
return !new File("/tmp/disable-text-hash").exists();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue