diff --git a/conf/zeppelin-site.xml.template b/conf/zeppelin-site.xml.template
index cbe0b5cd6d..bd8d7dd8ba 100755
--- a/conf/zeppelin-site.xml.template
+++ b/conf/zeppelin-site.xml.template
@@ -304,4 +304,10 @@
Size in characters of the maximum text message to be received by websocket. Defaults to 1024000
+
+ zeppelin.server.default.dir.allowed
+ false
+ Enable directory listings on server.
+
+
diff --git a/docs/install/configuration.md b/docs/install/configuration.md
index 56f6404ae7..befb52004f 100644
--- a/docs/install/configuration.md
+++ b/docs/install/configuration.md
@@ -260,6 +260,12 @@ If both are defined, then the **environment variables** will take priority.
1024000 |
Size (in characters) of the maximum text message that can be received by websocket. |
+
+ | ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED |
+ zeppelin.server.default.dir.allowed |
+ false |
+ Enable directory listings on server. |
+
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
index 371d0a131d..0657127765 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
@@ -346,6 +346,9 @@ public class ZeppelinServer extends Application {
webApp.addFilter(new FilterHolder(CorsFilter.class), "/*",
EnumSet.allOf(DispatcherType.class));
+ webApp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed",
+ Boolean.toString(conf.getBoolean(ConfVars.ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED)));
+
return webApp;
}
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/security/DirAccessTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/security/DirAccessTest.java
new file mode 100644
index 0000000000..820d0bad4d
--- /dev/null
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/security/DirAccessTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.zeppelin.security;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.apache.zeppelin.rest.AbstractTestRestApi;
+import org.junit.Test;
+
+public class DirAccessTest extends AbstractTestRestApi {
+
+ @Test
+ public void testDirAccessForbidden() throws Exception {
+ System.setProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED.getVarName(), "false");
+ AbstractTestRestApi.startUpWithAuthenticationEnable();
+ HttpClient httpClient = new HttpClient();
+ GetMethod getMethod = new GetMethod(getUrlToTest() + "/app/");
+ httpClient.executeMethod(getMethod);
+ AbstractTestRestApi.shutDown();
+ assert getMethod.getStatusCode() == HttpStatus.SC_FORBIDDEN;
+ }
+
+ @Test
+ public void testDirAccessOk() throws Exception {
+ System.setProperty(ZeppelinConfiguration.ConfVars.ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED.getVarName(), "true");
+ AbstractTestRestApi.startUpWithAuthenticationEnable();
+ HttpClient httpClient = new HttpClient();
+ GetMethod getMethod = new GetMethod(getUrlToTest() + "/app/");
+ httpClient.executeMethod(getMethod);
+ AbstractTestRestApi.shutDown();
+ assert getMethod.getStatusCode() == HttpStatus.SC_OK;
+ }
+
+ protected static String getUrlToTest() {
+ String url = "http://localhost:8080";
+ if (System.getProperty("url") != null) {
+ url = System.getProperty("url");
+ }
+ return url;
+ }
+}
+
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
index 259f9485be..2c8d91cde2 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
@@ -607,7 +607,8 @@ public class ZeppelinConfiguration extends XMLConfiguration {
ZEPPELIN_ALLOWED_ORIGINS("zeppelin.server.allowed.origins", "*"),
ZEPPELIN_ANONYMOUS_ALLOWED("zeppelin.anonymous.allowed", true),
ZEPPELIN_CREDENTIALS_PERSIST("zeppelin.credentials.persist", true),
- ZEPPELIN_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE("zeppelin.websocket.max.text.message.size", "1024000");
+ ZEPPELIN_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE("zeppelin.websocket.max.text.message.size", "1024000"),
+ ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED("zeppelin.server.default.dir.allowed", false);
private String varName;
@SuppressWarnings("rawtypes")