summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNils Schwabe2014-04-22 16:56:07 +0200
committerNils Schwabe2014-04-22 16:56:07 +0200
commit01e662bdfff823c4f5f0b6a270807fd0a3d2825f (patch)
treedaf063bc84c06781768794c17cc76f08decaa9c3
parentAdded test case for sha512crypt, removed try/catch blocks from other tests, s... (diff)
downloadmasterserver-01e662bdfff823c4f5f0b6a270807fd0a3d2825f.tar.gz
masterserver-01e662bdfff823c4f5f0b6a270807fd0a3d2825f.tar.xz
masterserver-01e662bdfff823c4f5f0b6a270807fd0a3d2825f.zip
added a method to imageserver so that finshed uploads can be signaled
did some todos from simon moved FtpCredentials creation to MasterFtpServer.java moved some options to to config file
-rw-r--r--config/global.properties.example32
-rw-r--r--src/main/java/org/openslx/imagemaster/App.java4
-rw-r--r--src/main/java/org/openslx/imagemaster/Globals.java47
-rw-r--r--src/main/java/org/openslx/imagemaster/db/ImageProcessor.java21
-rw-r--r--src/main/java/org/openslx/imagemaster/db/LdapUser.java26
-rw-r--r--src/main/java/org/openslx/imagemaster/server/ApiServer.java81
-rw-r--r--src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java53
-rw-r--r--src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java12
-rw-r--r--src/main/thrift/imagemaster.thrift17
-rw-r--r--src/test/java/org/openslx/imagemaster/AppTest.java2
10 files changed, 233 insertions, 62 deletions
diff --git a/config/global.properties.example b/config/global.properties.example
index c628288..e2e1a3b 100644
--- a/config/global.properties.example
+++ b/config/global.properties.example
@@ -1,2 +1,34 @@
# fill in properties and rename to global.properties
+
+#####################
+# Directories #
+#####################
+
+# the base dir of the ftp server (should exists)
ftp_base_dir=/tmp
+
+# the dir where the images are stored
+image_dir=/tmp
+
+#####################
+# LDAP data #
+#####################
+
+# the port of the LDAP server
+ldap_port=636
+
+# the host address of the LDAP server
+ldap_host=bv1.ruf.uni-freiburg.de
+
+# SSL usage
+ldap_ssl=true
+
+# bind query (don't forget to escape \= and use a % for the username replacement
+ldap_bind_query=uid\=%,ou\=people,dc\=uni-freiburg,dc\=de
+
+# search baseDn
+ldap_search_base_dn=ou\=people,dc\=uni-freiburg,dc\=de
+
+
+# search filter (use a % for the username replacement
+ldap_search_filter=(&(objectclass\=person)(uid\=%)) \ No newline at end of file
diff --git a/src/main/java/org/openslx/imagemaster/App.java b/src/main/java/org/openslx/imagemaster/App.java
index 3a309c5..aba2cd6 100644
--- a/src/main/java/org/openslx/imagemaster/App.java
+++ b/src/main/java/org/openslx/imagemaster/App.java
@@ -25,6 +25,10 @@ public class App {
stream = new BufferedInputStream(new FileInputStream(
"config/global.properties"));
Globals.properties.load(stream);
+ if (!Globals.propertiesValid()) {
+ log.error("Config file contains errors.");
+ System.exit(1);
+ }
} catch (IOException e) {
log.error("Could not load config file. Quitting.");
error = true;
diff --git a/src/main/java/org/openslx/imagemaster/Globals.java b/src/main/java/org/openslx/imagemaster/Globals.java
index b766b27..653e255 100644
--- a/src/main/java/org/openslx/imagemaster/Globals.java
+++ b/src/main/java/org/openslx/imagemaster/Globals.java
@@ -2,10 +2,57 @@ package org.openslx.imagemaster;
import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
import org.openslx.imagemaster.server.MasterFtpServer;
public class Globals {
public static final Properties properties = new Properties();
+
public static final MasterFtpServer ftpServer = new MasterFtpServer(2221, "admin",
"SI*HoZCC!]V)p>B2", Globals.properties.getProperty("ftp_base_dir"));
+
+ // properties
+ public static final String ftpBaseDir = "ftp_base_dir";
+ public static final String imageDir = "image_dir";
+ public static final String ldapPort = "ldap_port";
+ public static final String ldapHost = "ldap_host";
+ public static final String ldapSsl = "ldap_ssl";
+ public static final String ldapBindQuery = "ldap_bind_query";
+ public static final String ldapSearchBaseDn = "ldap_search_base_dn";
+ public static final String ldapSearchFilter = "ldap_search_filter";
+
+ public static boolean propertiesValid() {
+ if (Globals.properties.getProperty(ftpBaseDir).isEmpty()
+ || Globals.properties.getProperty(imageDir).isEmpty()
+ || Globals.properties.getProperty(ldapPort).isEmpty()
+ || Globals.properties.getProperty(ldapHost).isEmpty()
+ || Globals.properties.getProperty(ldapSsl).isEmpty()
+ || Globals.properties.getProperty(ldapBindQuery).isEmpty()
+ || Globals.properties.getProperty(ldapSearchBaseDn).isEmpty()
+ || Globals.properties.getProperty(ldapSearchBaseDn).isEmpty()
+ ) {
+ return false;
+ }
+
+ if (StringUtils.countMatches(Globals.properties.getProperty(ldapBindQuery), "%") != 1) {
+ return false;
+ }
+
+ if (StringUtils.countMatches(Globals.properties.getProperty(ldapSearchFilter), "%") != 1) {
+ return false;
+ }
+
+ // remove "/" at the end of the path
+ String ftp = Globals.properties.getProperty(ftpBaseDir);
+ if (ftp.endsWith("/")) {
+ Globals.properties.put(ftpBaseDir, ftp.substring(0, ftp.length() - 1));
+ }
+
+ String image = Globals.properties.getProperty(imageDir);
+ if (image.endsWith("/")) {
+ Globals.properties.put(imageDir, image.substring(0, image.length() -1 ));
+ }
+
+ return true;
+ }
}
diff --git a/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java b/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java
index d43b507..8c8bd8c 100644
--- a/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java
+++ b/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java
@@ -12,10 +12,18 @@ public class ImageProcessor {
private static Logger log = Logger.getLogger(ImageProcessor.class);
private static HashMap<String, ImageData> images = new HashMap<>();
- public static void processImageAfterUpload(String username, String filename) {
- /*
- * TODO: Process the image after download
- */
+
+ /**
+ * Processes an image after upload
+ * @param username the user that uploaded the file
+ * @param filename the name of the file that was uploaded (_no_ absolute path)
+ * @return
+ */
+ public static boolean processImageAfterUpload(String username, String filename) {
+ if (!images.containsKey(username)) {
+ return false;
+ }
+
log.info("Will now process '" + filename + "' from user '" + username
+ "'");
@@ -27,7 +35,7 @@ public class ImageProcessor {
if (!imageFile.exists()) {
// image file does not exist
- return;
+ return false;
}
imageFile.renameTo( new File(newFileName) );
@@ -40,6 +48,9 @@ public class ImageProcessor {
// update database
DbImage.update(images.get(username), newFileName);
log.info("Updated db: " + images.get(username).uuid);
+
+ images.remove(username);
+ return true;
}
/**
diff --git a/src/main/java/org/openslx/imagemaster/db/LdapUser.java b/src/main/java/org/openslx/imagemaster/db/LdapUser.java
index 17bf65e..1124696 100644
--- a/src/main/java/org/openslx/imagemaster/db/LdapUser.java
+++ b/src/main/java/org/openslx/imagemaster/db/LdapUser.java
@@ -14,6 +14,7 @@ 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.apache.log4j.Logger;
+import org.openslx.imagemaster.Globals;
import org.openslx.imagemaster.session.User;
import org.openslx.imagemaster.thrift.iface.AuthenticationError;
import org.openslx.imagemaster.thrift.iface.AuthenticationException;
@@ -63,24 +64,27 @@ public class LdapUser extends User
* @param login Login of user in the form "user@organization.com"
* @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;
+ String username, organization, firstName, lastName, eMail, satelliteAddress;
+
+ String[] temp = login.split("@");
+ if (temp.length != 2) throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Login must be in form user@organization.com");
+ username = temp[0];
- // TODO: Read connection info from config file
LdapConnectionConfig ldapConfig = new LdapConnectionConfig();
ldapConfig.setTrustManagers(new MyTrustManager());
- ldapConfig.setLdapPort(636);
- ldapConfig.setLdapHost("bv1.ruf.uni-freiburg.de");
- ldapConfig.setUseSsl(true);
+ ldapConfig.setLdapPort(Integer.valueOf(Globals.properties.getProperty(Globals.ldapPort)));
+ ldapConfig.setLdapHost(Globals.properties.getProperty(Globals.ldapHost));
+ ldapConfig.setUseSsl(Boolean.valueOf(Globals.properties.getProperty(Globals.ldapSsl)));
LdapNetworkConnection connection = new LdapNetworkConnection( ldapConfig );
// bind connection
- // TODO: Hard coded stuff here too. binddn, search query etc. need to be configurable
try {
- if ( connection.connect() )
- connection.bind("uid=" + login + ",ou=people,dc=uni-freiburg,dc=de", password);
+ if ( connection.connect() ) {
+ String name = Globals.properties.getProperty(Globals.ldapBindQuery).replace("%", username);
+ connection.bind(name, password);
+ }
} catch (LdapException e1) {
log.warn( "Connection to LDAP failed: " + e1.getMessage() );
}
@@ -108,8 +112,8 @@ public class LdapUser extends User
// make search query
try {
- EntryCursor cursor = connection.search("ou=people,dc=uni-freiburg,dc=de", "(&(objectclass=person)(uid="
- + login + "))", SearchScope.SUBTREE);
+ EntryCursor cursor = connection.search(Globals.properties.getProperty(Globals.ldapSearchBaseDn),
+ Globals.properties.getProperty(Globals.ldapSearchFilter).replace("%", username), SearchScope.SUBTREE);
// only use the first result
cursor.next();
Entry entry = cursor.get();
diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java
index eda48eb..fc1d9b0 100644
--- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java
+++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java
@@ -1,7 +1,9 @@
package org.openslx.imagemaster.server;
import java.io.File;
+import java.util.HashMap;
+import org.apache.ftpserver.ftplet.FtpException;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.openslx.imagemaster.Globals;
@@ -17,10 +19,13 @@ import org.openslx.imagemaster.session.SessionManager;
import org.openslx.imagemaster.session.User;
import org.openslx.imagemaster.thrift.iface.AuthenticationError;
import org.openslx.imagemaster.thrift.iface.AuthenticationException;
+import org.openslx.imagemaster.thrift.iface.AuthorizationError;
import org.openslx.imagemaster.thrift.iface.AuthorizationException;
import org.openslx.imagemaster.thrift.iface.FtpCredentials;
import org.openslx.imagemaster.thrift.iface.ImageData;
import org.openslx.imagemaster.thrift.iface.InvalidTokenException;
+import org.openslx.imagemaster.thrift.iface.ServerAuthenticationError;
+import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException;
import org.openslx.imagemaster.thrift.iface.ServerSessionData;
import org.openslx.imagemaster.thrift.iface.SessionData;
import org.openslx.imagemaster.thrift.iface.UserInfo;
@@ -85,29 +90,22 @@ public class ApiServer {
* @throws AuthorizationException if the uni/hs server has no valid session
* @throws TException
*/
- public static FtpCredentials submitImage(ImageData imageDescription,
- ServerSessionData serverSessionData) throws AuthorizationException,
+ public static FtpCredentials submitImage(String serverSessionId,
+ ImageData imageDescription) throws AuthorizationException,
TException {
- if (ServerSessionManager.getSession(serverSessionData.sessionId) == null) {
- throw new AuthenticationException(AuthenticationError.GENERIC_ERROR, "No valid serverSessionData");
+ if (ServerSessionManager.getSession(serverSessionId) == null) {
+ throw new AuthorizationException(AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData");
}
- String generatedUser = RandomString.generate(10, false);
- String generatedPass = RandomString.generate(16, true);
+ // create new user
+ FtpCredentials ftpCredentials = Globals.ftpServer.addUser(serverSessionId);
- if (!ImageProcessor.addImageDataToProcess(imageDescription, generatedUser)) {
+ if (!ImageProcessor.addImageDataToProcess(imageDescription, ftpCredentials.username)) {
+ Globals.ftpServer.removeUser(serverSessionId);
throw new TException("ImageData is not valid.");
}
-
- String dir = Globals.properties.getProperty("ftp_base_dir") + "/"
- + generatedUser + "/";
- if (new File(dir).mkdir()) {
- Globals.ftpServer.addUser(generatedUser, generatedPass, dir, true);
- log.info("Generated user/pass: " + generatedUser + "\t"
- + generatedPass + "\n with home dir: " + dir);
- }
-
- return new FtpCredentials(generatedUser, generatedPass);
+
+ return ftpCredentials;
}
/**
@@ -115,16 +113,15 @@ public class ApiServer {
* @param organization the organization that the server belongs to
* @return a random string that needs to be encrypted with the private
* key of the requesting satellite server
- * @throws TException
+ * @throws ServerAuthenticationException when organization is invalid/unknown
*/
public static String startServerAuthentication(String organization)
- throws TException {
- // TODO: Proper exceptions
+ throws ServerAuthenticationException {
if (organization == null || organization == "") {
- throw new TException("Empty organization");
+ throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization");
}
if (DbSatellite.fromOrganization(organization) == null) {
- throw new TException("Unkown organization");
+ throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization");
}
return ServerAuthenticator.startServerAuthentication(organization);
}
@@ -140,13 +137,12 @@ public class ApiServer {
public static ServerSessionData serverAuthenticate(String organization,
String challengeResponse) throws AuthenticationException,
TException {
- // TODO: Proper exceptions
if (organization == null || challengeResponse == null) {
- throw new TException("Empty organization org challengeResponse");
+ throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization or challengeResponse");
}
DbSatellite satellite = DbSatellite.fromOrganization(organization);
if (satellite == null) {
- throw new TException("Unkown organization");
+ throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization");
}
final ServerUser serverUser = ServerAuthenticator.serverAuthenticate(
organization, satellite.getAddress(), challengeResponse);
@@ -155,4 +151,39 @@ public class ApiServer {
return ServerSessionManager.addSession(session);
}
+ /**
+ * Tell the masterserver that the image upload finished.
+ * @param serverSessionId The session id of the hs/uni server
+ * @param imageDescription the description of the uploaded image
+ * @return if nothing went wrong
+ * @throws AuthorizationException if no valid session exists
+ */
+ public static boolean finishedUpload(String serverSessionId,
+ ImageData imageDescription) throws AuthorizationException {
+ // check if valid session exists
+ if (ServerSessionManager.getSession(serverSessionId) == null) {
+ throw new AuthorizationException(AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData");
+ }
+
+ // process the image
+ String username = Globals.ftpServer.getCredentialsFromSessionId(serverSessionId).username;
+
+ File userDirectory = new File(Globals.properties.getProperty(Globals.ftpBaseDir) + "/" + username);
+ File[] list = userDirectory.listFiles();
+
+ if (list.length != 1) return false;
+
+ log.info(username + " is done with upload");
+
+ // remove user that is not needed anymore
+ Globals.ftpServer.removeUser(username);
+ log.info("Removed user: " + username);
+
+ ImageProcessor.processImageAfterUpload(username, list[0].getName());
+
+ Globals.ftpServer.removeUser(serverSessionId);
+
+ return true;
+ }
+
}
diff --git a/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java b/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java
index 973c768..c6592bc 100644
--- a/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java
+++ b/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java
@@ -17,11 +17,15 @@ import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import org.apache.log4j.Logger;
+import org.openslx.imagemaster.Globals;
+import org.openslx.imagemaster.thrift.iface.FtpCredentials;
+import org.openslx.imagemaster.util.RandomString;
public class MasterFtpServer implements Runnable {
private static Logger log = Logger.getLogger( MasterFtpServer.class );
private FtpServer server;
private UserManager userManager;
+ private HashMap<String, FtpCredentials> users = new HashMap<>();
public MasterFtpServer(int port, String adminUsername, String adminPassword, String ftproot) {
FtpServerFactory serverFactory = new FtpServerFactory();
@@ -39,7 +43,7 @@ public class MasterFtpServer implements Runnable {
userManager = userManagerFactory.createUserManager();
// create new admin user
- addUser(adminUsername, adminPassword, ftproot, true);
+ //addUser(adminUsername, adminPassword, ftproot, true);
serverFactory.setUserManager(userManager);
// add the Ftplet
@@ -51,38 +55,57 @@ public class MasterFtpServer implements Runnable {
server = serverFactory.createServer();
}
- public boolean addUser(final String username, final String password, final String ftproot, final boolean writeAccess) {
+ public FtpCredentials addUser(final String serverSessionId) {
// TODO: enable SSL
- boolean result = true;
+
+ FtpCredentials ftpCredentials = null;
+
+ String generatedUser = RandomString.generate(10, false);
+ String generatedPass = RandomString.generate(16, true);
+
+ String dir = Globals.properties.getProperty(Globals.ftpBaseDir) + "/"
+ + generatedUser + "/";
+
+ if (!new File(dir).mkdir()) {
+ return ftpCredentials;
+ }
BaseUser user = new BaseUser();
- user.setName(username);
- user.setPassword(password);
- user.setHomeDirectory(ftproot);
+ user.setName(generatedUser);
+ user.setPassword(generatedPass);
+ user.setHomeDirectory(dir);
List<Authority> authorities = new ArrayList<Authority>();
- if (writeAccess) authorities.add(new WritePermission());
+ authorities.add(new WritePermission());
user.setAuthorities(authorities);
try {
userManager.save(user);
+ ftpCredentials = new FtpCredentials(generatedUser, generatedPass);
+ users.put(serverSessionId, ftpCredentials);
} catch (FtpException e) {
- result = false;
}
- return result;
+ log.info("Generated user/pass: " + generatedUser + "\t"
+ + generatedPass + "\n with home dir: " + dir);
+
+ return ftpCredentials;
}
- public boolean removeUser(final String username) {
- boolean result = true;
+ public boolean removeUser(final String serverSessionId) {
+ if (!users.containsKey(serverSessionId)) return false;
try {
- userManager.delete(username);
+ userManager.delete(users.get(serverSessionId).username);
+ users.remove(serverSessionId);
+ return true;
} catch (FtpException e) {
- result = false;
+ return false;
}
-
- return result;
+ }
+
+ public FtpCredentials getCredentialsFromSessionId(String serverSessionId) {
+ return users.get(serverSessionId);
}
@Override
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 096f63f..899af1a 100644
--- a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java
+++ b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java
@@ -53,10 +53,16 @@ public class ImageServerHandler implements ImageServer.Iface
}
@Override
- public FtpCredentials submitImage(ImageData imageDescription,
- ServerSessionData serverSessionData) throws AuthorizationException,
+ public FtpCredentials submitImage(String serverSessionId,
+ ImageData imageDescription) throws AuthorizationException,
TException {
- return ApiServer.submitImage(imageDescription, serverSessionData);
+ return ApiServer.submitImage(serverSessionId, imageDescription);
+ }
+
+ @Override
+ public boolean finshedUpload(String serverSessionId,
+ ImageData imageDescription) throws AuthorizationException {
+ return ApiServer.finishedUpload(serverSessionId, imageDescription);
}
}
diff --git a/src/main/thrift/imagemaster.thrift b/src/main/thrift/imagemaster.thrift
index a164e9b..fdf63ee 100644
--- a/src/main/thrift/imagemaster.thrift
+++ b/src/main/thrift/imagemaster.thrift
@@ -23,6 +23,12 @@ enum AuthenticationError {
BANNED_NETWORK
}
+enum ServerAuthenticationError {
+ GENERIC_ERROR,
+ INVALID_ORGANIZATION,
+ BANNED_NETWORK,
+}
+
exception AuthorizationException {
1: AuthorizationError number,
2: string message
@@ -36,6 +42,11 @@ exception AuthenticationException {
exception InvalidTokenException {
}
+exception ServerAuthenticationException {
+ 1: ServerAuthenticationError number,
+ 2: string message
+}
+
struct UserInfo {
1: string userId,
2: string firstName,
@@ -82,9 +93,11 @@ service ImageServer {
string startServerAuthentication(1:string organization),
- ServerSessionData serverAuthenticate(1:string organization, 2:string challengeResponse) throws (1:AuthenticationException failure),
+ ServerSessionData serverAuthenticate(1:string organization, 2:string challengeResponse) throws (1:ServerAuthenticationException failure),
+
+ FtpCredentials submitImage(1:string serverSessionId, 2:ImageData imageDescription) throws (1:AuthorizationException failure),
- FtpCredentials submitImage(1:ImageData imageDescription, 2:ServerSessionData serverSessionData) throws (1:AuthorizationException failure)
+ bool finshedUpload(1:string serverSessionId, 2:ImageData imageDescription) throws (1:AuthorizationException failure)
}
diff --git a/src/test/java/org/openslx/imagemaster/AppTest.java b/src/test/java/org/openslx/imagemaster/AppTest.java
index 120bd9e..a491242 100644
--- a/src/test/java/org/openslx/imagemaster/AppTest.java
+++ b/src/test/java/org/openslx/imagemaster/AppTest.java
@@ -122,7 +122,7 @@ public class AppTest
System.out.println("Created imageData");
- FtpCredentials ftpCredentials = client.submitImage(imageData, data);
+ FtpCredentials ftpCredentials = client.submitImage(data.sessionId, imageData);
System.out.println("Got FTP credentials. User: " + ftpCredentials.username + ", password: " + ftpCredentials.password);
FTPClient FtpClient = new FTPClient();