diff --git a/pom.xml b/pom.xml index 641880e06d5..7b708563271 100644 --- a/pom.xml +++ b/pom.xml @@ -99,7 +99,9 @@ 1.7.10 1.2.17 0.9.2 + 1.14.2 2.2 + 4.1.0 0.2.1 9.2.15.v20160210 4.4.1 @@ -203,6 +205,12 @@ ${gson.version} + + com.google.inject + guice + ${guice.version} + + org.danilopianini gson-extras diff --git a/zeppelin-interpreter/pom.xml b/zeppelin-interpreter/pom.xml index b0fd9920908..69c44ad5540 100644 --- a/zeppelin-interpreter/pom.xml +++ b/zeppelin-interpreter/pom.xml @@ -186,9 +186,19 @@ org.apache.maven.wagon wagon-provider-api + + org.sonatype.sisu + sisu-guice + + + com.google.inject + guice + ${guice.version} + + org.apache.maven.wagon wagon-provider-api diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java index 77279edcd39..5f70d849491 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java @@ -265,6 +265,14 @@ public boolean getBoolean(String envName, String propertyName, boolean defaultVa return getBooleanValue(propertyName, defaultValue); } + public Class getClass(ConfVars c) { + try { + return Class.forName(c.getStringValue()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + public boolean useSsl() { return getBoolean(ConfVars.ZEPPELIN_SSL); } @@ -351,6 +359,14 @@ public String getTrustStorePassword() { } } + public Class getZeppelinWebSecurityClassname() { + return getClass(ConfVars.ZEPPELIN_WEB_SECURITY_CLASSNAME); + } + + public Class getZeppelinSearchServiceClassname() { + return getClass(ConfVars.ZEPPELIN_SEARCH_SERVICE_CLASSNAME); + } + public String getNotebookDir() { return getString(ConfVars.ZEPPELIN_NOTEBOOK_DIR); } @@ -720,6 +736,11 @@ public static enum ConfVars { ZEPPELIN_CREDENTIALS_PERSIST("zeppelin.credentials.persist", true), ZEPPELIN_CREDENTIALS_ENCRYPT_KEY("zeppelin.credentials.encryptKey", null), ZEPPELIN_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE("zeppelin.websocket.max.text.message.size", "1024000"), + ZEPPELIN_USE_JDBC_ALIAS("zeppelin.use.jdbc.alias", true), + ZEPPELIN_WEB_SECURITY_CLASSNAME("zeppelin.web.security.classname", + "org.apache.zeppelin.web.DefaultWebSecurity"), + ZEPPELIN_SEARCH_SERVICE_CLASSNAME("zeppelin.search.service.classname", + "org.apache.zeppelin.search.LuceneSearch"), ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED("zeppelin.server.default.dir.allowed", false), ZEPPELIN_SERVER_XFRAME_OPTIONS("zeppelin.server.xframe.options", "SAMEORIGIN"), ZEPPELIN_SERVER_JETTY_NAME("zeppelin.server.jetty.name", null), diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/inject/ZeppelinModule.java b/zeppelin-server/src/main/java/org/apache/zeppelin/inject/ZeppelinModule.java new file mode 100644 index 00000000000..c997d141a79 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/inject/ZeppelinModule.java @@ -0,0 +1,56 @@ +/* + * 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.inject; + +import com.google.inject.Binder; +import com.google.inject.Module; +import com.google.inject.Provides; +import org.apache.zeppelin.conf.ZeppelinConfiguration; +import org.apache.zeppelin.search.SearchService; +import org.apache.zeppelin.server.ZeppelinServer; +import org.apache.zeppelin.web.WebSecurity; + +/** + * Guice injection module. + */ +public class ZeppelinModule implements Module { + private ZeppelinConfiguration conf; + + public ZeppelinModule(ZeppelinConfiguration conf) { + this.conf = conf; + } + + @Override + public void configure(Binder binder) { + + binder.bind(WebSecurity.class) + .to((Class) conf.getZeppelinWebSecurityClassname()); + + binder.bind(SearchService.class) + .to((Class) conf.getZeppelinSearchServiceClassname()); + + binder.requestStaticInjection(ZeppelinServer.class); + + } + + @Provides + public ZeppelinConfiguration getZeppelinConfiguration() { + return conf; + } + +} 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 f8625c2357c..85bc53e9983 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 @@ -9,7 +9,7 @@ * 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, + * 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. @@ -17,6 +17,13 @@ package org.apache.zeppelin.server; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Inject; + +import org.apache.zeppelin.web.WebSecurity; +import org.apache.zeppelin.inject.ZeppelinModule; + import java.io.File; import java.io.IOException; import java.util.EnumSet; @@ -78,17 +85,26 @@ public class ZeppelinServer extends Application { public static Server jettyWebServer; public static NotebookServer notebookWsServer; public static Helium helium; + public static HeliumApplicationFactory heliumApplicationFactory; + public static Injector injector; + @Inject + private static WebSecurity webSecurity; private final InterpreterSettingManager interpreterSettingManager; private SchedulerFactory schedulerFactory; private InterpreterFactory replFactory; + + @Inject + private ZeppelinConfiguration conf; + @Inject private SearchService noteSearchService; private NotebookRepoSync notebookRepo; private NotebookAuthorization notebookAuthorization; private Credentials credentials; public ZeppelinServer() throws Exception { - ZeppelinConfiguration conf = ZeppelinConfiguration.create(); + + injector.injectMembers(this); @@ -158,6 +174,7 @@ public ZeppelinServer() throws Exception { notebook.addNotebookEventListener(heliumApplicationFactory); notebook.addNotebookEventListener(notebookWsServer.getNotebookInformationListener()); + } public static void main(String[] args) throws InterruptedException { @@ -165,6 +182,8 @@ public static void main(String[] args) throws InterruptedException { final ZeppelinConfiguration conf = ZeppelinConfiguration.create(); conf.setProperty("args", args); + injector = Guice.createInjector(new ZeppelinModule(conf)); + jettyWebServer = setupJettyServer(conf); ContextHandlerCollection contexts = new ContextHandlerCollection(); @@ -330,14 +349,8 @@ private static void setupRestApiContextHandler(WebAppContext webapp, webapp.setSessionHandler(new SessionHandler()); webapp.addServlet(servletHolder, "/api/*"); - String shiroIniPath = conf.getShiroPath(); - if (!StringUtils.isBlank(shiroIniPath)) { - webapp.setInitParameter("shiroConfigLocations", new File(shiroIniPath).toURI().toString()); - SecurityUtils.setIsEnabled(true); - webapp.addFilter(ShiroFilter.class, "/api/*", EnumSet.allOf(DispatcherType.class)) - .setInitParameter("staticSecurityManagerEnabled", "true"); - webapp.addEventListener(new EnvironmentLoaderListener()); - } + webSecurity.addSecurityFilter(webapp); + } private static WebAppContext setupWebAppContext(ContextHandlerCollection contexts, @@ -363,8 +376,7 @@ private static WebAppContext setupWebAppContext(ContextHandlerCollection context webApp.addServlet(new ServletHolder(new DefaultServlet()), "/*"); contexts.addHandler(webApp); - webApp.addFilter(new FilterHolder(CorsFilter.class), "/*", - EnumSet.allOf(DispatcherType.class)); + webSecurity.addCorFilter(webApp); webApp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", Boolean.toString(conf.getBoolean(ConfVars.ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED))); diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/web/DefaultWebSecurity.java b/zeppelin-server/src/main/java/org/apache/zeppelin/web/DefaultWebSecurity.java new file mode 100644 index 00000000000..82040587ff9 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/web/DefaultWebSecurity.java @@ -0,0 +1,66 @@ +/* + * 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.web; + +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.web.env.EnvironmentLoaderListener; +import org.apache.shiro.web.servlet.ShiroFilter; +import org.apache.zeppelin.conf.ZeppelinConfiguration; +import org.apache.zeppelin.server.CorsFilter; +import org.apache.zeppelin.utils.SecurityUtils; +import org.eclipse.jetty.servlet.FilterHolder; +import org.eclipse.jetty.webapp.WebAppContext; + +import javax.inject.Inject; +import javax.servlet.DispatcherType; +import java.io.File; +import java.util.EnumSet; + +/** + * Default implementation of the actions to be taken + * by Zeppelin to secure the Web channel. + */ +public class DefaultWebSecurity implements WebSecurity { + + @Inject + private ZeppelinConfiguration conf; + + @Override + public void addCorFilter(WebAppContext webApp) { + + webApp.addFilter(new FilterHolder(CorsFilter.class), "/*", + EnumSet.allOf(DispatcherType.class)); + + } + + @Override + public void addSecurityFilter(WebAppContext webapp) { + + String shiroIniPath = conf.getShiroPath(); + + if (!StringUtils.isBlank(shiroIniPath)) { + webapp.setInitParameter("shiroConfigLocations", new File(shiroIniPath).toURI().toString()); + SecurityUtils.setIsEnabled(true); + webapp.addFilter(ShiroFilter.class, "/api/*", EnumSet.allOf(DispatcherType.class)) + .setInitParameter("staticSecurityManagerEnabled", "true"); + webapp.addEventListener(new EnvironmentLoaderListener()); + } + + } + +} diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/web/WebSecurity.java b/zeppelin-server/src/main/java/org/apache/zeppelin/web/WebSecurity.java new file mode 100644 index 00000000000..29a9b4e1a65 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/web/WebSecurity.java @@ -0,0 +1,32 @@ +/* + * 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.web; + +import org.eclipse.jetty.webapp.WebAppContext; + +/** + * Definition of the actions to be taken + * by Zeppelin to secure the Web channel. + */ +public interface WebSecurity { + + void addCorFilter(WebAppContext webApp); + + void addSecurityFilter(WebAppContext webApp); + +} diff --git a/zeppelin-zengine/pom.xml b/zeppelin-zengine/pom.xml index fd2d1dca961..b38e864f7e5 100644 --- a/zeppelin-zengine/pom.xml +++ b/zeppelin-zengine/pom.xml @@ -169,6 +169,12 @@ 15.0 + + org.codehaus.plexus + plexus-utils + 2.0.7 + + org.apache.lucene lucene-core diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/search/LuceneSearch.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/search/LuceneSearch.java index b43c45365d1..5cf8902ea3a 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/search/LuceneSearch.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/search/LuceneSearch.java @@ -39,7 +39,6 @@ import org.apache.lucene.index.Term; import org.apache.lucene.queryparser.classic.MultiFieldQueryParser; import org.apache.lucene.queryparser.classic.ParseException; -import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc;