=== Using Elasticsearch Java Clients with Shield

Shield supports the Java http://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html[transport client] for Elasticsearch. The transport client uses the same transport protocol that the cluster nodes use for inter-node communication. It is very efficient as it does not have to marshall and unmarshall JSON requests like a typical REST client.

NOTE: Using the Java Node Client with Shield is not recommended or supported.

[float]
[[transport-client]]
==== Configuring the Transport Client to work with Shield

To use the transport client with Shield, you need to:

[[java-transport-client-role]]
. Configure a user with the privileges required to start the transport client. A default 
`transport_client` role is defined in `roles.yml` that grants the `cluster:monitor/nodes/info` cluster permission. The transport client uses the node info API to fetch information about the nodes in the cluster. If the client is configured to use sniffing, you need to add the
`cluster:monitor/state` cluster permission to the `transport_client` role.

. Add the Shield JAR file (`shield-2.1.0.jar`) to your CLASSPATH. You can download the Shield distribution and extract the JAR file manually or you can get it from the http://maven.elasticsearch.org/releases/org/elasticsearch/plugin/shield/{version}/shield-{version}.jar[Elasticsearch Maven repository].
+
If you are using Maven, you need to add the Shield JAR file as a dependency in your project's `pom.xml` file:
+
[source,xml]
--------------------------------------------------------------
<project ...>

   <repositories>
      <!-- add the elasticsearch repo -->
      <repository>
         <id>elasticsearch-releases</id>
         <url>http://maven.elasticsearch.org/releases</url>
         <releases>
            <enabled>true</enabled>
         </releases>
         <snapshots>
            <enabled>false</enabled>
         </snapshots>
      </repository>
      ...
   </repositories>
   ...

   <dependencies>
      <!-- add the shield jar as a dependency -->
      <dependency>
         <groupId>org.elasticsearch.plugin</groupId>
         <artifactId>shield</artifactId>
         <version>2.1.0</version>
      </dependency>
      ...
   </dependencies>
   ...

 </project>
--------------------------------------------------------------
+
If you are using Gradle, you need to add the Shield JAR file as a dependency in your `build.gradle` file:
+
[source,groovy]
--------------------------------------------------------------
repositories {
  /* ... Any other repositories ... */

  // Add the Elasticsearch Maven Repository
  maven {
    url "http://maven.elasticsearch.org/releases"
  }
}

dependencies {
  // Provide the Shield jar on the classpath for compilation and at runtime
  // Note: Many projects can use the Shield jar as a runtime dependency
  compile "org.elasticsearch.plugin:shield:2.1.0"

  /* ... */
}
--------------------------------------------------------------

. Set up the transport client. At a minimum, you must configure `shield.user` to include the name and password of your transport client user in your requests. The following snippet configures the user credentials globally--every request submitted with this client includes the `transport_client_user` credentials in its headers.
+
[source,java]
-------------------------------------------------------------------------------------------------
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.shield.ShieldPlugin
...

TransportClient client = TransportClient.builder()
    .addPlugin(ShieldPlugin.class)
    .settings(Settings.builder()
        .put("cluster.name", "myClusterName")
        .put("shield.user", "transport_client_user:changeme")
        ...
        .build())
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9300))
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9301));
-------------------------------------------------------------------------------------------------
+
WARNING: If you configure a transport client without SSL, passwords are sent in plaintext.
+
You can also add an `Authorization` header to each request. If you've configured global authorization credentials, the `Authorization` header overrides the global authentication credentials. This is useful when an application has multiple users who access Elasticsearch using the same client. You can set the global token to a user that only has the `transport_client` role, and add the `transport_client` role to the individual users.
+
For example, the following snippet adds the `Authorization` header to a search request:
+
[source,java]
--------------------------------------------------------------------------------------------------
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.shield.ShieldPlugin

import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
...

TransportClient client = TransportClient.builder()
    .addPlugin(ShieldPlugin.class)
    .settings(Settings.builder()
        .put("cluster.name", "myClusterName")
        .put("shield.user", "transport_client_user:changeme")
        ...
        .build())
    .build()
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9300))
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9301));

String token = basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray()));

client.prepareSearch().putHeader("Authorization", token).get();
--------------------------------------------------------------------------------------------------

