GUACAMOLE-5: Associate the UserContext with any created tunnel.

This commit is contained in:
Michael Jumper
2016-07-15 21:17:57 -07:00
parent c231f4eb57
commit e4fe1a3a65
5 changed files with 140 additions and 16 deletions

View File

@@ -28,7 +28,7 @@ import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.tunnel.StreamInterceptingTunnel; import org.apache.guacamole.tunnel.UserTunnel;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -59,8 +59,8 @@ public class GuacamoleSession {
/** /**
* All currently-active tunnels, indexed by tunnel UUID. * All currently-active tunnels, indexed by tunnel UUID.
*/ */
private final Map<String, StreamInterceptingTunnel> tunnels = private final Map<String, UserTunnel> tunnels =
new ConcurrentHashMap<String, StreamInterceptingTunnel>(); new ConcurrentHashMap<String, UserTunnel>();
/** /**
* The last time this session was accessed. * The last time this session was accessed.
@@ -196,7 +196,7 @@ public class GuacamoleSession {
* *
* @return A map of all active tunnels associated with this session. * @return A map of all active tunnels associated with this session.
*/ */
public Map<String, StreamInterceptingTunnel> getTunnels() { public Map<String, UserTunnel> getTunnels() {
return tunnels; return tunnels;
} }
@@ -206,7 +206,7 @@ public class GuacamoleSession {
* *
* @param tunnel The tunnel to associate with this session. * @param tunnel The tunnel to associate with this session.
*/ */
public void addTunnel(StreamInterceptingTunnel tunnel) { public void addTunnel(UserTunnel tunnel) {
tunnels.put(tunnel.getUUID().toString(), tunnel); tunnels.put(tunnel.getUUID().toString(), tunnel);
} }

View File

@@ -30,7 +30,7 @@ import javax.ws.rs.core.MediaType;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleResourceNotFoundException; import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.GuacamoleSession; import org.apache.guacamole.GuacamoleSession;
import org.apache.guacamole.tunnel.StreamInterceptingTunnel; import org.apache.guacamole.tunnel.UserTunnel;
/** /**
* A REST resource which exposes the active tunnels of a Guacamole session. * A REST resource which exposes the active tunnels of a Guacamole session.
@@ -89,10 +89,10 @@ public class TunnelCollectionResource {
public TunnelResource getTunnel(@PathParam("tunnel") String tunnelUUID) public TunnelResource getTunnel(@PathParam("tunnel") String tunnelUUID)
throws GuacamoleException { throws GuacamoleException {
Map<String, StreamInterceptingTunnel> tunnels = session.getTunnels(); Map<String, UserTunnel> tunnels = session.getTunnels();
// Pull tunnel with given UUID // Pull tunnel with given UUID
final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID); final UserTunnel tunnel = tunnels.get(tunnelUUID);
if (tunnel == null) if (tunnel == null)
throw new GuacamoleResourceNotFoundException("No such tunnel."); throw new GuacamoleResourceNotFoundException("No such tunnel.");

View File

@@ -27,7 +27,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.tunnel.StreamInterceptingTunnel; import org.apache.guacamole.tunnel.UserTunnel;
/** /**
* A REST resource which abstracts the operations available for an individual * A REST resource which abstracts the operations available for an individual
@@ -48,7 +48,7 @@ public class TunnelResource {
/** /**
* The tunnel that this TunnelResource represents. * The tunnel that this TunnelResource represents.
*/ */
private final StreamInterceptingTunnel tunnel; private final UserTunnel tunnel;
/** /**
* Creates a new TunnelResource which exposes the operations and * Creates a new TunnelResource which exposes the operations and
@@ -57,7 +57,7 @@ public class TunnelResource {
* @param tunnel * @param tunnel
* The tunnel that this TunnelResource should represent. * The tunnel that this TunnelResource should represent.
*/ */
public TunnelResource(StreamInterceptingTunnel tunnel) { public TunnelResource(UserTunnel tunnel) {
this.tunnel = tunnel; this.tunnel = tunnel;
} }

View File

@@ -211,6 +211,10 @@ public class TunnelRequestService {
* @param session * @param session
* The Guacamole session to associate the tunnel with. * The Guacamole session to associate the tunnel with.
* *
* @param context
* The UserContext associated with the user for whom the tunnel is
* being created.
*
* @param type * @param type
* The type of object being connected to (connection or group). * The type of object being connected to (connection or group).
* *
@@ -226,12 +230,12 @@ public class TunnelRequestService {
* If an error occurs while obtaining the tunnel. * If an error occurs while obtaining the tunnel.
*/ */
protected GuacamoleTunnel createAssociatedTunnel(GuacamoleTunnel tunnel, protected GuacamoleTunnel createAssociatedTunnel(GuacamoleTunnel tunnel,
final String authToken, final GuacamoleSession session, final String authToken, final GuacamoleSession session,
final TunnelRequest.Type type, final String id) final UserContext context, final TunnelRequest.Type type,
throws GuacamoleException { final String id) throws GuacamoleException {
// Monitor tunnel closure and data // Monitor tunnel closure and data
StreamInterceptingTunnel monitoredTunnel = new StreamInterceptingTunnel(tunnel) { UserTunnel monitoredTunnel = new UserTunnel(context, tunnel) {
/** /**
* The time the connection began, measured in milliseconds since * The time the connection began, measured in milliseconds since
@@ -328,7 +332,7 @@ public class TunnelRequestService {
GuacamoleTunnel tunnel = createConnectedTunnel(userContext, type, id, info); GuacamoleTunnel tunnel = createConnectedTunnel(userContext, type, id, info);
// Associate tunnel with session // Associate tunnel with session
return createAssociatedTunnel(tunnel, authToken, session, type, id); return createAssociatedTunnel(tunnel, authToken, session, userContext, type, id);
} }

View File

@@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.guacamole.tunnel;
import java.util.Collection;
import java.util.UUID;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserContext;
/**
* Tunnel implementation which associates a given tunnel with the UserContext of
* the user that created it.
*
* @author Michael Jumper
*/
public class UserTunnel extends StreamInterceptingTunnel {
/**
* The UserContext associated with the user for whom this tunnel was
* created. This UserContext MUST be from the AuthenticationProvider that
* created this tunnel.
*/
private final UserContext userContext;
/**
* Creates a new UserTunnel which wraps the given tunnel, associating it
* with the given UserContext. The UserContext MUST be from the
* AuthenticationProvider that created this tunnel, and MUST be associated
* with the user for whom this tunnel was created.
*
* @param userContext
* The UserContext associated with the user for whom this tunnel was
* created. This UserContext MUST be from the AuthenticationProvider
* that created this tunnel.
*
* @param tunnel
* The tunnel whose stream-related instruction should be intercepted if
* interceptStream() is invoked.
*/
public UserTunnel(UserContext userContext, GuacamoleTunnel tunnel) {
super(tunnel);
this.userContext = userContext;
}
/**
* Returns the UserContext of the user for whom this tunnel was created.
* This UserContext will be the UserContext from the AuthenticationProvider
* that created this tunnel.
*
* @return
* The UserContext of the user for whom this tunnel was created.
*/
public UserContext getUserContext() {
return userContext;
}
/**
* Returns the ActiveConnection object associated with this tunnel within
* the AuthenticationProvider and UserContext which created the tunnel. If
* the AuthenticationProvider is not tracking active connections, or this
* tunnel is no longer active, this will be null.
*
* @return
* The ActiveConnection object associated with this tunnel, or null if
* this tunnel is no longer active or the AuthenticationProvider which
* created the tunnel is not tracking active connections.
*
* @throws GuacamoleException
* If an error occurs which prevents retrieval of the user's current
* active connections.
*/
public ActiveConnection getActiveConnection() throws GuacamoleException {
// Pull the UUID of the current tunnel
UUID uuid = getUUID();
// Get the directory of active connections
Directory<ActiveConnection> activeConnectionDirectory = userContext.getActiveConnectionDirectory();
Collection<String> activeConnectionIdentifiers = activeConnectionDirectory.getIdentifiers();
// Search all connections for a tunnel which matches this tunnel
for (ActiveConnection activeConnection : activeConnectionDirectory.getAll(activeConnectionIdentifiers)) {
// If we lack access, continue with next tunnel
GuacamoleTunnel tunnel = activeConnection.getTunnel();
if (tunnel == null)
continue;
// Tunnels are equivalent if they have the same UUID
if (uuid.equals(tunnel.getUUID()))
return activeConnection;
}
// No active connection associated with this tunnel
return null;
}
}