Installing the Java Module as a Jetty Handler

IMPORTANT

This guide only applies to Next-Gen WAF customers with access to the Next-Gen WAF control panel. If you have access to the Next-Gen WAF product in the Fastly control panel, you can only deploy the Next-Gen WAF with the Edge WAF deployment method.

Requirements

Jetty 9.2 or higher

Supported Application Types

For Jetty specific implementations, we support a HandlerWrapper-based install on Jetty 9.2 or higher.

We also provide a lower-level agent RPC communication API if you are interested in writing an implementation for another Java platform. If you are interested in writing an implementation for another Java platform, reach out to our support team.

Agent Configuration

Like other Next-Gen WAF modules, the Jetty Handler supports both Unix domain sockets and TCP sockets for communication with the Next-Gen WAF agent. By default, the agent uses Unix domain sockets with the address set to unix:/var/run/sigsci.sock. It is possible to override this or specify a TCP socket instead by configuring the rpc-address parameter in the Agent.

Additionally, ensure the agent is configured to use the default RPC version: rpc-version=0. This can be done by verifying the parameter rpc-version is not specified in the agent configuration or if it is specified, ensure that is specified with a value of 0. Below is an example Agent configuration that overrides the default Unix domain socket value:

1
2
3
accesskeyid = "YOUR AGENT ACCESSKEYID"
secretaccesskey = "YOUR AGENT SECRETACCESSKEY"
rpc-address = "127.0.0.1:9999"

Download

Download the Next-Gen WAF Java module manually or access it with Maven.

Download manually

  1. Download the Java module archive from https://dl.signalsciences.net/sigsci-module-java/sigsci-module-java_latest.tar.gz.
  2. Extract sigsci-module-java_latest.tar.gz.
  3. Deploy the jars using one of the following options:
    • Copy sigsci-module-java-{version}-shaded.jar (an uber jar with all the dependencies bundled) to your application’s classpath (e.g., %CATALINA_HOME%\webbapps\<APP_FOLDER>\WEB-INF\lib).
    • Copy sigsci-module-java-{version}.jar and its dependencies in the lib folder to your application’s classpath (e.g., %CATALINA_HOME%\webbapps\<APP_FOLDER>\WEB-INF\lib). If you already have any of the dependency jar files in your application classpath folder (i.e., for Tomcat in the WEB-INF\lib) then it is not necessary to copy them, even if the version numbers are different. The logging jars are optional based on how slf4j is configured.

Access with Maven

For projects using Maven for build or deployment, the latest version of Next-Gen WAF Java modules can be installed by adding XML to the project pom.xml file. For example:

1
2
3
4
5
6
7
8
9
10
11
12
<repositories>
<repository>
<id>sigsci-stable</id>
<url>https://packages.signalsciences.net/release/maven2</url>
</repository>
</repositories>
<dependency>
<groupId>com.signalsciences</groupId>
<artifactId>sigsci-module-java</artifactId>
<version>LATEST_MODULE_VERSION</version>
</dependency>

Be sure to replace LATEST_MODULE_VERSION with the latest release of the Java module. You can find the latest version in our version file at https://dl.signalsciences.net/sigsci-module-java/VERSION.

Install

The installation of the Jetty module varies slightly depending upon whether you deployed Jetty as an embedded or stand alone application.

If you are embedding Jetty within your web application, follow the instructions for Embedded Jetty.

Alternatively, if you are deploying your web application to a Jetty instance, follow the instructions for Standalone Jetty.

Embedded Jetty

The Next-Gen WAF Jetty module is currently implemented as a Handler. Edit your application to wrap your existing Handlers with the Next-Gen WAF Handler.

A typical Jetty based application will add all of the Handlers to a HandlerList, similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Server server = new Server(InetSocketAddress.createUnresolved("0.0.0.0", 8800));
ServletContextHandler context = new ServletContextHandler();
ServletHolder defHolder = new ServletHolder("default", DefaultServlet.class);
HandlerList handlers = new HandlerList();
// Servlet: /
defHolder.setInitParameter("pathInfoOnly", "true");
defHolder.setInitParameter("dirAllowed", "true");
defHolder.setInitParameter("acceptRanges", "true");
context.addServlet(defHolder, "/*");
context.addServlet(defHolder, "/");
// Existing App Handlers
handlers.addHandler(context);
handlers.addHandler(new DefaultHandler());
// Add the existing handlers as the server handler
server.setHandler(handlers);
try {
server.start();
server.join();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}

Add the Next-Gen WAF Handler around your primary handler. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Server server = new Server(InetSocketAddress.createUnresolved("0.0.0.0", 8800));
ServletContextHandler context = new ServletContextHandler();
ServletHolder defHolder = new ServletHolder("default", DefaultServlet.class);
HandlerList handlers = new HandlerList();
// Servlet: /
defHolder.setInitParameter("pathInfoOnly", "true");
defHolder.setInitParameter("dirAllowed", "true");
defHolder.setInitParameter("acceptRanges", "true");
context.addServlet(defHolder, "/*");
context.addServlet(defHolder, "/");
// Existing App Handlers
handlers.addHandler(context);
handlers.addHandler(new DefaultHandler());
// REMOVED: This is replaced by wrapping with the sigsci handler below
//server.setHandler(handlers);
//////////////////////////////////////////////////////////////////////////
// BEGIN ADDITION: Next-Gen WAF Handler
// Need to also add these imports for SignalSciencesHandler and Timeout:
// import com.signalsciences.jetty.SignalSciencesHandler;
// import com.signalsciences.rpc.util.Timeout;
//////////////////////////////////////////////////////////////////////////
// 1. Create a new SignalSciencesHandler
SignalSciencesHandler sigsciHandler = new SignalSciencesHandler();
// 2. Specify the URI of the sigsci-agent rpc-address (Unix)
sigsciHandler.getSigSciConfig().setRpcServerURI(URI.create("unix:/var/run/sigsci.sock"));
// 3. Specify a timeout
sigsciHandler.getSigSciConfig().setRpcTimeout(new Timeout(300, TimeUnit.MILLISECONDS));
// 4. Set rpcVersion to 0
sigsciHandler.getSigSciConfig().setRpcVersion(0);
// 5. Wrap the other handlers
sigsciHandler.setHandler(handlers);
// 6. Set the SignalSciencesHandler (wrapper) as the server handler
server.setHandler(sigsciHandler);
//////////////////////////////////////////////////////////////////////////
// END ADDITION
//////////////////////////////////////////////////////////////////////////
try {
server.start();
server.join();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}

Standalone Jetty

The Next-Gen WAF Jetty module is currently implemented as a handler. To use this, you will need to follow the steps below to update your server configuration.

Update Jetty Server Configuration File

In a default Jetty installation, the server configuration file can be found under {jetty.base}/etc/jetty.xml. You will need to update the configuration file to wrap the existing Handlers with the Next-Gen WAF Handler. Modify the stanza in the file that specifies the handler collection to include the Next-Gen WAF Handler. Below is an example using the out of the box jetty.xml file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<Set name="handler">
<New id="Wrapper" class="com.signalsciences.jetty.SignalSciencesHandler">
<Call name="setRpcServerURI">
<Arg>
<New class="java.net.URI">
<Arg>unix:/var/run/sigsci.sock</Arg>
</New>
</Arg>
</Call>
<Call name="setRpcTimeout">
<Arg>
<New class="com.signalsciences.rpc.util.Timeout">
<Arg type="long">300</Arg>
<Arg>
<Get class="java.util.concurrent.TimeUnit" name="MILLISECONDS"/>
</Arg>
</New>
</Arg>
</Call>
<Set name="handler">
<New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
</Item>
<Item>
<New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
</Item>
</Array>
</Set>
</New>
</Set>
</New>
</Set>

Deploy Signal Sciences Library to the Server ClassPath

There are two options for deploying the jars:

  • Copy sigsci-module-java-{version}-shaded.jar (an uber jar with all the dependencies bundled) to your server classpath.
  • Copy sigsci-module-java-{version}.jar and its dependencies in the lib folder to your server classpath.

Although optional, we recommended adding this library to {jetty.base}/lib/ext, as Jetty automatically loads libraries in this path to the server classpath.

Simple Example Server

For a more complete example, see the sigsci-jetty-simple-example JAR files included in the distribution. This consists of the binaries, source, and javadoc for a simple working example. The binary JAR is executable and can be run with commands similar to the following. These commands will start the simple server and point it at an agent running on TCP port 5000 on the local host, which require an agent started with rpc-address = "127.0.0.1:5000":

$ java -jar examples/sigsci-jetty-simple-example-{version}.jar

That command will produce the following output:

tcp://127.0.0.1:5000
00:00:00.384 [main] INFO c.s.example.SimpleExampleServer - WebRoot is jar:file:/x/sigsci-jetty-simple-example-0.1.3.jar!/webroot/
00:00:00.403 [main] INFO c.s.example.SimpleExampleServer - Signal Sciences WAF: enabled
00:00:00.501 [main] INFO c.s.example.SimpleExampleServer - Signal Sciences Simple Example Server started (http://0.0.0.0:8800/)
00:00:00.986 [qtp123456789-12] INFO c.s.example.RequestLogger - "GET /test/ HTTP/1.1" 302

This example test server will respond with a simple HTML page on the root directory. It can also be used to do basic tests using the /test/ context. In this test context the following parameters are interpreted:

  • response_time: Time in milliseconds to delay the response - to test timeouts.
  • response_code: The HTTP response code to return in the response.
  • size: The size of the response body in bytes.

For example:

$ curl -D- "http://127.0.0.1:8800/test/?response_code=302&response_time=10&size=86"

That command will produce the following output:

HTTP/1.1 302 Found
Date: Sat, 01 Sep 2016 00:00:00 GMT
Location: /
Content-Length: 86
Server: Jetty(9.2.z-SNAPSHOT)
Was this guide helpful?

Do not use this form to send sensitive information. If you need assistance, contact support. This form is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.