From 1fb1f5f3e37e2b4fafd4ac572b5d3b6d106aada1 Mon Sep 17 00:00:00 2001 From: nkorange Date: Tue, 14 Jan 2020 18:01:00 +0800 Subject: [PATCH] #1105 Add auth test case for config --- .../client/config/http/ServerHttpAgent.java | 10 +- .../client/config/impl/ClientWorker.java | 6 +- .../server/controller/ConfigController.java | 7 +- .../server/controller/ConfigServletInner.java | 3 + .../src/main/resources/META-INF/nacos-db.sql | 3 +- config/src/main/resources/META-INF/schema.sql | 3 +- .../console/controller/HealthController.java | 4 +- .../controller/ServerStateController.java | 2 +- .../nacos/roles/NacosRoleServiceImpl.java | 16 +- .../src/main/resources/application.properties | 3 + .../alibaba/nacos/core/auth/AuthFilter.java | 16 +- .../alibaba/nacos/core/auth/Permission.java | 7 + distribution/pom.xml | 1 + .../nacos/test/core/auth/AuthBase.java | 28 ++ .../test/core/auth/ConfigAuth_ITCase.java | 271 ++++++++++++++++++ .../test/core/auth/NamingAuth_ITCase.java | 177 ++++++++++++ .../src/test/resources/application.properties | 4 +- 17 files changed, 538 insertions(+), 23 deletions(-) create mode 100644 test/src/test/java/com/alibaba/nacos/test/core/auth/AuthBase.java create mode 100644 test/src/test/java/com/alibaba/nacos/test/core/auth/ConfigAuth_ITCase.java create mode 100644 test/src/test/java/com/alibaba/nacos/test/core/auth/NamingAuth_ITCase.java diff --git a/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java b/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java index 5a521493c..cf0c8fcfb 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java @@ -274,14 +274,14 @@ public class ServerHttpAgent implements HttpAgent { } private void injectSecurityInfo(List params) { - ArrayList list = (ArrayList) params; + //ArrayList list = (ArrayList) params; if (StringUtils.isNotBlank(securityProxy.getAccessToken())) { - list.add(Constants.ACCESS_TOKEN); - list.add(securityProxy.getAccessToken()); + params.add(Constants.ACCESS_TOKEN); + params.add(securityProxy.getAccessToken()); } if (StringUtils.isNotBlank(namespaceId)) { - list.add("tenant"); - list.add(namespaceId); + params.add("tenant"); + params.add(namespaceId); } } diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java index 31c34040e..f17ddccb3 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java @@ -359,7 +359,10 @@ public class ClientWorker { */ List checkUpdateConfigStr(String probeUpdateString, boolean isInitializingCacheList) throws IOException { - List params = Arrays.asList(Constants.PROBE_MODIFY_REQUEST, probeUpdateString); + + List params = new ArrayList(2); + params.add(Constants.PROBE_MODIFY_REQUEST); + params.add(probeUpdateString); List headers = new ArrayList(2); headers.add("Long-Pulling-Timeout"); @@ -516,6 +519,7 @@ public class ClientWorker { // check server config List changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList); + LOGGER.info("get changedGroupKeys:" + changedGroupKeys); for (String groupKey : changedGroupKeys) { String[] key = GroupKey.parseKey(groupKey); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java index d366a3e8c..b55154a9f 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java @@ -282,6 +282,8 @@ public class ConfigController { throw new IllegalArgumentException("invalid probeModify"); } + log.info("listen config id:" + probeModify); + probeModify = URLDecoder.decode(probeModify, Constants.ENCODE); Map clientMd5Map; @@ -291,6 +293,8 @@ public class ConfigController { throw new IllegalArgumentException("invalid probeModify"); } + log.info("listen config id 2:" + probeModify); + // do long-polling inner.doPollingConfig(request, response, clientMd5Map, probeModify.length()); } @@ -376,7 +380,7 @@ public class ConfigController { } @DeleteMapping(params = "beta=true") - @Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class) + @Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class) public RestResult stopBeta(@RequestParam(value = "dataId") String dataId, @RequestParam(value = "group") String group, @RequestParam(value = "tenant", required = false, @@ -545,6 +549,7 @@ public class ConfigController { } @PostMapping(params = "clone=true") + @Secured(action = ActionTypes.WRITE, parser = ConfigResourceParser.class) public RestResult> cloneConfig(HttpServletRequest request, @RequestParam(value = "src_user", required = false) String srcUser, @RequestParam(value = "tenant", required = true) String namespace, diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java index 6bc332b55..e82078d47 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java @@ -24,6 +24,7 @@ import com.alibaba.nacos.config.server.service.LongPollingService; import com.alibaba.nacos.config.server.service.PersistService; import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; import com.alibaba.nacos.config.server.utils.*; +import com.alibaba.nacos.core.utils.Loggers; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -98,6 +99,8 @@ public class ConfigServletInner { request.setAttribute("content", newResult); } + Loggers.AUTH.info("new content:" + newResult); + // 禁用缓存 response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", 0); diff --git a/config/src/main/resources/META-INF/nacos-db.sql b/config/src/main/resources/META-INF/nacos-db.sql index 14a2e2b74..0e8b29aa6 100644 --- a/config/src/main/resources/META-INF/nacos-db.sql +++ b/config/src/main/resources/META-INF/nacos-db.sql @@ -186,7 +186,8 @@ CREATE TABLE users ( CREATE TABLE roles ( username varchar(50) NOT NULL, - role varchar(50) NOT NULL + role varchar(50) NOT NULL, + constraint uk_username_role UNIQUE (username,role) ); CREATE TABLE permissions ( diff --git a/config/src/main/resources/META-INF/schema.sql b/config/src/main/resources/META-INF/schema.sql index 43249fd5c..90c499746 100644 --- a/config/src/main/resources/META-INF/schema.sql +++ b/config/src/main/resources/META-INF/schema.sql @@ -181,7 +181,8 @@ CREATE TABLE users ( CREATE TABLE roles ( username varchar(50) NOT NULL, - role varchar(50) NOT NULL + role varchar(50) NOT NULL, + constraint uk_username_role UNIQUE (username,role) ); CREATE TABLE permissions ( diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java b/console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java index f3595bdcb..05006ce55 100644 --- a/console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java +++ b/console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java @@ -51,7 +51,7 @@ public class HealthController { * @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that * Nacos is in broken states. */ - @GetMapping("liveness") + @GetMapping("/liveness") public ResponseEntity liveness() { return ResponseEntity.ok().body("OK"); } @@ -62,7 +62,7 @@ public class HealthController { * @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not * ready. */ - @GetMapping("readiness") + @GetMapping("/readiness") public ResponseEntity readiness(HttpServletRequest request) { boolean isConfigReadiness = isConfigReadiness(); boolean isNamingReadiness = isNamingReadiness(request); diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java b/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java index b18016d4e..80e04d5ed 100644 --- a/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java +++ b/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java @@ -34,7 +34,7 @@ import java.util.Map; @RequestMapping("/v1/console/server") public class ServerStateController { - @GetMapping("state") + @GetMapping("/state") public ResponseEntity serverState() { Map serverState = new HashMap<>(3); serverState.put("standalone_mode",SystemUtils.STANDALONE_MODE ? diff --git a/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java b/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java index 212500b4b..6fd3c0815 100644 --- a/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java +++ b/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java @@ -28,6 +28,7 @@ import com.alibaba.nacos.core.auth.Permission; import com.alibaba.nacos.core.utils.Loggers; import io.jsonwebtoken.lang.Collections; import org.apache.commons.lang3.StringUtils; +import org.apache.mina.util.ConcurrentHashSet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -59,6 +60,8 @@ public class NacosRoleServiceImpl { @Autowired private PermissionPersistService permissionPersistService; + private Set roleSet = new ConcurrentHashSet<>(); + private Map> roleInfoMap = new ConcurrentHashMap<>(); private Map> permissionInfoMap = new ConcurrentHashMap<>(); @@ -70,22 +73,23 @@ public class NacosRoleServiceImpl { if (roleInfoPage == null) { return; } - Set roleSet = new HashSet<>(16); + Set tmpRoleSet = new HashSet<>(16); Map> tmpRoleInfoMap = new ConcurrentHashMap<>(16); for (RoleInfo roleInfo : roleInfoPage.getPageItems()) { if (!tmpRoleInfoMap.containsKey(roleInfo.getUsername())) { tmpRoleInfoMap.put(roleInfo.getUsername(), new ArrayList<>()); } tmpRoleInfoMap.get(roleInfo.getUsername()).add(roleInfo); - roleSet.add(roleInfo.getRole()); + tmpRoleSet.add(roleInfo.getRole()); } Map> tmpPermissionInfoMap = new ConcurrentHashMap<>(16); - for (String role : roleSet) { + for (String role : tmpRoleSet) { Page permissionInfoPage = permissionPersistService.getPermissions(role, 1, Integer.MAX_VALUE); tmpPermissionInfoMap.put(role, permissionInfoPage.getPageItems()); } + roleSet = tmpRoleSet; roleInfoMap = tmpRoleInfoMap; permissionInfoMap = tmpPermissionInfoMap; } catch (Exception e) { @@ -178,6 +182,9 @@ public class NacosRoleServiceImpl { if (userDetailsService.getUser(username) == null) { throw new IllegalArgumentException("user '" + username + "' not found!"); } + if (GLOBAL_ADMIN_ROLE.equals(role)) { + throw new IllegalArgumentException("role '" + GLOBAL_ADMIN_ROLE + "' is not permitted to create!"); + } rolePersistService.addRole(role, username); } @@ -199,6 +206,9 @@ public class NacosRoleServiceImpl { } public void addPermission(String role, String resource, String action) { + if (!roleSet.contains(role)) { + throw new IllegalArgumentException("role " + role + " not found!"); + } permissionPersistService.addPermission(role, resource, action); } diff --git a/console/src/main/resources/application.properties b/console/src/main/resources/application.properties index 585e9e5f8..ff3b421bd 100644 --- a/console/src/main/resources/application.properties +++ b/console/src/main/resources/application.properties @@ -35,3 +35,6 @@ nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/ nacos.core.auth.system.type=nacos nacos.core.auth.enabled=false nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789 + + +tldSkipPatterns=derbyLocale_*.jar,jaxb-api.jar,jsr173_1.0_api.jar,jaxb1-impl.jar,activation.jar diff --git a/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java b/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java index f4f3c6df2..af8026b5e 100644 --- a/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java +++ b/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java @@ -67,7 +67,7 @@ public class AuthFilter implements Filter { } if (Loggers.AUTH.isDebugEnabled()) { - Loggers.AUTH.debug("auth filter start, request: {}", req.getRequestURI()); + Loggers.AUTH.debug("auth filter start, request: {} {}", req.getMethod(), req.getRequestURI()); } try { @@ -76,7 +76,8 @@ public class AuthFilter implements Filter { Method method = methodsCache.getMethod(req.getMethod(), path); if (method == null) { - throw new NoSuchMethodException(); + chain.doFilter(request, response); + return; } if (method.isAnnotationPresent(Secured.class) && authConfigs.isAuthEnabled()) { @@ -95,17 +96,20 @@ public class AuthFilter implements Filter { throw new AccessException("resource name invalid!"); } + if (Loggers.AUTH.isDebugEnabled()) { + Loggers.AUTH.debug("auth now, request: {} {}", req.getMethod(), req.getRequestURI()); + } + authManager.auth(new Permission(resource, action), authManager.login(req)); } } catch (AccessException e) { + if (Loggers.AUTH.isDebugEnabled()) { + Loggers.AUTH.debug("access denied, request: {} {}", req.getMethod(), req.getRequestURI()); + } resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getErrMsg()); return; - } catch (NoSuchMethodException e) { - resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, - "no such api:" + req.getMethod() + ":" + req.getRequestURI()); - return; } catch (IllegalArgumentException e) { resp.sendError(HttpServletResponse.SC_BAD_REQUEST, ExceptionUtil.getAllExceptionMsg(e)); return; diff --git a/core/src/main/java/com/alibaba/nacos/core/auth/Permission.java b/core/src/main/java/com/alibaba/nacos/core/auth/Permission.java index f13379f30..3bbfc4251 100644 --- a/core/src/main/java/com/alibaba/nacos/core/auth/Permission.java +++ b/core/src/main/java/com/alibaba/nacos/core/auth/Permission.java @@ -15,6 +15,8 @@ */ package com.alibaba.nacos.core.auth; +import com.alibaba.fastjson.JSON; + /** * Permission to auth * @@ -57,4 +59,9 @@ public class Permission { public void setAction(String action) { this.action = action; } + + @Override + public String toString() { + return JSON.toJSONString(this); + } } diff --git a/distribution/pom.xml b/distribution/pom.xml index 6fc92dc59..8be78681e 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -206,6 +206,7 @@ release-nacos.xml + posix diff --git a/test/src/test/java/com/alibaba/nacos/test/core/auth/AuthBase.java b/test/src/test/java/com/alibaba/nacos/test/core/auth/AuthBase.java new file mode 100644 index 000000000..2ea15e1f7 --- /dev/null +++ b/test/src/test/java/com/alibaba/nacos/test/core/auth/AuthBase.java @@ -0,0 +1,28 @@ +package com.alibaba.nacos.test.core.auth; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.nacos.test.base.HttpClient4Test; +import com.alibaba.nacos.test.base.Params; +import org.junit.Assert; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; + +public class AuthBase extends HttpClient4Test { + + public String login() { + + ResponseEntity response = request("/nacos/v1/auth/users/login", + Params.newParams() + .appendParam("username", "nacos") + .appendParam("password", "nacos") + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + JSONObject json = JSON.parseObject(response.getBody()); + Assert.assertTrue(json.containsKey("accessToken")); + return json.getString("accessToken"); + } +} diff --git a/test/src/test/java/com/alibaba/nacos/test/core/auth/ConfigAuth_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/core/auth/ConfigAuth_ITCase.java new file mode 100644 index 000000000..df8c4568c --- /dev/null +++ b/test/src/test/java/com/alibaba/nacos/test/core/auth/ConfigAuth_ITCase.java @@ -0,0 +1,271 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.test.core.auth; + +import com.alibaba.nacos.Nacos; +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.config.ConfigChangeEvent; +import com.alibaba.nacos.api.config.ConfigChangeItem; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.api.config.PropertyChangeType; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.client.config.http.HttpAgent; +import com.alibaba.nacos.client.config.listener.impl.AbstractConfigChangeListener; +import com.alibaba.nacos.test.base.Params; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.net.URL; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.fail; + +/** + * @author nkorange + * @since 1.2.0 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7001"}, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ConfigAuth_ITCase extends AuthBase { + + @LocalServerPort + private int port; + + private String accessToken; + + public static final long TIME_OUT = 2000; + + public ConfigService iconfig = null; + + private String dataId = "yanlin"; + private String group = "yanlin"; + + private String username = "username1"; + private String password = "password1"; + private String role = "role1"; + + private Properties properties; + + private String namespace1 = "namespace1"; + private String namespace2 = "namespace2"; + + @Before + public void init() throws Exception { + TimeUnit.SECONDS.sleep(5L); + String url = String.format("http://localhost:%d/", port); + this.base = new URL(url); + + accessToken = login(); + + // Create a user: + ResponseEntity response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", username) + .appendParam("password", password) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Create a role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", role) + .appendParam("username", username) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Add read permission for namespace1: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace1 + ":*:*") + .appendParam("action", "r") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Add read/write permission for namespace2: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace2 + ":*:*") + .appendParam("action", "rw") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Init properties: + properties = new Properties(); + properties.put(PropertyKeyConst.USERNAME, username); + properties.put(PropertyKeyConst.PASSWORD, password); + properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1" + ":" + port); + } + + @After + public void destroy() { + + // Delete permission: + ResponseEntity response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace1 + ":*:*") + .appendParam("action", "r") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace2 + ":*:*") + .appendParam("action", "rw") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete a role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", role) + .appendParam("username", username) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete a user: + response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", username) + .appendParam("password", password) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + } + + + @Test + public void publishConfigWithReadPermission() throws Exception { + + properties.put(PropertyKeyConst.NAMESPACE, namespace1); + // Construct configService: + iconfig = NacosFactory.createConfigService(properties); + + final String content = "test"; + try { + iconfig.publishConfig(dataId, group, content); + fail(); + } catch (NacosException ne) { + Assert.assertEquals(HttpStatus.FORBIDDEN.value(), ne.getErrCode()); + } + } + + @Test + public void publishConfigWithReadWritePermission() throws Exception { + + properties.put(PropertyKeyConst.NAMESPACE, namespace2); + // Construct configService: + iconfig = NacosFactory.createConfigService(properties); + + final String content = "test"; + boolean result = iconfig.publishConfig(dataId, group, content); + Assert.assertTrue(result); + + TimeUnit.SECONDS.sleep(2L); + + String value = iconfig.getConfig(dataId, group, TIME_OUT); + Assert.assertEquals(content, value); + + result = iconfig.removeConfig(dataId, group); + Thread.sleep(TIME_OUT); + Assert.assertTrue(result); + + TimeUnit.SECONDS.sleep(2L); + + value = iconfig.getConfig(dataId, group, TIME_OUT); + System.out.println(value); + Assert.assertNull(value); + } + + @Test + public void listenConfigWithReadWritePermission() throws Exception { + + CountDownLatch latch = new CountDownLatch(1); + + final String dataId = "test" + System.currentTimeMillis(); + final String group = "DEFAULT_GROUP"; + final String content = "config data"; + + properties.put(PropertyKeyConst.NAMESPACE, namespace2); + // Construct configService: + iconfig = NacosFactory.createConfigService(properties); + iconfig.addListener(dataId, group, new AbstractConfigChangeListener() { + @Override + public void receiveConfigChange(ConfigChangeEvent event) { + ConfigChangeItem cci = event.getChangeItem("content"); + Assert.assertEquals(null, cci.getOldValue()); + Assert.assertEquals(content, cci.getNewValue()); + Assert.assertEquals(PropertyChangeType.ADDED, cci.getType()); + System.out.println(cci); + latch.countDown(); + } + + }); + + iconfig.publishConfig(dataId, group, content); + + latch.await(); + } + +} diff --git a/test/src/test/java/com/alibaba/nacos/test/core/auth/NamingAuth_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/core/auth/NamingAuth_ITCase.java new file mode 100644 index 000000000..d871603b2 --- /dev/null +++ b/test/src/test/java/com/alibaba/nacos/test/core/auth/NamingAuth_ITCase.java @@ -0,0 +1,177 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.test.core.auth; + +import com.alibaba.nacos.Nacos; +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.test.base.Params; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Properties; + +/** + * @author nkorange + * @since 1.2.0 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7001"}, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class NamingAuth_ITCase extends AuthBase { + + @LocalServerPort + private int port; + + private String accessToken; + + private String username = "username1"; + private String password = "password1"; + private String role = "role1"; + + private Properties properties; + + private String namespace1 = "namespace1"; + private String namespace2 = "namespace2"; + + @Before + public void init() { + accessToken = login(); + // Create a user: + ResponseEntity response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", username) + .appendParam("password", password) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Create a role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", role) + .appendParam("username", username) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Add read permission for namespace1: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace1 + ":*:*") + .appendParam("action", "r") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Add read/write permission for namespace2: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace2 + ":*:*") + .appendParam("action", "rw") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Init properties: + properties = new Properties(); + properties.put(PropertyKeyConst.USERNAME, username); + properties.put(PropertyKeyConst.PASSWORD, password); + properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1" + ":" + port); + } + + @After + public void destroy() { + + // Delete permission: + ResponseEntity response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace1 + ":*:*") + .appendParam("action", "r") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", role) + .appendParam("resource", namespace2 + ":*:*") + .appendParam("action", "rw") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete a role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", role) + .appendParam("username", username) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete a user: + response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", username) + .appendParam("password", password) + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + } + + @Test + public void writeWithReadPermission() { + + properties.put(PropertyKeyConst.NAMESPACE, namespace1); + } + +} diff --git a/test/src/test/resources/application.properties b/test/src/test/resources/application.properties index 2dca8441e..814d4f575 100644 --- a/test/src/test/resources/application.properties +++ b/test/src/test/resources/application.properties @@ -14,7 +14,7 @@ management.metrics.export.influx.enabled=false #management.metrics.export.influx.consistency=one #management.metrics.export.influx.compressed=true -server.tomcat.accesslog.enabled=false +server.tomcat.accesslog.enabled=true server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D # default current work dir server.tomcat.basedir= @@ -26,7 +26,7 @@ nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/ nacos.core.auth.system.type=nacos ### If turn on auth system: -nacos.core.auth.enabled=true +nacos.core.auth.enabled=false nacos.core.auth.caching.enabled=false