diff --git a/apm-dist/bin/webappService.bat b/apm-dist/bin/webappService.bat index 1627db45a..049164a8c 100644 --- a/apm-dist/bin/webappService.bat +++ b/apm-dist/bin/webappService.bat @@ -37,5 +37,5 @@ if not defined JAVA_HOME ( set _EXECJAVA=java ) -start "%WEBAPP_PROCESS_TITLE%" %_EXECJAVA% -jar %JARPATH%/skywalking-webapp.jar --server.port=8080 --collector.ribbon.listOfServers=127.0.0.1:10800 --logging.file=%LOG_FILE_LOCATION% --collector.ribbon.ReadTimeout=10000 +start "%WEBAPP_PROCESS_TITLE%" %_EXECJAVA% -jar %JARPATH%/skywalking-webapp.jar --spring.config.location=%JAR_PATH%/webapp.yml --logging.file=%LOG_FILE_LOCATION% endlocal diff --git a/apm-dist/bin/webappService.sh b/apm-dist/bin/webappService.sh index 194e8d9c3..df0040dc7 100644 --- a/apm-dist/bin/webappService.sh +++ b/apm-dist/bin/webappService.sh @@ -34,9 +34,8 @@ _RUNJAVA=${JAVA_HOME}/bin/java [ -z "$JAVA_HOME" ] && _RUNJAVA=java eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/skywalking-webapp.jar \ - --server.port=8080 --collector.ribbon.listOfServers=127.0.0.1:10800 \ + --spring.config.location=${JAR_PATH}/webapp.yml \ --logging.file=${LOG_FILE_LOCATION} \ - --collector.ribbon.ReadTimeout=10000 \ 2>${WEBAPP_LOG_DIR}/webapp-console.log 1> /dev/null &" if [ $? -eq 0 ]; then diff --git a/apm-dist/src/main/assembly/binary.xml b/apm-dist/src/main/assembly/binary.xml index afdb0c094..193e69343 100644 --- a/apm-dist/src/main/assembly/binary.xml +++ b/apm-dist/src/main/assembly/binary.xml @@ -75,5 +75,10 @@ /webapp 0644 + + ${project.basedir}/../apm-webapp/src/main/assembly/webapp.yml + /webapp + 0644 + diff --git a/apm-webapp/src/main/assembly/webapp.yml b/apm-webapp/src/main/assembly/webapp.yml new file mode 100644 index 000000000..8e0f7d195 --- /dev/null +++ b/apm-webapp/src/main/assembly/webapp.yml @@ -0,0 +1,29 @@ +# 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. + +server: + port: 8080 + +collector: + path: /graphql + ribbon: + ReadTimeout: 10000 + listOfServers: 127.0.0.1:10800 + +security: + user: + admin: + password: admin diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/ApplicationStartUp.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/ApplicationStartUp.java index 5f3fe6102..f8f3dde22 100644 --- a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/ApplicationStartUp.java +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/ApplicationStartUp.java @@ -18,25 +18,17 @@ package org.apache.skywalking.apm.webapp; -import org.apache.skywalking.apm.webapp.config.UIConfig; -import org.apache.skywalking.apm.webapp.tools.RewritePathFilter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableZuulProxy public class ApplicationStartUp extends SpringBootServletInitializer { - public static void main(String[] args) throws Exception { - ApplicationContext applicationContext = SpringApplication.run(ApplicationStartUp.class, args); - } - - @Bean - public RewritePathFilter addWritePathFilter(UIConfig uiConfig) { - return new RewritePathFilter(uiConfig.getRewritePath()); + public static void main(String[] args) { + SpringApplication.run(ApplicationStartUp.class, args); } + } diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/CollectorServerList.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/CollectorServerList.java similarity index 98% rename from apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/CollectorServerList.java rename to apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/CollectorServerList.java index 95f3c2ecf..2df2b0d67 100644 --- a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/CollectorServerList.java +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/CollectorServerList.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.webapp.tools; +package org.apache.skywalking.apm.webapp.proxy; import com.google.common.base.Strings; import com.google.common.collect.Lists; diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/HttpClientTools.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/HttpClientTools.java similarity index 98% rename from apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/HttpClientTools.java rename to apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/HttpClientTools.java index da162a83b..8fcc974ab 100644 --- a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/HttpClientTools.java +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/HttpClientTools.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.webapp.tools; +package org.apache.skywalking.apm.webapp.proxy; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/RewritePathFilter.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/RewritePathFilter.java similarity index 80% rename from apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/RewritePathFilter.java rename to apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/RewritePathFilter.java index e3303f821..83450aa7c 100644 --- a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/tools/RewritePathFilter.java +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/proxy/RewritePathFilter.java @@ -16,10 +16,12 @@ * */ -package org.apache.skywalking.apm.webapp.tools; +package org.apache.skywalking.apm.webapp.proxy; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER; @@ -28,17 +30,23 @@ import static org.springframework.cloud.netflix.zuul.filters.support.FilterConst * * @author gaohongtao */ +@Component +@ConfigurationProperties(prefix = "collector") public class RewritePathFilter extends ZuulFilter { private static final String REQUEST_URI = "requestURI"; - private static final int ORDER = PRE_DECORATION_FILTER_ORDER + 1; + private static final int ORDER = PRE_DECORATION_FILTER_ORDER + 2; + + private String path; - public RewritePathFilter(String rewritePath) { - this.rewritePath = rewritePath; + public String getPath() { + return path; } - private final String rewritePath; + public void setPath(String path) { + this.path = path; + } @Override public int filterOrder() { @@ -59,7 +67,7 @@ public class RewritePathFilter extends ZuulFilter { @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); - ctx.set(REQUEST_URI, rewritePath); + ctx.set(REQUEST_URI, path); return null; } } diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/config/UIConfig.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/Account.java similarity index 68% rename from apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/config/UIConfig.java rename to apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/Account.java index c5a1f298c..cb33d86f7 100644 --- a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/config/UIConfig.java +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/Account.java @@ -16,21 +16,16 @@ * */ -package org.apache.skywalking.apm.webapp.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; +package org.apache.skywalking.apm.webapp.security; /** - * @author peng-yongsheng + * Account of Login. + * + * @author gaohongtao */ -@Configuration -public class UIConfig { - - @Value("${collector.path}") - private String rewritePath; +public interface Account { - public String getRewritePath() { - return rewritePath; - } + String userName(); + + String password(); } diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/LoginFilter.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/LoginFilter.java new file mode 100644 index 000000000..4c696beec --- /dev/null +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/LoginFilter.java @@ -0,0 +1,96 @@ +/* + * 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.skywalking.apm.webapp.security; + +import com.google.gson.Gson; +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.util.ReflectionUtils; + +import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER; + +/** + * Filter login request. + * + * @author gaohongtao + */ +@Component +public class LoginFilter extends ZuulFilter { + + private static final String REQUEST_URI = "requestURI"; + + private static final String LOGIN_URI = "/login/account"; + + private static final int ORDER = PRE_DECORATION_FILTER_ORDER + 1; + + private final UserChecker checker; + + public LoginFilter(final UserChecker checker) { + this.checker = checker; + } + + @Override public String filterType() { + return "pre"; + } + + @Override public int filterOrder() { + return ORDER; + } + + @Override public boolean shouldFilter() { + RequestContext ctx = RequestContext.getCurrentContext(); + return ctx.get(REQUEST_URI).equals(LOGIN_URI); + } + + @Override public Object run() { + RequestContext ctx = RequestContext.getCurrentContext(); + Account loginAccount = null; + try { + loginAccount = ReaderAccount.newReaderAccount(ctx.getRequest().getReader()); + } catch (IOException e) { + ReflectionUtils.rethrowRuntimeException(e); + } + Gson gson = new Gson(); + String resStr; + if (checker.check(loginAccount)) { + resStr = gson.toJson(new ResponseData("ok", "admin")); + } else { + resStr = gson.toJson(new ResponseData("error", "guest")); + } + HttpServletResponse response = ctx.getResponse(); + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + ctx.setResponseStatusCode(HttpServletResponse.SC_OK); + ctx.setResponseBody(resStr); + ctx.setSendZuulResponse(false); + return null; + } + + private static class ResponseData { + private final String status; + private final String currentAuthority; + ResponseData(final String status, final String currentAuthority) { + this.status = status; + this.currentAuthority = currentAuthority; + } + } +} diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/ReaderAccount.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/ReaderAccount.java new file mode 100644 index 000000000..9709f737d --- /dev/null +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/ReaderAccount.java @@ -0,0 +1,50 @@ +/* + * 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.skywalking.apm.webapp.security; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.BufferedReader; + +/** + * A container of login information. + * + * @author gaohongtao + */ +class ReaderAccount implements Account { + + private final static Gson GSON = new GsonBuilder().disableHtmlEscaping() + .setLenient().create(); + + private String userName; + + private String password; + + static ReaderAccount newReaderAccount(final BufferedReader accountReader) { + return GSON.fromJson(accountReader, ReaderAccount.class); + } + + public String userName() { + return userName; + } + + public String password() { + return password; + } +} diff --git a/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/UserChecker.java b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/UserChecker.java new file mode 100644 index 000000000..785fe3516 --- /dev/null +++ b/apm-webapp/src/main/java/org/apache/skywalking/apm/webapp/security/UserChecker.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.skywalking.apm.webapp.security; + +import com.google.common.base.Strings; +import java.util.HashMap; +import java.util.Map; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * A Checker to check username and password. + * + * @author gaohongtao + */ +@Component +@ConfigurationProperties(prefix = "security") +public class UserChecker { + + private Map user = new HashMap<>(); + + public Map getUser() { + return user; + } + + boolean check(Account account) { + if (Strings.isNullOrEmpty(account.userName()) || Strings.isNullOrEmpty(account.password())) { + return false; + } + if (!user.containsKey(account.userName())) { + return false; + } + return user.get(account.userName()).password.equals(account.password()); + } + + public static class User { + private String password; + + public void setPassword(String password) { + this.password = password; + } + } +} diff --git a/apm-webapp/src/main/resources/application.yml b/apm-webapp/src/main/resources/application.yml index 20d57d51d..69e5c9658 100644 --- a/apm-webapp/src/main/resources/application.yml +++ b/apm-webapp/src/main/resources/application.yml @@ -28,3 +28,8 @@ collector: ribbon: listOfServers: 127.0.0.1:10800 NIWSServerListClassName: org.apache.skywalking.apm.webapp.tools.CollectorServerList + +security: + user: + admin: + password: admin diff --git a/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/tools/RewritePathFilterTest.java b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/proxy/RewritePathFilterTest.java similarity index 89% rename from apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/tools/RewritePathFilterTest.java rename to apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/proxy/RewritePathFilterTest.java index b856fb608..013d96d3f 100644 --- a/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/tools/RewritePathFilterTest.java +++ b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/proxy/RewritePathFilterTest.java @@ -1,60 +1,60 @@ -/* - * 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.skywalking.apm.webapp.tools; - -import com.netflix.zuul.context.RequestContext; -import org.junit.Before; -import org.junit.Test; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; -import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER; - -public class RewritePathFilterTest { - - private RewritePathFilter filter; - - @Before - public void init() { - filter = new RewritePathFilter("/graphql"); - } - - @Test - public void filterOrder() { - assertThat(filter.filterOrder(), is(PRE_DECORATION_FILTER_ORDER + 1)); - } - - @Test - public void filterType() { - assertThat(filter.filterType(), is("pre")); - } - - @Test - public void shouldFilter() { - assertFalse(filter.shouldFilter()); - RequestContext.getCurrentContext().set("requestURI"); - assertTrue(filter.shouldFilter()); - } - - @Test - public void run() { - filter.run(); - assertThat(RequestContext.getCurrentContext().get("requestURI"), is("/graphql")); - } +/* + * 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.skywalking.apm.webapp.proxy; + +import com.netflix.zuul.context.RequestContext; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; +import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER; + +public class RewritePathFilterTest { + + private RewritePathFilter filter = new RewritePathFilter(); + + @Before + public void init() { + filter.setPath("/graphql"); + } + + @Test + public void filterOrder() { + assertThat(filter.filterOrder(), is(PRE_DECORATION_FILTER_ORDER + 2)); + } + + @Test + public void filterType() { + assertThat(filter.filterType(), is("pre")); + } + + @Test + public void shouldFilter() { + assertFalse(filter.shouldFilter()); + RequestContext.getCurrentContext().set("requestURI"); + assertTrue(filter.shouldFilter()); + } + + @Test + public void run() { + filter.run(); + assertThat(RequestContext.getCurrentContext().get("requestURI"), is("/graphql")); + } } \ No newline at end of file diff --git a/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/LoginFilterTest.java b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/LoginFilterTest.java new file mode 100644 index 000000000..cb20ba2ef --- /dev/null +++ b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/LoginFilterTest.java @@ -0,0 +1,70 @@ +/* + * 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.skywalking.apm.webapp.security; + +import com.netflix.zuul.context.RequestContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER; + + +public class LoginFilterTest { + + private LoginFilter loginFilter; + + @Before + public void setUp() { + UserChecker checker = new UserChecker(); + UserChecker.User user = new UserChecker.User(); + user.setPassword("admin"); + checker.getUser().put("admin", user); + loginFilter = new LoginFilter(checker); + } + + @After + public void tearDown() { + RequestContext.testSetCurrentContext(null); + } + + @Test + public void assertFilterType() { + assertThat(loginFilter.filterType(), is("pre")); + } + + @Test + public void assertFilterOrder() { + assertThat(loginFilter.filterOrder(), is(PRE_DECORATION_FILTER_ORDER + 1)); + } + + @Test + public void assertShouldFilter() { + RequestContext ctx = new RequestContext(); + ctx.set("requestURI", "/login/account"); + RequestContext.testSetCurrentContext(ctx); + assertTrue(loginFilter.shouldFilter()); + ctx.set("requestURI", "/dashboard"); + assertFalse(loginFilter.shouldFilter()); + } +} \ No newline at end of file diff --git a/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/LoginTest.java b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/LoginTest.java new file mode 100644 index 000000000..e077d5149 --- /dev/null +++ b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/LoginTest.java @@ -0,0 +1,90 @@ +/* + * 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.skywalking.apm.webapp.security; + +import com.netflix.zuul.context.RequestContext; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.UndeclaredThrowableException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class LoginTest { + + private LoginFilter loginFilter; + + @Mock + private RequestContext ctx; + + @Mock + private HttpServletRequest request; + + @Mock + private HttpServletResponse response; + + @Before + public void setUp() { + UserChecker checker = new UserChecker(); + UserChecker.User user = new UserChecker.User(); + user.setPassword("admin"); + checker.getUser().put("admin", user); + loginFilter = new LoginFilter(checker); + when(ctx.getRequest()).thenReturn(request); + when(ctx.getResponse()).thenReturn(response); + RequestContext.testSetCurrentContext(ctx); + } + + @Test + public void assertSuccessLogin() throws IOException { + when(request.getReader()).thenReturn(new BufferedReader(new StringReader("{\"userName\": \"admin\", \"password\":\"admin\"}"))); + loginFilter.run(); + assertHeaderAndStatusCode(); + verify(ctx).setResponseBody("{\"status\":\"ok\",\"currentAuthority\":\"admin\"}"); + } + + @Test + public void assertFailLogin() throws IOException { + when(request.getReader()).thenReturn(new BufferedReader(new StringReader("{\"userName\": \"admin\", \"password\":\"888888\"}"))); + loginFilter.run(); + assertHeaderAndStatusCode(); + verify(ctx).setResponseBody("{\"status\":\"error\",\"currentAuthority\":\"guest\"}"); + } + + @Test(expected = UndeclaredThrowableException.class) + public void assertException() throws IOException { + when(request.getReader()).thenThrow(new IOException()); + loginFilter.run(); + } + + private void assertHeaderAndStatusCode() { + verify(ctx).setResponseStatusCode(HttpServletResponse.SC_OK); + verify(response).setContentType("application/json"); + verify(response).setCharacterEncoding("UTF-8"); + } +} diff --git a/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/ReaderAccountTest.java b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/ReaderAccountTest.java new file mode 100644 index 000000000..3cfe631a3 --- /dev/null +++ b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/ReaderAccountTest.java @@ -0,0 +1,37 @@ +/* + * 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.skywalking.apm.webapp.security; + +import java.io.BufferedReader; +import java.io.StringReader; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class ReaderAccountTest { + + @Test + public void assertNewReaderAccount() { + Account account = ReaderAccount.newReaderAccount(new BufferedReader(new StringReader("{\"userName\": \"admin\", \"password\":\"888888\"}"))); + assertThat(account.userName(), is("admin")); + assertThat(account.password(), is("888888")); + } + +} \ No newline at end of file diff --git a/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/UserCheckerTest.java b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/UserCheckerTest.java new file mode 100644 index 000000000..81c266b41 --- /dev/null +++ b/apm-webapp/src/test/java/org/apache/skywalking/apm/webapp/security/UserCheckerTest.java @@ -0,0 +1,96 @@ +/* + * 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.skywalking.apm.webapp.security; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class UserCheckerTest { + + @Test + public void assertCheckSuccess() { + UserChecker checker = new UserChecker(); + UserChecker.User user = new UserChecker.User(); + user.setPassword("888888"); + checker.getUser().put("admin", user); + assertTrue(checker.check(new Account() { + @Override public String userName() { + return "admin"; + } + + @Override public String password() { + return "888888"; + } + })); + } + + @Test + public void assertCheckFail() { + UserChecker checker = new UserChecker(); + UserChecker.User user = new UserChecker.User(); + user.setPassword("123456"); + checker.getUser().put("guest", user); + assertFalse(checker.check(new Account() { + @Override public String userName() { + return "admin"; + } + + @Override public String password() { + return "888888"; + } + })); + assertFalse(checker.check(new Account() { + @Override public String userName() { + return "guest"; + } + + @Override public String password() { + return "888888"; + } + })); + assertFalse(checker.check(new Account() { + @Override public String userName() { + return "admin"; + } + + @Override public String password() { + return "123456"; + } + })); + assertFalse(checker.check(new Account() { + @Override public String userName() { + return ""; + } + + @Override public String password() { + return "123456"; + } + })); + assertFalse(checker.check(new Account() { + @Override public String userName() { + return "admin"; + } + + @Override public String password() { + return ""; + } + })); + } +} \ No newline at end of file diff --git a/docs/cn/Deploy-backend-in-cluster-mode-CN.md b/docs/cn/Deploy-backend-in-cluster-mode-CN.md index 4252e0308..d506d0acb 100644 --- a/docs/cn/Deploy-backend-in-cluster-mode-CN.md +++ b/docs/cn/Deploy-backend-in-cluster-mode-CN.md @@ -109,11 +109,14 @@ configuration: 1. 解压安装包 `tar -xvf skywalking-dist.tar.gz`,windows用户可以选择zip包 2. 配置UI集群模式. -UI的配置信息保存在 `bin/webappService.sh` 中 ( windows为`bin\webappService.bat`). +UI的配置信息保存在 `webapp/webapp.yml` 中. | 配置项 | 描述 | |----------------------------------|----------------------------------------------------------------------------------| | `server.port` | 监听端口 | | `collector.ribbon.listOfServers` | collector命名服务地址.(与 `config/application.yml` 中的`naming.jetty`配置保持相同 ),多个Collector地址以`,`分割 | +| `collector.path` | Collector查询uri. 默认: /graphql | +| `collector.ribbon.ReadTimeout` | 查询超时时间. 默认: 10 秒 | +| `security.user.*` | 登录用户名/密码. 默认: admin/admin | 3. 运行 `bin/webappService.sh` diff --git a/docs/cn/Quick-start-CN.md b/docs/cn/Quick-start-CN.md index a718cfbf3..1813beca8 100644 --- a/docs/cn/Quick-start-CN.md +++ b/docs/cn/Quick-start-CN.md @@ -4,4 +4,5 @@ 1. [单机模式](Deploy-backend-in-standalone-mode-CN.md) 1. [集群模式](Deploy-backend-in-cluster-mode-CN.md) 1. 部署 Java Agent,[doc](Deploy-skywalking-agent-CN.md) -1. 重启并访问系统功能,查看UI即可。 \ No newline at end of file +1. 重启并访问系统功能,查看UI即可。 +1. 登录页面的默认用户名/密码是`admin/admin`。 \ No newline at end of file diff --git a/docs/en/Deploy-backend-in-cluster-mode.md b/docs/en/Deploy-backend-in-cluster-mode.md index d8745b16f..3cc0a4915 100644 --- a/docs/en/Deploy-backend-in-cluster-mode.md +++ b/docs/en/Deploy-backend-in-cluster-mode.md @@ -131,14 +131,16 @@ configuration: ### Set UI -The config items of UI is saved in `bin/webappService.sh` (`bin\webappService.bat` for windows). +The config items of UI is saved in `webapp/webapp.yml`. Change `collector.ribbon.listOfServers` by following the description, with matching `naming.jetty`. | Config | Description | |----------------------------------|------------------------------------------------------------------------------------------------------| | `server.port` | Port to listen on. Default: 8080 | | `collector.ribbon.listOfServers` | Address to access collector naming service.(Consist with `naming.jetty` in `config/application.yml`). Multiple collector addresses are split by ',' | - +| `collector.path` | Collector query uri. Default: /graphql | +| `collector.ribbon.ReadTimeout` | Query timeout. Default: 10 seconds | +| `security.user.*` | Login username/password. Default: admin/admin | ### Start up collector node 1. Run `bin/startup.sh` to start collector and UI together. diff --git a/docs/en/Quick-start.md b/docs/en/Quick-start.md index e259d36b1..f553453b1 100644 --- a/docs/en/Quick-start.md +++ b/docs/en/Quick-start.md @@ -6,6 +6,7 @@ Quick start is for end users to start up the SkyWalking quickly in local. 1. Install Java Agent. [Doc](Deploy-skywalking-agent.md) 1. Set your OS time(include time zone) correct. 1. Reboot your applications, and open UI. +1. Default username/password for the login page is `admin/admin`. If you want to deploy SkyWalking in server or cloud as a cluster, please following these two documents: 1. [Install javaagent](Deploy-skywalking-agent.md)