-
Notifications
You must be signed in to change notification settings - Fork 392
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* CB-931 ldap identity provider * CB-931 add bruteforce protection to ldap --------- Co-authored-by: Evgenia Bezborodova <[email protected]>
- Loading branch information
1 parent
7cd22a8
commit 72ce16b
Showing
12 changed files
with
440 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
...les/io.cloudbeaver.model/src/io/cloudbeaver/auth/provider/fa/AbstractSessionExternal.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* DBeaver - Universal Database Manager | ||
* Copyright (C) 2010-2024 DBeaver Corp and others | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package io.cloudbeaver.auth.provider.fa; | ||
|
||
import org.jkiss.code.NotNull; | ||
import org.jkiss.code.Nullable; | ||
import org.jkiss.dbeaver.model.auth.*; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.Map; | ||
|
||
public abstract class AbstractSessionExternal implements SMSessionExternal { | ||
|
||
@NotNull | ||
protected final Map<String, Object> authParameters; | ||
@NotNull | ||
protected final SMSession parentSession; | ||
@NotNull | ||
protected final SMAuthSpace space; | ||
|
||
protected AbstractSessionExternal( | ||
@NotNull SMSession parentSession, | ||
@NotNull SMAuthSpace space, | ||
@NotNull Map<String, Object> authParameters | ||
) { | ||
this.parentSession = parentSession; | ||
this.space = space; | ||
this.authParameters = authParameters; | ||
} | ||
|
||
@NotNull | ||
@Override | ||
public SMAuthSpace getSessionSpace() { | ||
return space; | ||
} | ||
|
||
@NotNull | ||
@Override | ||
public SMSessionContext getSessionContext() { | ||
return this.parentSession.getSessionContext(); | ||
} | ||
|
||
@Nullable | ||
@Override | ||
public SMSessionPrincipal getSessionPrincipal() { | ||
return parentSession.getSessionPrincipal(); | ||
} | ||
|
||
@NotNull | ||
@Override | ||
public LocalDateTime getSessionStart() { | ||
return parentSession.getSessionStart(); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
// do nothing | ||
} | ||
|
||
@Override | ||
public Map<String, Object> getAuthParameters() { | ||
return authParameters; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
server/bundles/io.cloudbeaver.service.ldap.auth/META-INF/MANIFEST.MF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Manifest-Version: 1.0 | ||
Bundle-ManifestVersion: 2 | ||
Bundle-Vendor: Cloudbeaver LDAP | ||
Bundle-Vendor: DBeaver Corp | ||
Bundle-SymbolicName: io.cloudbeaver.service.ldap.auth;singleton:=true | ||
Bundle-Version: 1.0.0.qualifier | ||
Bundle-Release-Date: 20240506 | ||
Bundle-RequiredExecutionEnvironment: JavaSE-17 | ||
Bundle-ActivationPolicy: lazy | ||
Bundle-ClassPath: . | ||
Require-Bundle: org.jkiss.dbeaver.model;visibility:=reexport, | ||
org.jkiss.dbeaver.registry;visibility:=reexport, | ||
io.cloudbeaver.model | ||
Automatic-Module-Name: io.cloudbeaver.service.ldap.auth |
5 changes: 5 additions & 0 deletions
5
server/bundles/io.cloudbeaver.service.ldap.auth/build.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
source.. = src/ | ||
output.. = target/classes/ | ||
bin.includes = .,\ | ||
META-INF/,\ | ||
plugin.xml |
31 changes: 31 additions & 0 deletions
31
server/bundles/io.cloudbeaver.service.ldap.auth/plugin.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<?eclipse version="3.2"?> | ||
|
||
<plugin> | ||
<extension point="org.jkiss.dbeaver.auth.provider"> | ||
<authProvider id="ldap" label="LDAP" description="LDAP authentication provider" | ||
configurable="true" | ||
class="io.cloudbeaver.service.ldap.auth.LdapAuthProvider" | ||
icon="platform:/plugin/org.jkiss.dbeaver.model/icons/idp/ldap.png" | ||
> | ||
<configuration> | ||
<propertyGroup label="LDAP" description="LDAP authentication"> | ||
<property id="ldap-host" label="Host" type="string" description="LDAP server host" required="true"/> | ||
<property id="ldap-port" label="Port" type="integer" defaultValue="389" required="true" description="LDAP server port, default is 389"/> | ||
<property id="ldap-dn" label="Base Distinguished Name" type="string" | ||
description="Base Distinguished Name applicable for all users, example: dc=myOrg,dc=com" | ||
required="true" | ||
/> | ||
</propertyGroup> | ||
</configuration> | ||
<credentials> | ||
<propertyGroup label="Auth credentials"> | ||
<property id="units" label="Unit paths" type="string" description="LDAP unit paths separated by commas. Example ou=unit1,ou=unit2" user="true"/> | ||
<property id="user" label="User name" type="string" description="LDAP user name" user="true"/> | ||
<property id="password" label="User password" type="string" description="LDAP user password" | ||
user="true" encryption="plain"/> | ||
</propertyGroup> | ||
</credentials> | ||
</authProvider> | ||
</extension> | ||
</plugin> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | ||
xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>io.cloudbeaver</groupId> | ||
<artifactId>bundles</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
<relativePath>../</relativePath> | ||
</parent> | ||
<artifactId>io.cloudbeaver.service.ldap.auth</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
<packaging>eclipse-plugin</packaging> | ||
|
||
</project> |
166 changes: 166 additions & 0 deletions
166
....cloudbeaver.service.ldap.auth/src/io/cloudbeaver/service/ldap/auth/LdapAuthProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/* | ||
* DBeaver - Universal Database Manager | ||
* Copyright (C) 2010-2024 DBeaver Corp and others | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.cloudbeaver.service.ldap.auth; | ||
|
||
import io.cloudbeaver.DBWUserIdentity; | ||
import io.cloudbeaver.auth.SMAuthProviderExternal; | ||
import io.cloudbeaver.auth.SMBruteForceProtected; | ||
import io.cloudbeaver.auth.provider.local.LocalAuthProviderConstants; | ||
import io.cloudbeaver.model.session.WebSession; | ||
import io.cloudbeaver.model.user.WebUser; | ||
import org.jkiss.code.NotNull; | ||
import org.jkiss.code.Nullable; | ||
import org.jkiss.dbeaver.DBException; | ||
import org.jkiss.dbeaver.model.DBPObject; | ||
import org.jkiss.dbeaver.model.auth.SMSession; | ||
import org.jkiss.dbeaver.model.data.json.JSONUtils; | ||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; | ||
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration; | ||
import org.jkiss.dbeaver.model.security.SMController; | ||
import org.jkiss.utils.CommonUtils; | ||
|
||
import javax.naming.Context; | ||
import javax.naming.directory.DirContext; | ||
import javax.naming.directory.InitialDirContext; | ||
import java.util.HashMap; | ||
import java.util.Hashtable; | ||
import java.util.Map; | ||
import java.util.UUID; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
public class LdapAuthProvider implements SMAuthProviderExternal<SMSession>, SMBruteForceProtected { | ||
public LdapAuthProvider() { | ||
} | ||
|
||
@Override | ||
public Map<String, Object> authExternalUser( | ||
@NotNull DBRProgressMonitor monitor, | ||
@Nullable SMAuthProviderCustomConfiguration providerConfig, | ||
@NotNull Map<String, Object> authParameters | ||
) throws DBException { | ||
if (providerConfig == null) { | ||
throw new DBException("LDAP provider config is null"); | ||
} | ||
String userName = JSONUtils.getString(authParameters, LdapConstants.CRED_USERNAME); | ||
if (CommonUtils.isEmpty(userName)) { | ||
throw new DBException("LDAP user name is empty"); | ||
} | ||
String password = JSONUtils.getString(authParameters, LdapConstants.CRED_PASSWORD); | ||
if (CommonUtils.isEmpty(password)) { | ||
throw new DBException("LDAP password is empty"); | ||
} | ||
String unit = CommonUtils.nullIfEmpty(JSONUtils.getString(authParameters, LdapConstants.CRED_UNITS)); | ||
|
||
LdapSettings ldapSettings = new LdapSettings(providerConfig); | ||
Hashtable<String, String> environment = new Hashtable<>(); | ||
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); | ||
|
||
var ldapProviderUrl = "ldap://" + ldapSettings.getHost() + ":" + ldapSettings.getPort(); | ||
environment.put(Context.PROVIDER_URL, ldapProviderUrl); | ||
environment.put(Context.SECURITY_AUTHENTICATION, "simple"); | ||
|
||
String cn = "cn=" + userName; | ||
var principal = Stream.of(cn, unit, ldapSettings.getBaseDN()) | ||
.filter(CommonUtils::isNotEmpty) | ||
.collect(Collectors.joining(",")); | ||
|
||
environment.put(Context.SECURITY_PRINCIPAL, principal); | ||
environment.put(Context.SECURITY_CREDENTIALS, password); | ||
try { | ||
DirContext context = new InitialDirContext(environment); | ||
context.close(); | ||
Map<String, Object> userData = new HashMap<>(); | ||
userData.put(LdapConstants.CRED_USERNAME, userName); | ||
userData.put(LdapConstants.CRED_SESSION_ID, UUID.randomUUID()); | ||
return userData; | ||
} catch (Exception e) { | ||
throw new DBException("LDAP authentication failed: " + e.getMessage(), e); | ||
} | ||
} | ||
|
||
@NotNull | ||
@Override | ||
public DBWUserIdentity getUserIdentity( | ||
@NotNull DBRProgressMonitor monitor, | ||
@Nullable SMAuthProviderCustomConfiguration customConfiguration, | ||
@NotNull Map<String, Object> authParameters | ||
) throws DBException { | ||
String userName = JSONUtils.getString(authParameters, LocalAuthProviderConstants.CRED_USER); | ||
if (CommonUtils.isEmpty(userName)) { | ||
throw new DBException("LDAP user name is empty"); | ||
} | ||
return new DBWUserIdentity(userName, userName); | ||
} | ||
|
||
@Nullable | ||
@Override | ||
public DBPObject getUserDetails( | ||
@NotNull DBRProgressMonitor monitor, | ||
@NotNull WebSession webSession, | ||
@NotNull SMSession session, | ||
@NotNull WebUser user, | ||
boolean selfIdentity | ||
) throws DBException { | ||
return null; | ||
} | ||
|
||
@NotNull | ||
@Override | ||
public String validateLocalAuth( | ||
@NotNull DBRProgressMonitor monitor, | ||
@NotNull SMController securityController, | ||
@NotNull SMAuthProviderCustomConfiguration providerConfig, | ||
@NotNull Map<String, Object> userCredentials, | ||
@Nullable String activeUserId | ||
) throws DBException { | ||
String userId = JSONUtils.getString(userCredentials, LdapConstants.CRED_USERNAME); | ||
if (CommonUtils.isEmpty(userId)) { | ||
throw new DBException("LDAP user id not found"); | ||
} | ||
return activeUserId == null ? userId : activeUserId; | ||
} | ||
|
||
@Override | ||
public SMSession openSession( | ||
@NotNull DBRProgressMonitor monitor, | ||
@NotNull SMSession mainSession, | ||
@Nullable SMAuthProviderCustomConfiguration customConfiguration, | ||
@NotNull Map<String, Object> userCredentials | ||
) throws DBException { | ||
return new LdapSession(mainSession, mainSession.getSessionSpace(), userCredentials); | ||
} | ||
|
||
@Override | ||
public void closeSession(@NotNull SMSession mainSession, SMSession session) throws DBException { | ||
|
||
} | ||
|
||
@Override | ||
public void refreshSession( | ||
@NotNull DBRProgressMonitor monitor, | ||
@NotNull SMSession mainSession, | ||
SMSession session | ||
) throws DBException { | ||
|
||
} | ||
|
||
@Override | ||
public Object getInputUsername(@NotNull Map<String, Object> cred) { | ||
return cred.get(LdapConstants.CRED_USERNAME); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
.../io.cloudbeaver.service.ldap.auth/src/io/cloudbeaver/service/ldap/auth/LdapConstants.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* DBeaver - Universal Database Manager | ||
* Copyright (C) 2010-2024 DBeaver Corp and others | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.cloudbeaver.service.ldap.auth; | ||
|
||
public interface LdapConstants { | ||
String PARAM_HOST = "ldap-host"; | ||
String PARAM_PORT = "ldap-port"; | ||
String PARAM_DN = "ldap-dn"; | ||
|
||
|
||
String CRED_USERNAME = "user"; | ||
String CRED_PASSWORD = "password"; | ||
String CRED_UNITS = "units"; | ||
String CRED_SESSION_ID = "session-id"; | ||
} |
41 changes: 41 additions & 0 deletions
41
...es/io.cloudbeaver.service.ldap.auth/src/io/cloudbeaver/service/ldap/auth/LdapSession.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* DBeaver - Universal Database Manager | ||
* Copyright (C) 2010-2024 DBeaver Corp and others | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.cloudbeaver.service.ldap.auth; | ||
|
||
import io.cloudbeaver.auth.provider.fa.AbstractSessionExternal; | ||
import org.jkiss.code.NotNull; | ||
import org.jkiss.dbeaver.model.auth.SMAuthSpace; | ||
import org.jkiss.dbeaver.model.auth.SMSession; | ||
import org.jkiss.dbeaver.model.data.json.JSONUtils; | ||
|
||
import java.util.Map; | ||
|
||
public class LdapSession extends AbstractSessionExternal { | ||
protected LdapSession( | ||
@NotNull SMSession parentSession, | ||
@NotNull SMAuthSpace space, | ||
@NotNull Map<String, Object> authParameters | ||
) { | ||
super(parentSession, space, authParameters); | ||
} | ||
|
||
@NotNull | ||
@Override | ||
public String getSessionId() { | ||
return JSONUtils.getString(authParameters, LdapConstants.CRED_SESSION_ID, "sessionNotFound"); | ||
} | ||
} |
Oops, something went wrong.