Search in sources :

Example 56 with AccessToken

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");
    }
}
Also used : TransactionToken(com.cinchapi.concourse.thrift.TransactionToken) AccessToken(com.cinchapi.concourse.thrift.AccessToken) SecurityException(com.cinchapi.concourse.thrift.SecurityException) ConcourseServer(com.cinchapi.concourse.server.ConcourseServer)

Example 57 with AccessToken

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");
    }
}
Also used : PermissionException(com.cinchapi.concourse.thrift.PermissionException) AccessToken(com.cinchapi.concourse.thrift.AccessToken) Inspector(com.cinchapi.concourse.server.Inspector) ConcourseServer(com.cinchapi.concourse.server.ConcourseServer)

Example 58 with AccessToken

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);
        }
    }
}
Also used : TransactionToken(com.cinchapi.concourse.thrift.TransactionToken) Request(spark.Request) JsonObject(com.google.gson.JsonObject) Response(spark.Response) AccessToken(com.cinchapi.concourse.thrift.AccessToken) HttpError(com.cinchapi.concourse.server.http.errors.HttpError) Route(spark.Route)

Example 59 with AccessToken

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;
}
Also used : Version(com.github.zafarkhaja.semver.Version) AnyStrings(com.cinchapi.common.base.AnyStrings) JsonObject(com.google.gson.JsonObject) StringUtils(org.apache.commons.lang.StringUtils) URL(java.net.URL) Logger(com.cinchapi.concourse.util.Logger) HashBasedTable(com.google.common.collect.HashBasedTable) Reflections(org.reflections.Reflections) ByteBuffer(java.nio.ByteBuffer) DirectoryStream(java.nio.file.DirectoryStream) MessageQueue(com.cinchapi.concourse.server.plugin.io.MessageQueue) URLClassLoader(java.net.URLClassLoader) Future(java.util.concurrent.Future) Resources(com.cinchapi.concourse.util.Resources) CharStreams(com.google.common.io.CharStreams) Map(java.util.Map) ConcurrentMaps(com.cinchapi.concourse.util.ConcurrentMaps) AccessToken(com.cinchapi.concourse.thrift.AccessToken) Path(java.nio.file.Path) ZipException(java.util.zip.ZipException) FileSystem(com.cinchapi.concourse.server.io.FileSystem) ComplexTObject(com.cinchapi.concourse.thrift.ComplexTObject) Set(java.util.Set) Versions(com.cinchapi.concourse.server.plugin.util.Versions) Executors(java.util.concurrent.Executors) ClasspathHelper(org.reflections.util.ClasspathHelper) Sets(com.google.common.collect.Sets) ConcourseServer(com.cinchapi.concourse.server.ConcourseServer) List(java.util.List) Queues(com.cinchapi.concourse.util.Queues) WriteEvent(com.cinchapi.concourse.server.plugin.data.WriteEvent) Modifier(java.lang.reflect.Modifier) Entry(java.util.Map.Entry) CheckedExceptions(com.cinchapi.common.base.CheckedExceptions) TransactionToken(com.cinchapi.concourse.thrift.TransactionToken) JsonParser(com.google.gson.JsonParser) Constructor(java.lang.reflect.Constructor) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) Reflection(com.cinchapi.common.reflect.Reflection) Lists(com.google.common.collect.Lists) BINARY_QUEUE(com.cinchapi.concourse.server.GlobalState.BINARY_QUEUE) ExecutorService(java.util.concurrent.ExecutorService) ConfigurationBuilder(org.reflections.util.ConfigurationBuilder) Time(com.cinchapi.concourse.time.Time) Iterator(java.util.Iterator) AfterInstallHook(com.cinchapi.concourse.server.plugin.hook.AfterInstallHook) Files(java.nio.file.Files) BaseEncoding(com.google.common.io.BaseEncoding) MorePaths(com.cinchapi.concourse.util.MorePaths) ZipFiles(com.cinchapi.concourse.util.ZipFiles) Throwables(com.google.common.base.Throwables) IOException(java.io.IOException) InputStreamReader(java.io.InputStreamReader) Maps(com.google.common.collect.Maps) File(java.io.File) JavaApp(com.cinchapi.concourse.server.io.process.JavaApp) ExecutionException(java.util.concurrent.ExecutionException) InterProcessCommunication(com.cinchapi.concourse.server.plugin.io.InterProcessCommunication) PluginSerializer(com.cinchapi.concourse.server.plugin.io.PluginSerializer) Paths(java.nio.file.Paths) Collections(java.util.Collections) Table(com.google.common.collect.Table) ConcurrentMap(java.util.concurrent.ConcurrentMap) ByteBuffer(java.nio.ByteBuffer) AccessToken(com.cinchapi.concourse.thrift.AccessToken) InterProcessCommunication(com.cinchapi.concourse.server.plugin.io.InterProcessCommunication)

Example 60 with AccessToken

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));
    }
}
Also used : AccessToken(com.cinchapi.concourse.thrift.AccessToken) ConcurrentMap(java.util.concurrent.ConcurrentMap) InterProcessCommunication(com.cinchapi.concourse.server.plugin.io.InterProcessCommunication) ByteBuffer(java.nio.ByteBuffer)

Aggregations

AccessToken (com.cinchapi.concourse.thrift.AccessToken)96 ByteBuffer (java.nio.ByteBuffer)72 TransactionToken (com.cinchapi.concourse.thrift.TransactionToken)60 TException (org.apache.thrift.TException)60 AtomicReference (java.util.concurrent.atomic.AtomicReference)56 AnyStrings (com.cinchapi.common.base.AnyStrings)55 CheckedExceptions (com.cinchapi.common.base.CheckedExceptions)55 Reflection (com.cinchapi.common.reflect.Reflection)55 Permission (com.cinchapi.concourse.security.Permission)55 Role (com.cinchapi.concourse.security.Role)55 Internal (com.cinchapi.concourse.server.aop.Internal)55 VerifyAccessToken (com.cinchapi.concourse.server.aop.VerifyAccessToken)55 VerifyReadPermission (com.cinchapi.concourse.server.aop.VerifyReadPermission)55 VerifyWritePermission (com.cinchapi.concourse.server.aop.VerifyWritePermission)55 FileSystem (com.cinchapi.concourse.server.io.FileSystem)55 ConcourseManagementService (com.cinchapi.concourse.server.management.ConcourseManagementService)55 PluginManager (com.cinchapi.concourse.server.plugin.PluginManager)55 AbstractSyntaxTree (com.cinchapi.ccl.syntax.AbstractSyntaxTree)28 NaturalLanguage (com.cinchapi.ccl.util.NaturalLanguage)28 Array (com.cinchapi.common.base.Array)28