Skip to content
This repository has been archived by the owner on Jul 17, 2023. It is now read-only.

Commit

Permalink
GUACAMOLE-360: Refactor TunnelRequestService to handle any Connectabl…
Browse files Browse the repository at this point in the history
…e supported by TunnelRequestType.
  • Loading branch information
mike-jumper committed Aug 11, 2019
1 parent 403431b commit 1c7242b
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 121 deletions.
Expand Up @@ -21,8 +21,6 @@

import java.util.List;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleException;

/**
Expand Down Expand Up @@ -101,40 +99,6 @@ public abstract class TunnelRequest {
*/
public static final String TIMEZONE_PARAMETER = "GUAC_TIMEZONE";

/**
* All supported object types that can be used as the destination of a
* tunnel.
*/
public static enum Type {

/**
* A Guacamole connection.
*/
CONNECTION("c"),

/**
* A Guacamole connection group.
*/
CONNECTION_GROUP("g");

/**
* The parameter value which denotes a destination object of this type.
*/
final String PARAMETER_VALUE;

/**
* Defines a Type having the given corresponding parameter value.
*
* @param value
* The parameter value which denotes a destination object of this
* type.
*/
Type(String value) {
PARAMETER_VALUE = value;
}

};

/**
* Returns the value of the parameter having the given name.
*
Expand Down Expand Up @@ -257,18 +221,11 @@ public String getAuthenticationProviderIdentifier()
* If the type was not present in the request, or if the type requested
* is in the wrong format.
*/
public Type getType() throws GuacamoleException {

String type = getRequiredParameter(TYPE_PARAMETER);

// For each possible object type
for (Type possibleType : Type.values()) {
public TunnelRequestType getType() throws GuacamoleException {

// Match against defined parameter value
if (type.equals(possibleType.PARAMETER_VALUE))
return possibleType;

}
TunnelRequestType type = TunnelRequestType.parseType(getRequiredParameter(TYPE_PARAMETER));
if (type != null)
return type;

throw new GuacamoleClientException("Illegal identifier - unknown type.");

Expand Down
Expand Up @@ -24,15 +24,13 @@
import java.util.List;
import java.util.Map;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.GuacamoleResourceNotFoundException;
import org.apache.guacamole.GuacamoleSession;
import org.apache.guacamole.GuacamoleUnauthorizedException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.Connectable;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.net.event.TunnelCloseEvent;
import org.apache.guacamole.net.event.TunnelConnectEvent;
Expand Down Expand Up @@ -204,58 +202,20 @@ protected GuacamoleClientInformation getClientInformation(TunnelRequest request)
* If an error occurs while creating the tunnel.
*/
protected GuacamoleTunnel createConnectedTunnel(UserContext context,
final TunnelRequest.Type type, String id,
final TunnelRequestType type, String id,
GuacamoleClientInformation info, Map<String, String> tokens)
throws GuacamoleException {

// Create connected tunnel from identifier
GuacamoleTunnel tunnel = null;
switch (type) {

// Connection identifiers
case CONNECTION: {

// Get connection directory
Directory<Connection> directory = context.getConnectionDirectory();

// Get authorized connection
Connection connection = directory.get(id);
if (connection == null) {
logger.info("Connection \"{}\" does not exist for user \"{}\".", id, context.self().getIdentifier());
throw new GuacamoleSecurityException("Requested connection is not authorized.");
}

// Connect tunnel
tunnel = connection.connect(info, tokens);
logger.info("User \"{}\" connected to connection \"{}\".", context.self().getIdentifier(), id);
break;
}

// Connection group identifiers
case CONNECTION_GROUP: {

// Get connection group directory
Directory<ConnectionGroup> directory = context.getConnectionGroupDirectory();

// Get authorized connection group
ConnectionGroup group = directory.get(id);
if (group == null) {
logger.info("Connection group \"{}\" does not exist for user \"{}\".", id, context.self().getIdentifier());
throw new GuacamoleSecurityException("Requested connection group is not authorized.");
}

// Connect tunnel
tunnel = group.connect(info, tokens);
logger.info("User \"{}\" connected to group \"{}\".", context.self().getIdentifier(), id);
break;
}

// Type is guaranteed to be one of the above
default:
assert(false);

}
// Retrieve requested destination object
Connectable connectable = type.getConnectable(context, id);
if (connectable == null)
throw new GuacamoleResourceNotFoundException("Requested tunnel "
+ "destination does not exist.");

// Connect tunnel to destination
GuacamoleTunnel tunnel = connectable.connect(info, tokens);
logger.info("User \"{}\" connected to {} \"{}\".",
context.self().getIdentifier(), type.NAME, id);
return tunnel;

}
Expand Down Expand Up @@ -297,7 +257,7 @@ protected GuacamoleTunnel createConnectedTunnel(UserContext context,
*/
protected GuacamoleTunnel createAssociatedTunnel(final GuacamoleTunnel tunnel,
final String authToken, final GuacamoleSession session,
final UserContext context, final TunnelRequest.Type type,
final UserContext context, final TunnelRequestType type,
final String id) throws GuacamoleException {

// Monitor tunnel closure and data
Expand All @@ -320,26 +280,9 @@ public void close() throws GuacamoleException {
long connectionEndTime = System.currentTimeMillis();
long duration = connectionEndTime - connectionStartTime;

// Log closure
switch (type) {

// Connection identifiers
case CONNECTION:
logger.info("User \"{}\" disconnected from connection \"{}\". Duration: {} milliseconds",
session.getAuthenticatedUser().getIdentifier(), id, duration);
break;

// Connection group identifiers
case CONNECTION_GROUP:
logger.info("User \"{}\" disconnected from connection group \"{}\". Duration: {} milliseconds",
session.getAuthenticatedUser().getIdentifier(), id, duration);
break;

// Type is guaranteed to be one of the above
default:
assert(false);

}
logger.info("User \"{}\" disconnected from {} \"{}\". Duration: {} milliseconds",
session.getAuthenticatedUser().getIdentifier(),
type.NAME, id, duration);

try {

Expand Down Expand Up @@ -390,7 +333,7 @@ public GuacamoleTunnel createTunnel(TunnelRequest request)
// Parse request parameters
String authToken = request.getAuthenticationToken();
String id = request.getIdentifier();
TunnelRequest.Type type = request.getType();
TunnelRequestType type = request.getType();
String authProviderIdentifier = request.getAuthenticationProviderIdentifier();
GuacamoleClientInformation info = getClientInformation(request);

Expand Down
@@ -0,0 +1,140 @@
/*
* 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 org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.Connectable;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.UserContext;

/**
* All supported object types that can be used as the destination of a tunnel.
*
* @see TunnelRequest#TYPE_PARAMETER
* @see TunnelRequest#getType()
*/
public enum TunnelRequestType {

/**
* A Guacamole connection.
*/
CONNECTION("c", "connection") {

@Override
public Connection getConnectable(UserContext userContext,
String identifier) throws GuacamoleException {
return userContext.getConnectionDirectory().get(identifier);
}

},

/**
* A Guacamole connection group.
*/
CONNECTION_GROUP("g", "connection group") {

@Override
public ConnectionGroup getConnectable(UserContext userContext,
String identifier) throws GuacamoleException {
return userContext.getConnectionGroupDirectory().get(identifier);
}

};

/**
* The parameter value which denotes a destination object of this type
* within a tunnel request.
*
* @see TunnelRequest#TYPE_PARAMETER
* @see TunnelRequest#getType()
*/
public final String PARAMETER_VALUE;

/**
* A human-readable, descriptive name of the type of destination object.
*/
public final String NAME;

/**
* Defines a tunnel request type having the given corresponding parameter
* value and human-readable name.
*
* @param value
* The parameter value which denotes a destination object of this
* type.
*
* @param name
* A human-readable, descriptive name of the type of destination
* object.
*/
private TunnelRequestType(String value, String name) {
PARAMETER_VALUE = value;
NAME = name;
}

/**
* Retrieves the object having the given identifier from the given
* UserContext, where the type of object retrieved is the type of object
* represented by this tunnel request type.
*
* @param userContext
* The UserContext to retrieve the object from.
*
* @param identifier
* The identifier of the object to retrieve.
*
* @return
* The object having the given identifier, or null if no such object
* exists.
*
* @throws GuacamoleException
* If an error occurs retrieving the requested object, or if permission
* to retrieve the object is denied.
*/
public abstract Connectable getConnectable(UserContext userContext,
String identifier) throws GuacamoleException;

/**
* Parses the given tunnel request type string, returning the
* TunnelRequestType which matches that string, as declared by
* {@link #PARAMETER_VALUE}. If no such type exists, null is returned.
*
* @param type
* The type string to parse.
*
* @return
* The TunnelRequestType which specifies the given string as its
* {@link #PARAMETER_VALUE}, or null if no such type exists.
*/
public static TunnelRequestType parseType(String type) {

// Locate type with given parameter value
for (TunnelRequestType possibleType : values()) {
if (type.equals(possibleType.PARAMETER_VALUE))
return possibleType;
}

// No such type
return null;

}

}

0 comments on commit 1c7242b

Please sign in to comment.