Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LDAP-44] Cater for extendability and inheritance #26

Merged
merged 5 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@

public class LdapAuthenticate {

private final LdapConnection conn;
protected final LdapConnection conn;

private final ObjectClass oclass;
protected final ObjectClass oclass;

private final String username;
protected final String username;

private final OperationOptions options;
protected final OperationOptions options;

public LdapAuthenticate(LdapConnection conn, ObjectClass oclass, String username, OperationOptions options) {
this.conn = conn;
Expand Down Expand Up @@ -90,7 +90,7 @@ public Uid resolveUsername() {
return authnObject.getUid();
}

private ConnectorObject getObjectToAuthenticate() {
protected ConnectorObject getObjectToAuthenticate() {
List<String> userNameAttrs = getUserNameAttributes();
Map<String, ConnectorObject> entryDN2Object = new HashMap<String, ConnectorObject>();
final String dnAttributeName = conn.getConfiguration().getDnAttribute();
Expand All @@ -113,15 +113,15 @@ private ConnectorObject getObjectToAuthenticate() {
return null;
}

private List<String> getUserNameAttributes() {
protected List<String> getUserNameAttributes() {
String[] result = LdapConstants.getLdapUidAttributes(options);
if (result != null && result.length > 0) {
return Arrays.asList(result);
}
return conn.getSchemaMapping().getUserNameLdapAttributes(oclass);
return conn.getSchema().getUserNameLdapAttributes(oclass);
}

private static boolean isSuccess(AuthenticationResult authResult) {
protected static boolean isSuccess(AuthenticationResult authResult) {
// We consider PASSWORD_EXPIRED to be a success, because it means the credentials were right.
return authResult.getType() != null
&& (authResult.getType().equals(AuthenticationResultType.SUCCESS)
Expand Down
46 changes: 33 additions & 13 deletions src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import net.tirasa.connid.bundles.ldap.commons.LdapConstants;
import net.tirasa.connid.bundles.ldap.commons.LdapUtil;
import net.tirasa.connid.bundles.ldap.commons.ObjectClassMappingConfig;
import net.tirasa.connid.bundles.ldap.schema.LdapSchemaMapping;
import net.tirasa.connid.bundles.ldap.schema.LdapSchema;
ilgrosso marked this conversation as resolved.
Show resolved Hide resolved
import net.tirasa.connid.bundles.ldap.search.DefaultSearchStrategy;
import net.tirasa.connid.bundles.ldap.sync.LdapSyncStrategy;
import net.tirasa.connid.bundles.ldap.sync.sunds.SunDSChangeLogSyncStrategy;
Expand Down Expand Up @@ -225,6 +225,10 @@ public enum SearchScope {

private Class<? extends LdapSyncStrategy> syncStrategyClass = null;

private Class<? extends LdapSyncStrategy> fallbackSyncStrategyClass = SunDSChangeLogSyncStrategy.class;

private Class<? extends LdapConnection> connectionClass = LdapConnection.class;

/**
* The SearchScope for user objects
*/
Expand Down Expand Up @@ -258,7 +262,7 @@ public enum SearchScope {
false, CollectionUtil.newList("cn"));

private final ObjectClassMappingConfig anyObjectConfig = new ObjectClassMappingConfig(
LdapSchemaMapping.ANY_OBJECT_CLASS,
LdapSchema.ANY_OBJECT_CLASS,
CollectionUtil.newList("top"),
false, CollectionUtil.newList(DEFAULT_ID_ATTRIBUTE));

Expand Down Expand Up @@ -365,13 +369,13 @@ public void validate() {
checkLdapSyncStrategy();
}

private void checkNotBlank(String value, String errorMessage) {
protected void checkNotBlank(String value, String errorMessage) {
if (StringUtil.isBlank(value)) {
failValidation(errorMessage);
}
}

private void checkNotBlank(GuardedByteArray array, String errorMessage) {
protected void checkNotBlank(GuardedByteArray array, String errorMessage) {
final int[] length = { 0 };
if (array != null) {
array.access(new Accessor() {
Expand All @@ -388,7 +392,7 @@ public void access(byte[] clearBytes) {
}

@SuppressWarnings("unchecked")
private void checkLdapSyncStrategy() {
protected void checkLdapSyncStrategy() {
try {
Class<?> clazz = Class.forName(syncStrategy);
if (LdapSyncStrategy.class.isAssignableFrom(clazz) && !Modifier.isAbstract(clazz.getModifiers())) {
Expand All @@ -401,35 +405,35 @@ private void checkLdapSyncStrategy() {
}
}

private void checkNotEmpty(Collection<?> collection, String errorMessage) {
protected void checkNotEmpty(Collection<?> collection, String errorMessage) {
if (collection.isEmpty()) {
failValidation(errorMessage);
}
}

private void checkNotEmpty(String[] array, String errorMessage) {
protected void checkNotEmpty(String[] array, String errorMessage) {
if (array == null || array.length < 1) {
failValidation(errorMessage);
}
}

private void checkNoBlankValues(Collection<String> collection, String errorMessage) {
protected void checkNoBlankValues(Collection<String> collection, String errorMessage) {
for (String each : collection) {
if (StringUtil.isBlank(each)) {
failValidation(errorMessage);
}
}
}

private void checkNoBlankValues(String[] array, String errorMessage) {
protected void checkNoBlankValues(String[] array, String errorMessage) {
for (String each : array) {
if (StringUtil.isBlank(each)) {
failValidation(errorMessage);
}
}
}

private void checkNoInvalidLdapNames(String[] array, String errorMessage) {
protected void checkNoInvalidLdapNames(String[] array, String errorMessage) {
for (String each : array) {
try {
new LdapName(each);
Expand All @@ -439,7 +443,7 @@ private void checkNoInvalidLdapNames(String[] array, String errorMessage) {
}
}

private void checkValidScope(String scope, String errorMessage) {
protected void checkValidScope(String scope, String errorMessage) {
switch (scope) {
case OperationOptions.SCOPE_OBJECT:
case OperationOptions.SCOPE_ONE_LEVEL:
Expand All @@ -450,7 +454,7 @@ private void checkValidScope(String scope, String errorMessage) {
}
}

private void failValidation(String key, Object... args) {
protected void failValidation(String key, Object... args) {
String message = getConnectorMessages().format(key, null, args);
throw new ConfigurationException(message);
}
Expand Down Expand Up @@ -1033,6 +1037,22 @@ public Class<? extends LdapSyncStrategy> getSyncStrategyClass() {
return syncStrategyClass;
}

protected Class<? extends LdapSyncStrategy> getFallbackSyncStrategyClass() {
return fallbackSyncStrategyClass;
}

protected void setFallbackSyncStrategyClass(Class<? extends LdapSyncStrategy> fallbackSyncStrategyClass) {
this.fallbackSyncStrategyClass = fallbackSyncStrategyClass;
}

protected Class<? extends LdapConnection> getConnectionClass() {
return connectionClass;
}

protected void setConnectionClass(Class<? extends LdapConnection> connectionClass) {
this.connectionClass = connectionClass;
}

// Getters and setters for configuration properties end here.
public List<LdapName> getBaseContextsAsLdapNames() {
if (baseContextsAsLdapNames == null) {
Expand Down Expand Up @@ -1090,7 +1110,7 @@ public Map<ObjectClass, ObjectClassMappingConfig> getObjectClassMappingConfigs()
return result;
}

private EqualsHashCodeBuilder createHashCodeBuilder() {
protected EqualsHashCodeBuilder createHashCodeBuilder() {
EqualsHashCodeBuilder builder = new EqualsHashCodeBuilder();
// Exposed configuration properties.
builder.append(host);
Expand Down
40 changes: 20 additions & 20 deletions src/main/java/net/tirasa/connid/bundles/ldap/LdapConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
import net.tirasa.connid.bundles.ldap.commons.LdapUtil;
import net.tirasa.connid.bundles.ldap.commons.ServerNativeSchema;
import net.tirasa.connid.bundles.ldap.commons.StaticNativeSchema;
import net.tirasa.connid.bundles.ldap.schema.LdapSchemaMapping;
import net.tirasa.connid.bundles.ldap.schema.LdapSchema;
import org.identityconnectors.common.CollectionUtil;
import org.identityconnectors.common.Pair;
import org.identityconnectors.common.StringUtil;
Expand Down Expand Up @@ -95,23 +95,23 @@ public class LdapConnection {
LDAP_BINARY_OPTION_ATTRS.add("supportedAlgorithms");
}

private static final String LDAP_CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
protected static final String LDAP_CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";

private static final Log LOG = Log.getLog(LdapConnection.class);

private final LdapConfiguration config;
protected final LdapConfiguration config;

private final LdapSchemaMapping schemaMapping;
protected LdapSchema schema;

private LdapContext initCtx;
protected LdapContext initCtx;

private Set<String> supportedControls;
protected Set<String> supportedControls;

private ServerType serverType;
protected ServerType serverType;

public LdapConnection(LdapConfiguration config) {
this.config = config;
schemaMapping = new LdapSchemaMapping(this);
schema = new LdapSchema(this);
}

public String format(String key, String dflt, Object... args) {
Expand All @@ -130,7 +130,7 @@ public LdapContext getInitialContext() {
return initCtx;
}

private LdapContext connect(String principal, GuardedString credentials) {
protected LdapContext connect(String principal, GuardedString credentials) {
Pair<AuthenticationResult, LdapContext> pair = createContext(principal, credentials);
if (pair.first.getType().equals(AuthenticationResultType.SUCCESS)) {
return pair.second;
Expand All @@ -139,7 +139,7 @@ private LdapContext connect(String principal, GuardedString credentials) {
throw new IllegalStateException("Should never get here");
}

private Pair<AuthenticationResult, LdapContext> createContext(String principal, GuardedString credentials) {
protected Pair<AuthenticationResult, LdapContext> createContext(String principal, GuardedString credentials) {
final List<Pair<AuthenticationResult, LdapContext>> result =
new ArrayList<Pair<AuthenticationResult, LdapContext>>(1);

Expand Down Expand Up @@ -183,7 +183,7 @@ public void access(final char[] clearChars) {
return result.get(0);
}

private Pair<AuthenticationResult, LdapContext> createContext(final Hashtable<?, ?> env) {
protected Pair<AuthenticationResult, LdapContext> createContext(final Hashtable<?, ?> env) {
AuthenticationResult authnResult = null;
InitialLdapContext context = null;
try {
Expand Down Expand Up @@ -214,7 +214,7 @@ private Pair<AuthenticationResult, LdapContext> createContext(final Hashtable<?,
return new Pair<AuthenticationResult, LdapContext>(authnResult, context);
}

private static boolean hasPasswordExpiredControl(Control[] controls) {
protected static boolean hasPasswordExpiredControl(Control[] controls) {
if (controls != null) {
for (Control control : controls) {
if (control instanceof PasswordExpiredResponseControl) {
Expand All @@ -225,7 +225,7 @@ private static boolean hasPasswordExpiredControl(Control[] controls) {
return false;
}

private String getLdapUrls() {
protected String getLdapUrls() {
StringBuilder builder = new StringBuilder();
builder.append("ldap://");
builder.append(config.getHost());
Expand All @@ -246,7 +246,7 @@ public void close() {
}
}

private static void quietClose(LdapContext ctx) {
protected static void quietClose(LdapContext ctx) {
try {
if (ctx != null) {
ctx.close();
Expand All @@ -256,8 +256,8 @@ private static void quietClose(LdapContext ctx) {
}
}

public LdapSchemaMapping getSchemaMapping() {
return schemaMapping;
public LdapSchema getSchema() {
return schema;
}

public LdapNativeSchema createNativeSchema() {
Expand Down Expand Up @@ -303,7 +303,7 @@ public boolean supportsControl(final String oid) {
return getSupportedControls().contains(oid);
}

private Set<String> getSupportedControls() {
protected Set<String> getSupportedControls() {
if (supportedControls == null) {
try {
Attributes attrs = getInitialContext().getAttributes("", new String[] { "supportedControl" });
Expand All @@ -324,7 +324,7 @@ public ServerType getServerType() {
return serverType;
}

private ServerType detectServerType() {
protected ServerType detectServerType() {
try {
Attributes attrs = getInitialContext().getAttributes("", new String[] { "vendorVersion" });
String vendorVersion = LdapUtil.getStringAttrValue(attrs, "vendorVersion");
Expand Down Expand Up @@ -379,9 +379,9 @@ public void propagate(Exception cause) {

public static class AuthenticationResult {

private final AuthenticationResultType type;
protected final AuthenticationResultType type;

private final Exception cause;
protected final Exception cause;

public AuthenticationResult(AuthenticationResultType type) {
this(type, null);
Expand Down
36 changes: 26 additions & 10 deletions src/main/java/net/tirasa/connid/bundles/ldap/LdapConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ public class LdapConnector implements
/**
* The configuration for this connector instance.
*/
private LdapConfiguration config;
protected LdapConfiguration config;

/**
* The connection to the LDAP server.
*/
private LdapConnection conn;
protected LdapConnection conn;

private LdapSyncStrategy syncStrategy;
protected LdapSyncStrategy syncStrategy;

@Override
public Configuration getConfiguration() {
Expand All @@ -87,15 +87,31 @@ public Configuration getConfiguration() {
@Override
public void init(Configuration cfg) {
config = (LdapConfiguration) cfg;
conn = new LdapConnection(config);

Class<? extends LdapSyncStrategy> syncStrategyClass = config.getSyncStrategyClass();
Class<? extends LdapConnection> connectionClass = config.getConnectionClass();

try {
conn = connectionClass.getConstructor(LdapConfiguration.class).newInstance(config);
} catch (Exception e) {
LOG.error(e, "Could not instantiate the configured connection class implementation {0}, reverting to {1}",
connectionClass.getName(), LdapConnection.class.getName());
conn = new LdapConnection(config);
}

try {
syncStrategy = syncStrategyClass.getConstructor(LdapConnection.class).newInstance(conn);
syncStrategy = syncStrategyClass.getConstructor(connectionClass).newInstance(conn);
} catch (Exception e) {
Class<? extends LdapSyncStrategy> fallbackSyncStrategyClass = config.getFallbackSyncStrategyClass();
LOG.error(e, "Could not instantiate the configured {0} implementation, reverting to {1}",
LdapSyncStrategy.class.getName(), SunDSChangeLogSyncStrategy.class.getName());
syncStrategy = new SunDSChangeLogSyncStrategy(conn);
LdapSyncStrategy.class.getName(), fallbackSyncStrategyClass.getName());
try {
syncStrategy = config.getFallbackSyncStrategyClass().getConstructor(connectionClass)
.newInstance(conn);
} catch (Exception ex) {
LOG.error(e, "Could not instantiate the configured fallback {0} imeplementation, falling back to {1}",
LdapSyncStrategy.class.getName(), SunDSChangeLogSyncStrategy.class);
syncStrategy = new SunDSChangeLogSyncStrategy(conn);
}
}
}

Expand All @@ -116,7 +132,7 @@ public void checkAlive() {

@Override
public Schema schema() {
return conn.getSchemaMapping().schema();
return conn.getSchema().schema();
}

@Override
Expand All @@ -142,7 +158,7 @@ public Uid resolveUsername(
public FilterTranslator<LdapFilter> createFilterTranslator(
final ObjectClass oclass,
final OperationOptions options) {
return new LdapFilterTranslator(conn.getSchemaMapping(), oclass);
return new LdapFilterTranslator(conn.getSchema(), oclass);
}

@Override
Expand Down
Loading