use of com.cinchapi.concourse.thrift.AccessToken in project concourse by cinchapi.
the class AccessTokenVerificationAdvice method invoke.
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
AccessToken token = null;
TransactionToken transaction = null;
Object[] args = invocation.getArguments();
int index = 0;
while (token == null && (transaction == null || index < args.length)) {
Object arg = args[index];
if (arg instanceof AccessToken) {
token = (AccessToken) arg;
} else if (arg instanceof TransactionToken) {
transaction = (TransactionToken) arg;
}
++index;
}
if (token != null) {
ConcourseServer concourse = (ConcourseServer) invocation.getThis();
if (concourse.inspector().isValidToken(token)) {
if (transaction == null || (transaction != null && transaction.getAccessToken().equals(token) && concourse.inspector().isValidTransaction(transaction))) {
return invocation.proceed();
} else {
throw new IllegalArgumentException("Invalid transaction");
}
} else {
throw new SecurityException("Invalid access token");
}
} else {
throw new SecurityException("Unauthorized");
}
}
use of com.cinchapi.concourse.thrift.AccessToken in project concourse by cinchapi.
the class PermissionVerificationAdvice method invoke.
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
AccessToken token = null;
String environment = null;
Object[] args = invocation.getArguments();
int i = 0;
while ((token == null || environment == null) && i < args.length) {
Object arg = args[i];
if (token == null && arg instanceof AccessToken) {
token = (AccessToken) arg;
} else if (token != null && environment == null && arg instanceof String) {
// This relies on the convention that the environment parameter
// always comes after the AccessToken parameter
environment = (String) arg;
}
++i;
}
if (token != null && environment != null) {
ConcourseServer concourse = (ConcourseServer) invocation.getThis();
Inspector inspector = concourse.inspector();
if (inspector.tokenUserHasPermission(token, permission, environment)) {
return invocation.proceed();
} else {
throw new PermissionException("Insufficient Permission");
}
} else {
throw new IllegalStateException("Cannot verify permissions without an AccessToken and environment");
}
}
use of com.cinchapi.concourse.thrift.AccessToken in project concourse by cinchapi.
the class HttpServer method initialize.
/**
* Initialize a {@link EndpointContainer container} by registering all of
* its
* endpoints.
*
* @param container the {@link EndpointContainer} to initialize
*/
private static void initialize(EndpointContainer container) {
for (final Endpoint endpoint : container.endpoints()) {
String action = endpoint.getAction();
Route route = new Route(endpoint.getPath()) {
@Override
public Object handle(Request request, Response response) {
response.type(endpoint.getContentType().toString());
// The HttpRequests preprocessor assigns attributes to the
// request in order for the Endpoint to make calls into
// ConcourseServer.
AccessToken creds = (AccessToken) request.attribute(GlobalState.HTTP_ACCESS_TOKEN_ATTRIBUTE);
String environment = MoreObjects.firstNonNull((String) request.attribute(GlobalState.HTTP_ENVIRONMENT_ATTRIBUTE), GlobalState.DEFAULT_ENVIRONMENT);
String fingerprint = (String) request.attribute(GlobalState.HTTP_FINGERPRINT_ATTRIBUTE);
// does the fingerprint match?
if ((boolean) request.attribute(GlobalState.HTTP_REQUIRE_AUTH_ATTRIBUTE) && creds == null) {
halt(401);
}
if (!Strings.isNullOrEmpty(fingerprint) && !fingerprint.equals(HttpRequests.getFingerprint(request))) {
Logger.warn("Request made with mismatching fingerprint. Expecting {} but got {}", HttpRequests.getFingerprint(request), fingerprint);
halt(401);
}
TransactionToken transaction = null;
try {
Long timestamp = Longs.tryParse((String) request.attribute(GlobalState.HTTP_TRANSACTION_TOKEN_ATTRIBUTE));
transaction = creds != null && timestamp != null ? new TransactionToken(creds, timestamp) : transaction;
} catch (NullPointerException e) {
}
try {
return endpoint.serve(request, response, creds, transaction, environment);
} catch (Exception e) {
if (e instanceof HttpError) {
response.status(((HttpError) e).getCode());
} else if (e instanceof SecurityException || e instanceof java.lang.SecurityException) {
response.removeCookie(GlobalState.HTTP_AUTH_TOKEN_COOKIE);
response.status(401);
} else if (e instanceof IllegalArgumentException) {
response.status(400);
} else {
response.status(500);
Logger.error("", e);
}
JsonObject json = new JsonObject();
json.addProperty("error", e.getMessage());
return json.toString();
}
}
};
if (action.equals("get")) {
Spark.get(route);
} else if (action.equals("post")) {
Spark.post(route);
} else if (action.equals("put")) {
Spark.put(route);
} else if (action.equals("delete")) {
Spark.delete(route);
} else if (action.equals("upsert")) {
Spark.post(route);
Spark.put(route);
} else if (action.equals("options")) {
Spark.options(route);
}
}
}
use of com.cinchapi.concourse.thrift.AccessToken in project concourse by cinchapi.
the class PluginManager method startEventLoop.
/**
* Start a {@link Thread} that serves as an event loop; processing both
* requests and responses {@code #fromPlugin}.
* <p>
* Requests are forked to a {@link RemoteInvocationThread} for processing.
* </p>
* <p>
* Responses are placed on the appropriate
* {@link RegistryData#FROM_PLUGIN_RESPONSES queue} and listeners are
* notified.
* </p>
*
* @param id the plugin id
* @return the event loop thread
*/
private Thread startEventLoop(String id) {
final InterProcessCommunication incoming = (InterProcessCommunication) registry.get(id, RegistryData.FROM_PLUGIN);
final InterProcessCommunication outgoing = (InterProcessCommunication) registry.get(id, RegistryData.FROM_SERVER);
final ConcurrentMap<AccessToken, RemoteMethodResponse> fromPluginResponses = (ConcurrentMap<AccessToken, RemoteMethodResponse>) registry.get(id, RegistryData.FROM_PLUGIN_RESPONSES);
Thread loop = new Thread(new Runnable() {
@Override
public void run() {
ByteBuffer data;
while ((data = incoming.read()) != null) {
RemoteMessage message = serializer.deserialize(data);
if (message.type() == RemoteMessage.Type.REQUEST) {
RemoteMethodRequest request = (RemoteMethodRequest) message;
Logger.debug("Received REQUEST from Plugin {}: {}", id, request);
Thread worker = new RemoteInvocationThread(request, outgoing, server, true, fromPluginResponses);
worker.setUncaughtExceptionHandler((thread, throwable) -> {
Logger.error("While processing request '{}' from '{}', the following " + "non-recoverable error occurred:", request, id, throwable);
});
worker.start();
} else if (message.type() == RemoteMessage.Type.RESPONSE) {
RemoteMethodResponse response = (RemoteMethodResponse) message;
Logger.debug("Received RESPONSE from Plugin {}: {}", id, response);
ConcurrentMaps.putAndSignal(fromPluginResponses, response.creds, response);
} else if (message.type() == RemoteMessage.Type.STOP) {
break;
} else {
// Ignore the message...
continue;
}
}
}
}, "plugin-event-loop-" + id);
loop.setDaemon(true);
loop.start();
return loop;
}
use of com.cinchapi.concourse.thrift.AccessToken in project concourse by cinchapi.
the class PluginManager method invoke.
/**
* Invoke {@code method} that is defined in the plugin endpoint inside of
* {@clazz}. The provided {@code creds}, {@code transaction} token and
* {@code environment} are used to ensure proper alignment with the
* corresponding client session on the server.
*
* @param plugin class or alias name of the {@link Plugin}
* @param method the name of the method to invoke
* @param args a list of arguments to pass to the method
* @param creds the {@link AccessToken} submitted to ConcourseServer via the
* invokePlugin method
* @param transaction the {@link TransactionToken} submitted to
* ConcourseServer via
* the invokePlugin method
* @param environment the environment submitted to ConcourseServer via the
* invokePlugin method
* @return the response from the plugin
*/
public ComplexTObject invoke(String plugin, String method, List<ComplexTObject> args, final AccessToken creds, TransactionToken transaction, String environment) {
String clazz = getIdByAlias(plugin);
InterProcessCommunication fromServer = (InterProcessCommunication) registry.get(clazz, RegistryData.FROM_SERVER);
if (fromServer == null) {
String message = ambiguous.contains(plugin) ? "Multiple plugins are " + "configured to use the alias '{}' so it is not permitted. " + "Please invoke the plugin using its full qualified name" : "No plugin with id or alias {} exists";
throw new PluginException(AnyStrings.format(message, clazz));
}
RemoteMethodRequest request = new RemoteMethodRequest(method, creds, transaction, environment, args);
ByteBuffer buffer = serializer.serialize(request);
fromServer.write(buffer);
ConcurrentMap<AccessToken, RemoteMethodResponse> fromPluginResponses = (ConcurrentMap<AccessToken, RemoteMethodResponse>) registry.get(clazz, RegistryData.FROM_PLUGIN_RESPONSES);
RemoteMethodResponse response = ConcurrentMaps.waitAndRemove(fromPluginResponses, creds);
if (!response.isError()) {
return response.response;
} else {
Logger.error("Plugin Exception:", response.error);
throw new PluginException(AnyStrings.format("An error occurred when invoking '{}' in '{}': ", method, clazz, response.error));
}
}
Aggregations