. Enable SSL to authenticate clients and encrypt communications. To enable SSL, you need to:

.. Configure the client's keystore path and password. Client authentication requires every 
client to have a certification signed by a trusted CA. 
+
NOTE: Client authentication is enabled by default. For information about disabling client authentication, see <<disabling-client-auth, Disabling Client Authentication>>.
+
[source,java]
--------------------------------------------------------------------------------------------------
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.shield.ShieldPlugin
...

TransportClient client = TransportClient.builder()
    .addPlugin(ShieldPlugin.class)
    .settings(Settings.builder()
        .put("cluster.name", "myClusterName")
        .put("shield.user", "transport_client_user:changeme")
        .put("shield.ssl.keystore.path", "/path/to/client.jks") (1)
        .put("shield.ssl.keystore.password", "password")
        ...
        .build());
--------------------------------------------------------------------------------------------------
+
(1) The `client.jks` keystore must contain the client's signed certificate and the CA certificate.
+
.. Enable the SSL transport by setting `shield.transport.ssl` to `true` in the client configuration.
+
[source,java]
--------------------------------------------------------------------------------------------------
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.shield.ShieldPlugin
...

TransportClient client = TransportClient.builder()
    .addPlugin(ShieldPlugin.class)
    .settings(Settings.builder()
        .put("cluster.name", "myClusterName")
        .put("shield.user", "transport_client_user:changeme")
        .put("shield.ssl.keystore.path", "/path/to/client.jks") (1)
        .put("shield.ssl.keystore.password", "password")
        .put("shield.transport.ssl", "true")
        ...
        .build())
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9300))
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9301));
--------------------------------------------------------------------------------------------------

[float]
[[disabling-client-auth]]
===== Disabling Client Authentication

If you want to disable client authentication, you can use a client-specific transport protocol. For more information, <<separating-node-client-traffic, Separating Node to Node and Client Traffic>>.

If you are not using client authentication and sign the Elasticsearch node certificates with your own CA, you need to set the truststore path and password in the client configuration:

[source,java]
------------------------------------------------------------------------------------------------------
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.shield.ShieldPlugin
...

TransportClient client = TransportClient.builder()
    .addPlugin(ShieldPlugin.class)
    .settings(Settings.builder()
        .put("cluster.name", "myClusterName")
        .put("shield.user", "test_user:changeme")
        .put("shield.ssl.truststore.path", "/path/to/truststore.jks") (1)
        .put("shield.ssl.truststore.password", "password")
        .put("shield.transport.ssl", "true")
        ...
        .build())
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9300))
    .addTransportAddress(new InetSocketTransportAddress("localhost", 9301));
------------------------------------------------------------------------------------------------------
(1) The `truststore.jks` truststore must contain the certificate of the CA that signed the Elasticsearch node certificates. 

NOTE: If you are using a public CA that is already trusted by the Java runtime, you to not need to set the `shield.ssl.truststore.path` and `shield.ssl.truststore.password`.

[float]
[[connecting-anonymously]]
===== Connecting Anonymously added[1.1.0]

To enable the transport client to connect anonymously, you must assign the anonymous user the privileges defined in the  <<java-transport-client-role,transport_client>> role. Anonymous access must also be enabled, of course. For more information, see  <<anonymous-access,Enabling Anonymous Access>>.

[float]
[[shield-client]]
==== Shield Client

Shield exposes its own API through the `ShieldClient` class. At the moment, this API only exposes one operation, for clearing the realm caches. `ShieldClient` is a wrapper around the existing clients (any client class implementing `org.elasticsearch.client.Client`).

The following example shows how you can clear Shield's realm caches using `ShieldClient`:

[source,java]
------------------------------------------------------------------------------------------------------
import static org.elasticsearch.node.NodeBuilder.*;
...

Client client = ... // create the transport client

ShieldClient shieldClient = new ShieldClient(client);
ClearRealmCacheResponse response = shieldClient.authc().prepareClearRealmCache()
    .realms("ldap1", "ad1") (1)
    .usernames("rdeniro")
    .get();
------------------------------------------------------------------------------------------------------

(1) Clears the `ldap1` and `ad1` realm caches for the `rdeniro` user.


