diff options
author | Simon Rettberg | 2015-07-15 17:33:19 +0200 |
---|---|---|
committer | Simon Rettberg | 2015-07-15 17:33:19 +0200 |
commit | 2987d0992a0609a3c9eb23048d87df630225b978 (patch) | |
tree | 4f9a778563b2da0316bc3e637d2dd31ee5280b70 /dozentenmodulserver | |
parent | [cilent] check if vmdk parsed from vmx is relative or absolute and do proper ... (diff) | |
download | tutor-module-2987d0992a0609a3c9eb23048d87df630225b978.tar.gz tutor-module-2987d0992a0609a3c9eb23048d87df630225b978.tar.xz tutor-module-2987d0992a0609a3c9eb23048d87df630225b978.zip |
Adapt to changed thrift api for improved session validation
Diffstat (limited to 'dozentenmodulserver')
9 files changed, 177 insertions, 31 deletions
diff --git a/dozentenmodulserver/setup/sat-01-schema.sql b/dozentenmodulserver/setup/sat-01-schema.sql index e07156f8..bb4a4e5c 100644 --- a/dozentenmodulserver/setup/sat-01-schema.sql +++ b/dozentenmodulserver/setup/sat-01-schema.sql @@ -114,7 +114,7 @@ CREATE TABLE IF NOT EXISTS `imageversion` ( `isvalid` tinyint(1) NOT NULL, `isprocessed` tinyint(1) NOT NULL, `mastersha1` binary(20) DEFAULT NULL, - `virtualizerconfig` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT 'Specific configuration of the virtualizer for this image. For vmware, this is basically a dump of the *.vmx.', + `virtualizerconfig` text BINARY NULL DEFAULT NULL COMMENT 'Specific configuration of the virtualizer for this image. For vmware, this is basically a dump of the *.vmx.', PRIMARY KEY (`imageversionid`), KEY `version_access` (`imagebaseid`,`isenabled`,`isvalid`,`createtime`), KEY `fk_imageversion_2_idx` (`uploaderid`), diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java index 992d5562..570cf1fa 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java @@ -55,6 +55,7 @@ public class App { ThriftManager.setMasterServerAddress("bwlp-masterserver.ruf.uni-freiburg.de"); // Load useful things from master server + //LOGGER.info(ThriftManager.getMasterClient().getUserFromToken("9ECAC1AFC02FF295292362BD165847AE")); OrganizationList.get(); OperatingSystemList.get(); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java index fc78a5aa..3f392048 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java @@ -70,10 +70,10 @@ public class DbImage { public static ImageDetailsRead getImageDetails(UserInfo user, String imageBaseId) throws TNotFoundException, SQLException { try (MysqlConnection connection = Database.getConnection()) { - MysqlStatement stmt = connection.prepareStatement("SELECT imagebaseid, currentversionid, latestversionid," - + " displayname, description, osid, virtid, createtime, updatetime, ownerid, updaterid," - + " sharemode, istemplate," - + " canlinkdefault, candownloaddefault, caneditdefault, canadmindefault," + MysqlStatement stmt = connection.prepareStatement("SELECT i.imagebaseid, i.currentversionid, i.latestversionid," + + " i.displayname, i.description, i.osid, i.virtid, i.createtime, i.updatetime, i.ownerid, i.updaterid," + + " i.sharemode, i.istemplate," + + " i.canlinkdefault, i.candownloaddefault, i.caneditdefault, i.canadmindefault," + " perm.canlink, perm.candownload, perm.canedit, perm.canadmin" + " FROM imagebase i" + " LEFT JOIN imagepermission perm ON (i.imagebaseid = perm.imagebaseid AND perm.userid = :userid)" @@ -95,7 +95,7 @@ public class DbImage { toShareMode(rs.getString("sharemode")), rs.getByte("istemplate") != 0, defaultPermissions); return image; } catch (SQLException e) { - LOGGER.error("Query failed in DbImage.getImage()", e); + LOGGER.error("Query failed in DbImage.getImageDetails()", e); throw e; } } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOsVirt.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOsVirt.java index e092e944..f49c9065 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOsVirt.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbOsVirt.java @@ -3,13 +3,16 @@ package org.openslx.bwlp.sat.database.mappers; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; import org.openslx.bwlp.sat.database.Database; import org.openslx.bwlp.sat.database.MysqlConnection; import org.openslx.bwlp.sat.database.MysqlStatement; import org.openslx.bwlp.thrift.iface.OperatingSystem; +import org.openslx.bwlp.thrift.iface.Virtualizer; public class DbOsVirt { @@ -29,20 +32,22 @@ public class DbOsVirt { } connection.commit(); } catch (SQLException e) { - LOGGER.error("Query failed in DbOsVirt.writeOsList()", e); + LOGGER.error("Query failed in DbOsVirt.storeOsList()", e); throw e; } } public static List<OperatingSystem> getOsList() throws SQLException { try (MysqlConnection connection = Database.getConnection()) { + // Query OSs MysqlStatement stmt = connection.prepareStatement("SELECT osid, displayname, architecture" + " FROM operatingsystem"); ResultSet rs = stmt.executeQuery(); List<OperatingSystem> list = new ArrayList<>(); + Map<Integer, Map<String, String>> osVirtMappings = getOsVirtMappings(connection); while (rs.next()) { - // TODO: virt mapping - list.add(new OperatingSystem(rs.getInt("osid"), rs.getString("displayname"), null, + int osId = rs.getInt("osid"); + list.add(new OperatingSystem(osId, rs.getString("displayname"), osVirtMappings.get(osId), rs.getString("architecture"))); } return list; @@ -51,5 +56,55 @@ public class DbOsVirt { throw e; } } + + private static Map<Integer, Map<String, String>> getOsVirtMappings(MysqlConnection connection) throws SQLException { + MysqlStatement stmt = connection.prepareStatement("SELECT osid, virtid, virtoskeyword FROM os_x_virt"); + ResultSet rs = stmt.executeQuery(); + Map<Integer, Map<String, String>> map = new HashMap<>(); + while (rs.next()) { + Integer osId = rs.getInt("osid"); + Map<String, String> osMap = map.get(osId); + if (osMap == null) { + osMap = new HashMap<>(); + map.put(osId, osMap); + } + osMap.put(rs.getString("virtid"), rs.getString("virtoskeyword")); + } + return map; + } + + public static void storeVirtualizerList(List<Virtualizer> list) throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("INSERT INTO virtualizer" + + " (virtid, virtname) VALUES" + + " (:virtid, :virtname)" + + " ON DUPLICATE KEY UPDATE virtname = VALUES(virtname)"); + for (Virtualizer virt : list) { + stmt.setString("virtid", virt.virtId); + stmt.setString("displayname", virt.virtName); + stmt.executeUpdate(); + } + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in DbOsVirt.storeVirtualizerList()", e); + throw e; + } + } + + public static List<Virtualizer> getVirtualizerList() throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("SELECT virtid, virtname" + + " FROM virtualizer"); + ResultSet rs = stmt.executeQuery(); + List<Virtualizer> list = new ArrayList<>(); + while (rs.next()) { + list.add(new Virtualizer(rs.getString("virtid"), rs.getString("virtname"))); + } + return list; + } catch (SQLException e) { + LOGGER.error("Query failed in DbOsVirt.getVirtualizerList()", e); + throw e; + } + } } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java index 86660ac1..34fc6cce 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/User.java @@ -41,29 +41,32 @@ public class User { * Check if given user is allowed to login to this satellite. * * @param user user to check login permission for - * @return true if user is allowed to login to this satellite + * @return null if user is allowed, {@link AuthorizationError} otherwise */ - public static boolean canLogin(UserInfo user) { + public static AuthorizationError canLogin(UserInfo user) { LocalUser localData = LocalData.getLocalUser(user); - if (localData != null) - return localData.canLogin; // User locally known, use user-specific permission + if (localData != null) { + if (localData.canLogin) + return null; // User locally known, use user-specific permission + return AuthorizationError.ACCOUNT_SUSPENDED; + } LocalOrganization local = LocalData.getLocalOrganization(user.organizationId); // User unknown, check per-organization login permission if (local == null) - return false; + return AuthorizationError.INVALID_ORGANIZATION; if (local.canLogin) - return true; + return null; // Special case: If user is not allowed to login, check if there are no allowed // organizations yet. If so, automatically allow the organization of this user. try { if (DbOrganization.getLoginAllowedOrganizations().isEmpty()) { DbOrganization.setCanLogin(user.organizationId, true); - return true; + return null; } } catch (SQLException e) { // Ignore } - return false; + return AuthorizationError.GENERIC_ERROR; } /** diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/BinaryListener.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/BinaryListener.java index 70c47edb..3e0159b6 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/BinaryListener.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/BinaryListener.java @@ -49,9 +49,9 @@ public class BinaryListener implements Runnable { final TNonblockingServerTransport serverTransport; try { serverTransport = new TNonblockingServerSocket(port); - log.fatal("Listening on port " + port + " (plain handler)"); + log.info("Listening on port " + port + " (plain handler)"); } catch (TTransportException e) { - log.fatal("Could not listen on port " + port + " (plain handler)"); + log.info("Could not listen on port " + port + " (plain handler)"); throw e; } THsHaServer.Args args = new THsHaServer.Args(serverTransport); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java index 24a110e5..22a90de7 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java @@ -105,8 +105,8 @@ public class ServerHandler implements SatelliteServer.Iface { */ @Override - public boolean isAuthenticated(String userToken) { - return SessionManager.get(userToken) != null; + public void isAuthenticated(String userToken) throws TAuthorizationException, TInternalServerError { + SessionManager.ensureAuthenticated(userToken); } @Override diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java index 1f36adfb..936b7a06 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java @@ -12,6 +12,7 @@ import org.openslx.bwlp.sat.permissions.User; import org.openslx.bwlp.thrift.iface.AuthorizationError; import org.openslx.bwlp.thrift.iface.Role; import org.openslx.bwlp.thrift.iface.TAuthorizationException; +import org.openslx.bwlp.thrift.iface.TInternalServerError; import org.openslx.bwlp.thrift.iface.TInvalidTokenException; import org.openslx.bwlp.thrift.iface.UserInfo; import org.openslx.thrifthelper.ThriftManager; @@ -80,14 +81,36 @@ public class SessionManager { } /** - * Get the user corresponding to the given token. Returns null if the token - * is not known, or the session already timed out. + * Do nothing if a user belongs to the given token and is authorized to use + * this satellite, throw an exception otherwise. + * + * @param token Token in question + * @throws TAuthorizationException + * @throws TInternalServerError + */ + public static void ensureAuthenticated(String token) throws TAuthorizationException, + TInternalServerError { + getInternal(token); + } + + /** + * Get the user corresponding to the given token. Returns <code>null</code> + * if the token is not known, or the session already timed out. * * @param token user's token * @return UserInfo for the matching user */ public static UserInfo get(String token) { + try { + return getInternal(token); + } catch (TAuthorizationException | TInternalServerError e) { + return null; + } + } + + private static UserInfo getInternal(String token) throws TAuthorizationException, TInternalServerError { Entry e = tokenManager.get(token); + LOGGER.info("Cache miss for token " + token + ", asking master"); if (e == null) return getRemote(token); // User session already cached @@ -114,25 +137,63 @@ public class SessionManager { * * @param token token of user to get * @return + * @throws TAuthorizationException if user is not allowed to use this + * satellite, this exception contains the reason + * @throws TInternalServerError if something unexpected fails */ - private static UserInfo getRemote(String token) { + private static UserInfo getRemote(String token) throws TAuthorizationException, TInternalServerError { UserInfo ui = null; try { ui = ThriftManager.getMasterClient().getUserFromToken(token); } catch (TInvalidTokenException ite) { - return null; // Token not known to master server + LOGGER.warn("Invalid token: " + token, ite); + throw new TAuthorizationException(AuthorizationError.INVALID_TOKEN, + "Your token is not known to the master server"); } catch (Exception e) { - LOGGER.warn("Could not reach master server to query for user token of a client!", e); + LOGGER.warn("Could not reach master server to query for user token (" + token + ") of a client!", + e); + throw new TInternalServerError(); } + LOGGER.info("Got user " + ui.userId + " for token " + token); + // TODO XXX HACK: Remove this once master server supplies role + if (ui.role == null) + ui.role = Role.TUTOR; // Valid reply, check if user is allowed to communicate with this satellite server - if (!User.canLogin(ui)) - return null; + AuthorizationError authError = User.canLogin(ui); + if (authError != null) { + LOGGER.info("User " + ui.userId + " cannot login: " + authError.toString()); + switch (authError) { + case ACCOUNT_SUSPENDED: + throw new TAuthorizationException(authError, + "Your account is not allowed to log in to this satellite"); + case BANNED_NETWORK: + throw new TAuthorizationException(authError, "Your IP address is banned from this satellite"); + case INVALID_CREDENTIALS: + case INVALID_KEY: + case CHALLENGE_FAILED: + throw new TAuthorizationException(authError, "Authentication error"); + case INVALID_ORGANIZATION: + throw new TAuthorizationException(authError, + "Your organization is not known to this satellite"); + case ORGANIZATION_SUSPENDED: + throw new TAuthorizationException(authError, + "Your organization is not allowed to log in to this satellite"); + case NOT_AUTHENTICATED: + case NO_PERMISSION: + throw new TAuthorizationException(authError, "No permission"); + case GENERIC_ERROR: + case INVALID_TOKEN: + default: + throw new TAuthorizationException(authError, "Internal server error"); + } + } // Is valid, insert/update db record, but ignore students if (ui.role != Role.STUDENT) { try { DbUser.writeUserOnLogin(ui); } catch (SQLException e) { - return null; + LOGGER.info("User " + ui.userId + " cannot be written to DB - rejecting."); + throw new TInternalServerError(); } } tokenManager.put(token, new Entry(ui)); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/VirtualizerList.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/VirtualizerList.java index 87b85186..469096d8 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/VirtualizerList.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/VirtualizerList.java @@ -1,7 +1,11 @@ package org.openslx.bwlp.sat.thrift.cache; import java.util.List; +import org.apache.log4j.Logger; +import org.openslx.bwlp.sat.database.mappers.DbOsVirt; + +import java.sql.SQLException; import org.apache.thrift.TException; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.thrifthelper.ThriftManager; @@ -12,6 +16,8 @@ import org.openslx.thrifthelper.ThriftManager; */ public class VirtualizerList extends CacheBase<List<Virtualizer>> { + private static final Logger LOGGER = Logger.getLogger(VirtualizerList.class); + private static final VirtualizerList instance = new VirtualizerList(); public static List<Virtualizer> get() { @@ -20,8 +26,28 @@ public class VirtualizerList extends CacheBase<List<Virtualizer>> { @Override protected List<Virtualizer> getCallback() throws TException { - return ThriftManager.getMasterClient().getVirtualizers(); - // TODO: Store in DB + final List<Virtualizer> list; + try { + list = ThriftManager.getMasterClient().getVirtualizers(); + } catch (TException e1) { + LOGGER.warn("Could not fetch Virtualizer list from master, using local data...", e1); + try { + return DbOsVirt.getVirtualizerList(); + } catch (SQLException e) { + LOGGER.warn("Using local Virtualizer list from database also failed.", e); + } + return null; + } +// QuickTimer.scheduleOnce(new Task() { +// @Override +// public void fire() { +// try { +// DbOsVirt.storeOsList(list); +// } catch (SQLException e) { +// } +// } +// }); + return list; } } |