summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNils Schwabe2014-04-08 12:23:58 +0200
committerNils Schwabe2014-04-08 12:23:58 +0200
commitc5c204b42ef294ecaf5ff7b048d26e117ddb8c57 (patch)
treee3aa563b42e631994818ca624796a076cbe50725
parentInitial Commit (diff)
downloadmasterserver-c5c204b42ef294ecaf5ff7b048d26e117ddb8c57.tar.gz
masterserver-c5c204b42ef294ecaf5ff7b048d26e117ddb8c57.tar.xz
masterserver-c5c204b42ef294ecaf5ff7b048d26e117ddb8c57.zip
LDAP functionallity
- added apache ldap client api to pom.xml - added the LDAP user which authenticates to the LDAP server - added testAuthentication to AppTest - users get inserted into db after authenticating - added log4j properties to filter unuseful debug messages
-rw-r--r--config/mysql.properties (renamed from config/mysql.properties.example)0
-rw-r--r--pom.xml14
-rw-r--r--src/main/java/org/openslx/imagemaster/App.java5
-rw-r--r--src/main/java/org/openslx/imagemaster/db/DbSatellite.java36
-rw-r--r--src/main/java/org/openslx/imagemaster/db/DbUser.java49
-rw-r--r--src/main/java/org/openslx/imagemaster/db/LDAPUser.java134
-rw-r--r--src/main/java/org/openslx/imagemaster/db/MySQL.java5
-rw-r--r--src/main/java/org/openslx/imagemaster/server/ApiServer.java3
-rw-r--r--src/main/java/org/openslx/imagemaster/session/Authenticator.java24
-rw-r--r--src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java5
-rw-r--r--src/main/properties/log4j.properties11
-rw-r--r--src/test/java/org/openslx/imagemaster/AppTest.java40
-rwxr-xr-xthrift-compile.sh6
13 files changed, 300 insertions, 32 deletions
diff --git a/config/mysql.properties.example b/config/mysql.properties
index a434dff..a434dff 100644
--- a/config/mysql.properties.example
+++ b/config/mysql.properties
diff --git a/pom.xml b/pom.xml
index 28192b7..5fa8390 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,14 @@
</configuration>
</plugin>
</plugins>
+ <resources>
+ <resource>
+ <directory>src/main/properties</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ </resource>
+ </resources>
</build>
<dependencies>
@@ -86,5 +94,11 @@
<version>0.6.0</version>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.directory.api</groupId>
+ <artifactId>api-all</artifactId>
+ <version>1.0.0-M21</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/src/main/java/org/openslx/imagemaster/App.java b/src/main/java/org/openslx/imagemaster/App.java
index ef04e54..8040d35 100644
--- a/src/main/java/org/openslx/imagemaster/App.java
+++ b/src/main/java/org/openslx/imagemaster/App.java
@@ -3,7 +3,6 @@ package org.openslx.imagemaster;
import java.util.ArrayList;
import java.util.List;
-import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.openslx.imagemaster.thrift.server.BinaryListener;
@@ -20,8 +19,8 @@ public class App
public static void main( String[] args )
{
// Init logging
- BasicConfigurator.configure();
- log.info( "Starting Application" );
+ log.info( "Starting Application" );
+
// Create binary listener
Thread t;
t = new Thread(new BinaryListener(), "BinaryListener");
diff --git a/src/main/java/org/openslx/imagemaster/db/DbSatellite.java b/src/main/java/org/openslx/imagemaster/db/DbSatellite.java
new file mode 100644
index 0000000..da20fbc
--- /dev/null
+++ b/src/main/java/org/openslx/imagemaster/db/DbSatellite.java
@@ -0,0 +1,36 @@
+package org.openslx.imagemaster.db;
+
+public class DbSatellite {
+ /*
+ * Get row from mysql db and
+ */
+
+ private String organization, address, name;
+
+ // needs to be public in order to be found by MySQL
+ public DbSatellite(String organization, String address, String name) {
+ this.organization = organization;
+ this.address = address;
+ this.name = name;
+ }
+
+ public static DbSatellite createDbSatellite(String organization) {
+ return MySQL
+ .findUniqueOrNull(
+ DbSatellite.class,
+ "SELECT satellite.organization, satellite.address, satellite.name FROM satellite WHERE satellite.organization = ? LIMIT 1",
+ organization);
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getOrganization() {
+ return organization;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/openslx/imagemaster/db/DbUser.java b/src/main/java/org/openslx/imagemaster/db/DbUser.java
index f8400a9..9370f40 100644
--- a/src/main/java/org/openslx/imagemaster/db/DbUser.java
+++ b/src/main/java/org/openslx/imagemaster/db/DbUser.java
@@ -1,30 +1,45 @@
package org.openslx.imagemaster.db;
+import org.apache.log4j.Logger;
+import org.openslx.imagemaster.session.Authenticator;
import org.openslx.imagemaster.session.User;
-
-public class DbUser extends User
-{
- public DbUser(String username, String password, String organization, String firstName, String lastName, String eMail,
- String satelliteAddress)
- {
- super( username, password, organization, firstName, lastName, eMail, satelliteAddress );
+public class DbUser extends User {
+ private static Logger log = Logger.getLogger( Authenticator.class );
+
+ public DbUser(String username, String password, String organization,
+ String firstName, String lastName, String eMail,
+ String satelliteAddress) {
+ super(username, password, organization, firstName, lastName, eMail,
+ satelliteAddress);
}
/**
* Query database for user with given login
- * @param login (user@organization)
- * @return instance of DbUser for matching entry from DB, or null if not found
+ *
+ * @param login
+ * (user@organization)
+ * @return instance of DbUser for matching entry from DB, or null if not
+ * found
*/
- public static DbUser forLogin( final String login )
- {
- final String[] parts = login.split( "@" );
- if ( parts.length != 2 )
+ public static DbUser forLogin(final String login) {
+ final String[] parts = login.split("@");
+ if (parts.length != 2)
return null;
- return MySQL.findUniqueOrNull( DbUser.class,
- "SELECT user.username, user.password, user.organization, user.firstname, user.lastname, user.email, satellite.address FROM user" +
- " LEFT JOIN satellite USING (organization)" +
- " WHERE user.username = ? AND user.organization = ? LIMIT 1", parts[0], parts[1] );
+ return MySQL
+ .findUniqueOrNull(
+ DbUser.class,
+ "SELECT user.username, user.password, user.organization, user.firstname, user.lastname, user.email, satellite.address FROM user"
+ + " LEFT JOIN satellite USING (organization)"
+ + " WHERE user.username = ? AND user.organization = ? LIMIT 1",
+ parts[0], parts[1]);
+ }
+
+ public static boolean insertOrUpdate(User user) {
+ log.debug("Inserted user '" + user.username + "' into db.");
+ MySQL.update("INSERT INTO user (username, password, organization, firstname, lastname, email) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE password=VALUES(password), organization=VALUES(organization), firstname=VALUES(firstname), lastname=VALUES(lastname), email=VALUES(email)",
+ user.username, user.password, user.organization, user.firstName, user.lastName, user.eMail);
+ return false;
}
}
diff --git a/src/main/java/org/openslx/imagemaster/db/LDAPUser.java b/src/main/java/org/openslx/imagemaster/db/LDAPUser.java
new file mode 100644
index 0000000..ae8d38d
--- /dev/null
+++ b/src/main/java/org/openslx/imagemaster/db/LDAPUser.java
@@ -0,0 +1,134 @@
+package org.openslx.imagemaster.db;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.openslx.imagemaster.session.User;
+import org.openslx.imagemaster.thrift.iface.AuthenticationException;
+import org.openslx.imagemaster.util.Sha512Crypt;
+
+/*
+ * This TrustManager is used to accept custom certificates.
+ */
+class MyTrustManager implements X509TrustManager {
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1)
+ throws CertificateException {}
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1)
+ throws CertificateException {}
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+}
+
+public class LDAPUser extends User {
+
+ protected LDAPUser(String username, String password, String organization,
+ String firstName, String lastName, String eMail,
+ String satelliteAddress) {
+ super(username, password, organization, firstName, lastName, eMail,
+ satelliteAddress);
+ }
+
+ /**
+ * Query LDAP for user with given login
+ * @param login (user@organization)
+ * @return instance of LDAPUser for matching entry from LDAP, or null if not found
+ */
+ @SuppressWarnings("finally")
+ public static LDAPUser forLogin( final String login, final String password ) throws AuthenticationException {
+ String username, organization, firstName, lastName, eMail, satelliteAddress;
+
+ LdapConnectionConfig ldapConfig = new LdapConnectionConfig();
+ ldapConfig.setTrustManagers(new MyTrustManager());
+ ldapConfig.setLdapPort(636);
+ ldapConfig.setLdapHost("bv1.ruf.uni-freiburg.de");
+ ldapConfig.setUseSsl(true);
+
+ LdapNetworkConnection connection = new LdapNetworkConnection( ldapConfig );
+
+ // bind connection
+ try {
+ connection.bind("uid=" + login + ",ou=people,dc=uni-freiburg,dc=de", password);
+ } catch (LdapException e1) {
+ try {
+ connection.unBind();
+ connection.close();
+ } catch (LdapException | IOException e) {
+ } finally {
+ AuthenticationException ae = new AuthenticationException();
+ ae.message = "Could not bind to LDAP server. Invalid credentials.";
+ throw ae;
+ }
+ }
+
+ // test authorization
+ if (!connection.isConnected() || !connection.isAuthenticated()) {
+ try {
+ connection.unBind();
+ connection.close();
+ } catch (LdapException | IOException e) {
+ } finally {
+ AuthenticationException ae = new AuthenticationException();
+ ae.message = "Could not connect / authenticate to LDAP server. Invalid credentials?";
+ throw ae;
+ }
+ }
+
+ // make search query
+ try {
+ EntryCursor cursor = connection.search("ou=people,dc=uni-freiburg,dc=de", "(&(objectclass=person)(uid="
+ + login + "))", SearchScope.SUBTREE);
+ // only use the first result
+ cursor.next();
+ Entry entry = cursor.get();
+ username = entry.get("uid").getString();
+ organization = "Test Organization"; // will be filled with bwIDM LDAP server
+ firstName = entry.get("givenName").getString();
+ lastName = entry.get("sn").getString();
+ eMail = entry.get("rufPreferredMail").getString();
+ // get the satellite address from db
+ DbSatellite dbSatellite = DbSatellite.createDbSatellite(organization);
+ if (dbSatellite != null) {
+ satelliteAddress = dbSatellite.getAddress();
+ } else {
+ /*
+ * Organization is not known..
+ * TODO: Handle this
+ */
+ satelliteAddress = "addressNotKown";
+ }
+ } catch (LdapException | CursorException e1) {
+ return null;
+ } finally {
+ // close connection
+ try {
+ connection.unBind();
+ } catch (LdapException e) {
+ return null;
+ }
+ try {
+ connection.close();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ return new LDAPUser(username, Sha512Crypt.Sha512_crypt(password, null, 0), organization, firstName, lastName, eMail, satelliteAddress);
+ }
+}
diff --git a/src/main/java/org/openslx/imagemaster/db/MySQL.java b/src/main/java/org/openslx/imagemaster/db/MySQL.java
index 15bf5e2..a31046d 100644
--- a/src/main/java/org/openslx/imagemaster/db/MySQL.java
+++ b/src/main/java/org/openslx/imagemaster/db/MySQL.java
@@ -76,5 +76,8 @@ class MySQL
{
return db.findUniqueOrNull( clazz, sql, args );
}
-
+
+ protected static int update(String query, Object... args) {
+ return db.update(query, args);
+ }
}
diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java
index e62b61b..dd0ec9e 100644
--- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java
+++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java
@@ -36,8 +36,7 @@ public class ApiServer
* @throws AuthenticationException if login not successful
*/
public static SessionData authenticate( String login, String password )
- throws AuthenticationException
- {
+ throws AuthenticationException {
if ( login == null || password == null ) {
throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Empty username or password!" );
}
diff --git a/src/main/java/org/openslx/imagemaster/session/Authenticator.java b/src/main/java/org/openslx/imagemaster/session/Authenticator.java
index f730c72..d1cca94 100644
--- a/src/main/java/org/openslx/imagemaster/session/Authenticator.java
+++ b/src/main/java/org/openslx/imagemaster/session/Authenticator.java
@@ -2,16 +2,17 @@ package org.openslx.imagemaster.session;
import org.apache.log4j.Logger;
import org.openslx.imagemaster.db.DbUser;
+import org.openslx.imagemaster.db.LDAPUser;
import org.openslx.imagemaster.thrift.iface.AuthenticationError;
import org.openslx.imagemaster.thrift.iface.AuthenticationException;
-import org.openslx.imagemaster.util.Sha512Crypt;
+
public class Authenticator
{
private static Logger log = Logger.getLogger( Authenticator.class );
/**
- * Authenticate the user against whatever backend... currently MySQL only
+ * Authenticate the user against whatever backend
* @param username
* @param password
* @return
@@ -19,12 +20,23 @@ public class Authenticator
*/
public static User authenticate( String username, String password ) throws AuthenticationException
{
- DbUser user = DbUser.forLogin( username );
- if ( user == null || !Sha512Crypt.verifyPassword( password, user.password ) ) {
- log.debug( "Login failed: " + username );
+// DbUser user = DbUser.forLogin( username );
+// if ( user == null || !Sha512Crypt.verifyPassword( password, user.password ) ) {
+// log.debug( "Login failed: " + username );
+// throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Invalid username or password!" );
+// }
+// log.debug( "Login successful: " + username );
+
+ LDAPUser user = LDAPUser.forLogin( username, password ); // throws exception if credentials are invalid
+ if (user == null) {
+ log.debug( "Login failed: " + username);
throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Invalid username or password!" );
}
- log.debug( "Login successful: " + username );
+ log.debug( "Login succesful: " + username );
+
+ // if successfull: update/insert into db
+ DbUser.insertOrUpdate(user);
+
return user;
}
//
diff --git a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java
index 6be5d40..c1d3aa8 100644
--- a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java
+++ b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java
@@ -1,5 +1,6 @@
package org.openslx.imagemaster.thrift.server;
+import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.openslx.imagemaster.server.ApiServer;
import org.openslx.imagemaster.thrift.iface.AuthenticationException;
@@ -10,10 +11,12 @@ import org.openslx.imagemaster.thrift.iface.UserInfo;
public class ImageServerHandler implements ImageServer.Iface
{
-
+ private static Logger log = Logger.getLogger( ApiServer.class );
+
@Override
public boolean ping() throws TException
{
+ log.debug("Ping...");
// TODO: Return false if service unavailable but running
return true;
}
diff --git a/src/main/properties/log4j.properties b/src/main/properties/log4j.properties
new file mode 100644
index 0000000..4ef8d15
--- /dev/null
+++ b/src/main/properties/log4j.properties
@@ -0,0 +1,11 @@
+log4j.rootLogger=DEBUG, A1
+
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+
+log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
+
+log4j.logger.org.apache.directory=ERROR
+log4j.logger.org.apache.mina.filter.codec.ProtocolCodecFilter=ERROR
+log4j.logger.org.apache.mina.filter.ssl=ERROR \ No newline at end of file
diff --git a/src/test/java/org/openslx/imagemaster/AppTest.java b/src/test/java/org/openslx/imagemaster/AppTest.java
index 38cff57..775d5c8 100644
--- a/src/test/java/org/openslx/imagemaster/AppTest.java
+++ b/src/test/java/org/openslx/imagemaster/AppTest.java
@@ -4,6 +4,16 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import org.apache.thrift.TException;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TProtocol;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
+import org.apache.thrift.transport.TTransportException;
+import org.openslx.imagemaster.thrift.iface.ImageServer.Client;
+import org.openslx.imagemaster.thrift.iface.SessionData;
+import org.openslx.imagemaster.thrift.iface.UserInfo;
+
/**
* Unit test for simple App.
*/
@@ -35,4 +45,34 @@ public class AppTest
{
assertTrue( true );
}
+
+ /**
+ * Test the authentication
+ */
+ public void testAuthentication() {
+ TTransport transport = new TSocket("localhost", 9090);
+ try {
+ transport.open();
+ } catch (TTransportException e) {
+ assertTrue("Could not connect", false);
+ }
+
+ TProtocol protocol = new TBinaryProtocol(transport);
+ Client client = new Client(protocol);
+
+ try {
+ assertTrue("Could not ping server", client.ping());
+ } catch (TException e) {
+ assertTrue("Could not ping server", false);
+ }
+ try {
+ SessionData sessionData = client.authenticate("ns202", "xxxxxxxxxx");
+ UserInfo userInfo = client.getUserFromToken(sessionData.getAuthToken());
+ System.out.println("User info: " + userInfo);
+ System.out.println("Server address from MySQL: " + sessionData.serverAddress);
+ } catch (TException e) {
+ e.printStackTrace();
+ assertTrue("Could not login", false);
+ }
+ }
}
diff --git a/thrift-compile.sh b/thrift-compile.sh
index 0a1099b..76be97c 100755
--- a/thrift-compile.sh
+++ b/thrift-compile.sh
@@ -1,7 +1,9 @@
#!/bin/sh
rm -r gen-java
-thrift --gen java src/main/thrift/imagemaster.thrift && \
- rm -r src/main/java/org/openslx/imagemaster/thrift/iface && \
+thrift --gen java src/main/thrift/imagemaster.thrift && {
+ rm -r src/main/java/org/openslx/imagemaster/thrift/iface
cp -r gen-java/org src/main/java/
+}
+