#1105 Add integration tests

This commit is contained in:
nkorange 2020-01-09 19:13:37 +08:00
parent 02fea89f49
commit 82731985aa
24 changed files with 834 additions and 65 deletions

View File

@ -35,4 +35,4 @@ Build Instructions for NACOS
Execute the following command in order to build the tar.gz packages and install JAR into local repository:
#build nacos
$ mvn -Prelease-nacos -DskipTests clean install -U
$ mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U

View File

@ -76,6 +76,8 @@ public class Constants {
public static final String TOKEN_TTL = "tokenTtl";
public static final String GLOBAL_ADMIN = "globalAdmin";
public static final String TOKEN_REFRESH_WINDOW = "tokenRefreshWindow";
/**

View File

@ -189,6 +189,13 @@ CREATE TABLE roles (
role varchar(50) NOT NULL
);
CREATE TABLE permissions (
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action)
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
INSERT INTO roles (username, role) VALUES ('nacos', 'GLOBAL_ADMIN');

View File

@ -184,6 +184,13 @@ CREATE TABLE roles (
role varchar(50) NOT NULL
);
CREATE TABLE permissions (
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action)
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
INSERT INTO roles (username, role) VALUES ('nacos', 'GLOBAL_ADMIN');

View File

@ -76,7 +76,7 @@ public class UserController {
@PostMapping
public Object createUser(@RequestParam String username, @RequestParam String password) {
User user = userDetailsService.getUser(username);
User user = userDetailsService.getUserFromDatabase(username);
if (user != null) {
throw new IllegalArgumentException("user '" + username + "' already exist!");
}
@ -112,7 +112,7 @@ public class UserController {
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
public Object updateUser(@RequestParam String username, @RequestParam String newPassword) {
User user = userDetailsService.getUser(username);
User user = userDetailsService.getUserFromDatabase(username);
if (user == null) {
throw new IllegalArgumentException("user " + username + " not exist!");
}
@ -162,6 +162,7 @@ public class UserController {
JSONObject result = new JSONObject();
result.put(Constants.ACCESS_TOKEN, user.getToken());
result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds());
result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin());
return result;
}
@ -196,8 +197,8 @@ public class UserController {
RestResult<String> rr = new RestResult<String>();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = ((UserDetails) principal).getUsername();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
String password = userDetails.getPassword();
User user = userDetailsService.getUserFromDatabase(username);
String password = user.getPassword();
// TODO: throw out more fine grained exceptions
try {

View File

@ -16,6 +16,8 @@
package com.alibaba.nacos.console.exception;
import com.alibaba.nacos.core.auth.AccessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ -30,9 +32,10 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class ConsoleExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(ConsoleExceptionHandler.class);
@ExceptionHandler(AccessException.class)
private ResponseEntity<String> handleAccessException(AccessException e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getErrMsg());
}
@ -40,4 +43,10 @@ public class ConsoleExceptionHandler {
private ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.toString());
}
@ExceptionHandler(Exception.class)
private ResponseEntity<String> handleException(Exception e) {
logger.error("CONSOLE", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.toString());
}
}

View File

@ -16,6 +16,7 @@
package com.alibaba.nacos.console.security.nacos;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.config.server.auth.RoleInfo;
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.console.security.nacos.users.NacosUser;
import com.alibaba.nacos.core.auth.AccessException;
@ -34,6 +35,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* Builtin access control entry of Nacos
@ -74,10 +76,17 @@ public class NacosAuthManager implements AuthManager {
Authentication authentication = tokenManager.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
String userId = authentication.getName();
String username = authentication.getName();
NacosUser user = new NacosUser();
user.setUserName(userId);
user.setUserName(username);
user.setToken(token);
List<RoleInfo> roleInfoList = roleService.getRoles(username);
for (RoleInfo roleInfo : roleInfoList) {
if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {
user.setGlobalAdmin(true);
break;
}
}
return user;
}

View File

@ -23,6 +23,7 @@ import com.alibaba.nacos.config.server.auth.RolePersistService;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.core.auth.AuthConfigs;
import com.alibaba.nacos.core.auth.Permission;
import com.alibaba.nacos.core.utils.Loggers;
import io.jsonwebtoken.lang.Collections;
@ -44,7 +45,10 @@ import java.util.regex.Pattern;
@Service
public class NacosRoleServiceImpl {
private static final String GLOBAL_ADMIN_ROLE = "GLOBAL_ADMIN";
public static final String GLOBAL_ADMIN_ROLE = "GLOBAL_ADMIN";
@Autowired
private AuthConfigs authConfigs;
@Autowired
private RolePersistService rolePersistService;
@ -95,13 +99,13 @@ public class NacosRoleServiceImpl {
* Note if the user has many roles, this method returns true if any one role of the user has the
* desired permission.
*
* @param username user info
* @param username user info
* @param permission permission to auth
* @return true if granted, false otherwise
*/
public boolean hasPermission(String username, Permission permission) {
List<RoleInfo> roleInfoList = roleInfoMap.get(username);
List<RoleInfo> roleInfoList = getRoles(username);
if (Collections.isEmpty(roleInfoList)) {
return false;
}
@ -120,7 +124,7 @@ public class NacosRoleServiceImpl {
// For other roles, use a pattern match to decide if pass or not.
for (RoleInfo roleInfo : roleInfoList) {
List<PermissionInfo> permissionInfoList = permissionInfoMap.get(roleInfo.getRole());
List<PermissionInfo> permissionInfoList = getPermissions(roleInfo.getRole());
if (Collections.isEmpty(permissionInfoList)) {
continue;
}
@ -136,11 +140,36 @@ public class NacosRoleServiceImpl {
return false;
}
public List<RoleInfo> getRoles(String username) {
List<RoleInfo> roleInfoList = roleInfoMap.get(username);
if (!authConfigs.isCachingEnabled()) {
Page<RoleInfo> roleInfoPage = getRolesFromDatabase(username, 1, Integer.MAX_VALUE);
if (roleInfoPage != null) {
roleInfoList = roleInfoPage.getPageItems();
}
}
return roleInfoList;
}
public Page<RoleInfo> getRolesFromDatabase(String userName, int pageNo, int pageSize) {
Page<RoleInfo> roles = rolePersistService.getRolesByUserName(userName, pageNo, pageSize);
if (roles == null) {
return new Page<>();
}
return roles;
}
public List<PermissionInfo> getPermissions(String role) {
List<PermissionInfo> permissionInfoList = permissionInfoMap.get(role);
if (!authConfigs.isCachingEnabled()) {
Page<PermissionInfo> permissionInfoPage = getPermissionsFromDatabase(role, 1, Integer.MAX_VALUE);
if (permissionInfoPage != null) {
permissionInfoList = permissionInfoPage.getPageItems();
}
}
return permissionInfoList;
}
public Page<PermissionInfo> getPermissionsByRoleFromDatabase(String role, int pageNo, int pageSize) {
return permissionPersistService.getPermissions(role, pageNo, pageSize);
}
@ -157,11 +186,15 @@ public class NacosRoleServiceImpl {
}
public void deleteRole(String role) {
rolePersistService.deleteRole(role);
}
public Page<PermissionInfo> getPermissionsFromDatabase(String role, int pageNo, int pageSize) {
Page<PermissionInfo> pageInfo = permissionPersistService.getPermissions(role, pageNo, pageSize);
if (pageInfo == null) {
return new Page<>();
}
return pageInfo;
}

View File

@ -27,6 +27,8 @@ public class NacosUser extends User {
private String token;
private boolean globalAdmin = false;
public String getToken() {
return token;
}
@ -35,6 +37,14 @@ public class NacosUser extends User {
this.token = token;
}
public boolean isGlobalAdmin() {
return globalAdmin;
}
public void setGlobalAdmin(boolean globalAdmin) {
this.globalAdmin = globalAdmin;
}
@Override
public String toString() {
return JSON.toJSONString(this);

View File

@ -19,6 +19,7 @@ package com.alibaba.nacos.console.security.nacos.users;
import com.alibaba.nacos.config.server.auth.UserPersistService;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.config.server.model.User;
import com.alibaba.nacos.core.auth.AuthConfigs;
import com.alibaba.nacos.core.utils.Loggers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@ -44,6 +45,9 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserPersistService userPersistService;
@Autowired
private AuthConfigs authConfigs;
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
private void reload() {
try {
@ -66,6 +70,10 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService {
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMap.get(username);
if (!authConfigs.isCachingEnabled()) {
user = userPersistService.findUserByUsername(username);
}
if (user == null) {
throw new UsernameNotFoundException(username);
}
@ -81,7 +89,15 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService {
}
public User getUser(String username) {
return userMap.get(username);
User user = userMap.get(username);
if (!authConfigs.isCachingEnabled()) {
user = getUserFromDatabase(username);
}
return user;
}
public User getUserFromDatabase(String username) {
return userPersistService.findUserByUsername(username);
}
public void createUser(String username, String password) {

View File

@ -74,6 +74,11 @@ public class AuthConfigs {
.getProperty("nacos.core.auth.enabled", "false"));
}
public boolean isCachingEnabled() {
return BooleanUtils.toBoolean(reloadableConfigs.getProperties()
.getProperty("nacos.core.auth.caching.enabled", "true"));
}
@Bean
public FilterRegistrationBean authFilterRegistration() {
FilterRegistrationBean<AuthFilter> registration = new FilterRegistrationBean<>();

View File

@ -35,13 +35,12 @@ import java.util.Properties;
* @author nkorange
* @since 1.2.0
*/
@ConditionalOnProperty(name = "spring.config.location", matchIfMissing = false)
@Component
public class ReloadableConfigs {
private Properties properties;
@Value("${spring.config.location}")
@Value("${spring.config.location:}")
private String path;
private static final String FILE_PREFIX = "file:";

View File

@ -104,6 +104,9 @@ nacos.core.auth.default.token.expire.seconds=18000
### The default token:
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.
nacos.core.auth.caching.enabled=true
#*************** Istio Related Configurations ***************#
### If turn on the MCP server:

View File

@ -419,10 +419,7 @@ public class HttpClient {
inputStream = new GZIPInputStream(inputStream);
}
HttpResult result = new HttpResult(respCode, IoUtils.toString(inputStream, getCharset(conn)), respHeaders);
inputStream.close();
return result;
return new HttpResult(respCode, IoUtils.toString(inputStream, getCharset(conn)), respHeaders);
}
private static String getCharset(HttpURLConnection conn) {

17
pom.xml
View File

@ -525,6 +525,11 @@
<artifactId>nacos-example</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-address</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
@ -539,12 +544,12 @@
<version>1.2.58</version>
</dependency>
<!-- javax libs-->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs</artifactId>
<version>2.1</version>
</dependency>
<!-- &lt;!&ndash; javax libs&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>javax.ws.rs</groupId>-->
<!-- <artifactId>javax.ws.rs</artifactId>-->
<!-- <version>1.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>javax.servlet</groupId>

View File

@ -80,6 +80,11 @@
<artifactId>nacos-console</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-address</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View File

@ -1,4 +1,313 @@
/*
* 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;
public class Permission_ITCase {
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.Nacos;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.core.auth.Permission;
import com.alibaba.nacos.test.base.HttpClient4Test;
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.net.URL;
import java.util.concurrent.TimeUnit;
/**
* @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 Permission_ITCase extends HttpClient4Test {
@LocalServerPort
private int port;
private String accessToken;
@Before
public void init() throws Exception {
TimeUnit.SECONDS.sleep(5L);
String url = String.format("http://localhost:%d/", port);
this.base = new URL(url);
}
@After
public void destroy() {
// Delete permission:
ResponseEntity<String> response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("resource", "public:*:*")
.appendParam("action", "rw")
.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", "role1")
.appendParam("resource", "test1:*:*")
.appendParam("action", "r")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Delete role:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("role", "role1")
.appendParam("username", "username2")
.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", "username3")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
}
@Test
public void login() {
ResponseEntity<String> 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"));
accessToken = json.getString("accessToken");
}
@Test
public void createDeleteQueryPermission() {
login();
// Create a user:
ResponseEntity<String> response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("username", "username3")
.appendParam("password", "password1")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.POST);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Create role:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("role", "role1")
.appendParam("username", "username3")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.POST);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Create permission:
response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("resource", "public:*:*")
.appendParam("action", "rw")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.POST);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Create another permission:
response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("resource", "test1:*:*")
.appendParam("action", "r")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.POST);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query permission:
response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("pageNo", "1")
.appendParam("pageSize", "10")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.GET);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
Page<Permission> permissionPage = JSON.parseObject(response.getBody(), new TypeReference<Page<Permission>>() {
});
Assert.assertNotNull(permissionPage);
Assert.assertNotNull(permissionPage.getPageItems());
boolean found1=false,found2=false;
for (Permission permission : permissionPage.getPageItems()) {
if (permission.getResource().equals("public:*:*") && permission.getAction().equals("rw")) {
found1 = true;
}
if (permission.getResource().equals("test1:*:*") && permission.getAction().equals("r")) {
found2 = true;
}
if (found1 && found2) {
break;
}
}
Assert.assertTrue(found1);
Assert.assertTrue(found2);
// Delete permission:
response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("resource", "public:*:*")
.appendParam("action", "rw")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query permission:
response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("pageNo", "1")
.appendParam("pageSize", "10")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.GET);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
permissionPage = JSON.parseObject(response.getBody(), new TypeReference<Page<Permission>>() {
});
Assert.assertNotNull(permissionPage);
Assert.assertNotNull(permissionPage.getPageItems());
found1=false;
found2=false;
for (Permission permission : permissionPage.getPageItems()) {
if (permission.getResource().equals("public:*:*") && permission.getAction().equals("rw")) {
found1 = true;
}
if (permission.getResource().equals("test1:*:*") && permission.getAction().equals("r")) {
found2 = true;
}
}
Assert.assertFalse(found1);
Assert.assertTrue(found2);
// Delete permission:
response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("resource", "test1:*:*")
.appendParam("action", "r")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query permission:
response = request("/nacos/v1/auth/permissions",
Params.newParams()
.appendParam("role", "role1")
.appendParam("pageNo", "1")
.appendParam("pageSize", "10")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.GET);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
permissionPage = JSON.parseObject(response.getBody(), new TypeReference<Page<Permission>>() {
});
Assert.assertNotNull(permissionPage);
Assert.assertNotNull(permissionPage.getPageItems());
found1=false;
found2=false;
for (Permission permission : permissionPage.getPageItems()) {
if (permission.getResource().equals("public:*:*") && permission.getAction().equals("rw")) {
found1 = true;
}
if (permission.getResource().equals("test1:*:*") && permission.getAction().equals("r")) {
found2 = true;
}
}
Assert.assertFalse(found1);
Assert.assertFalse(found2);
}
}

View File

@ -1,4 +1,306 @@
/*
* 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;
public class Role_ITCase {
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.Nacos;
import com.alibaba.nacos.config.server.auth.RoleInfo;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.test.base.HttpClient4Test;
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.net.URL;
import java.util.concurrent.TimeUnit;
/**
* @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 Role_ITCase extends HttpClient4Test {
@LocalServerPort
private int port;
private String accessToken;
@Before
public void init() throws Exception {
TimeUnit.SECONDS.sleep(5L);
String url = String.format("http://localhost:%d/", port);
this.base = new URL(url);
}
@After
public void destroy() {
// Delete role:
ResponseEntity<String> response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("role", "role1")
.appendParam("username", "username2")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Delete role:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("role", "role2")
.appendParam("username", "username2")
.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", "username2")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
}
@Test
public void login() {
ResponseEntity<String> 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"));
accessToken = json.getString("accessToken");
}
@Test
public void createDeleteQueryRole() {
login();
// Create a user:
ResponseEntity<String> response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("username", "username2")
.appendParam("password", "password1")
.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", "role1")
.appendParam("username", "username2")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.POST);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query role of user:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("username", "username2")
.appendParam("pageNo", "1")
.appendParam("pageSize", "10")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.GET);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
Page<RoleInfo> roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference<Page<RoleInfo>>() {
});
Assert.assertNotNull(roleInfoPage);
Assert.assertNotNull(roleInfoPage.getPageItems());
boolean found = false;
for (RoleInfo roleInfo : roleInfoPage.getPageItems()) {
if (roleInfo.getRole().equals("role1")) {
found = true;
break;
}
}
Assert.assertTrue(found);
// Add second role to user:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("role", "role2")
.appendParam("username", "username2")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.POST);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query roles of user:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("username", "username2")
.appendParam("pageNo", "1")
.appendParam("pageSize", "10")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.GET);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference<Page<RoleInfo>>() {
});
Assert.assertNotNull(roleInfoPage);
Assert.assertNotNull(roleInfoPage.getPageItems());
found = false;
boolean found2 = false;
for (RoleInfo roleInfo : roleInfoPage.getPageItems()) {
if (roleInfo.getRole().equals("role1")) {
found = true;
}
if (roleInfo.getRole().equals("role2")) {
found2 = true;
}
if (found && found2) {
break;
}
}
Assert.assertTrue(found);
Assert.assertTrue(found2);
// Delete role:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("role", "role2")
.appendParam("username", "username2")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query roles of user:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("username", "username2")
.appendParam("pageNo", "1")
.appendParam("pageSize", "10")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.GET);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference<Page<RoleInfo>>() {
});
Assert.assertNotNull(roleInfoPage);
Assert.assertNotNull(roleInfoPage.getPageItems());
found = false;
found2 = false;
for (RoleInfo roleInfo : roleInfoPage.getPageItems()) {
if (roleInfo.getRole().equals("role1")) {
found = true;
}
if (roleInfo.getRole().equals("role2")) {
found2 = true;
}
}
Assert.assertFalse(found2);
Assert.assertTrue(found);
// Delete role:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("role", "role1")
.appendParam("username", "username2")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query roles of user:
response = request("/nacos/v1/auth/roles",
Params.newParams()
.appendParam("username", "username2")
.appendParam("pageNo", "1")
.appendParam("pageSize", "10")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.GET);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference<Page<RoleInfo>>() {
});
Assert.assertNotNull(roleInfoPage);
Assert.assertNotNull(roleInfoPage.getPageItems());
found = false;
found2 = false;
for (RoleInfo roleInfo : roleInfoPage.getPageItems()) {
if (roleInfo.getRole().equals("role1")) {
found = true;
}
if (roleInfo.getRole().equals("role2")) {
found2 = true;
}
}
Assert.assertFalse(found2);
Assert.assertFalse(found);
}
}

View File

@ -1,14 +1,30 @@
/*
* 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.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.Nacos;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.config.server.model.User;
import com.alibaba.nacos.console.utils.PasswordEncoderUtil;
import com.alibaba.nacos.naming.NamingApp;
import com.alibaba.nacos.test.base.HttpClient4Test;
import com.alibaba.nacos.test.base.Params;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -20,18 +36,17 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* @author nkorange
* @since 1.2.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = NamingApp.class, properties = {"server.servlet.context-path=/nacos"},
@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7001"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class User_ITCase extends HttpClient4Test {
protected URL base;
@LocalServerPort
private int port;
@ -39,18 +54,34 @@ public class User_ITCase extends HttpClient4Test {
@Before
public void init() throws Exception {
TimeUnit.SECONDS.sleep(5L);
String url = String.format("http://localhost:%d/", port);
this.base = new URL(url);
login();
}
@After
public void destroy() {
// Delete a user:
ResponseEntity<String> response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("username", "username1")
.appendParam("accessToken", accessToken)
.done(),
String.class,
HttpMethod.DELETE);
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
}
@Test
public void login() {
ResponseEntity<String> response = request("/nacos/v1/ns/auth/users/login",
ResponseEntity<String> response = request("/nacos/v1/auth/users/login",
Params.newParams()
.appendParam("username", "username1")
.appendParam("password", "password1")
.appendParam("username", "nacos")
.appendParam("password", "nacos")
.done(),
String.class,
HttpMethod.POST);
@ -64,8 +95,10 @@ public class User_ITCase extends HttpClient4Test {
@Test
public void createUpdateDeleteUser() {
login();
// Create a user:
ResponseEntity<String> response = request("/nacos/v1/ns/auth/users",
ResponseEntity<String> response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("username", "username1")
.appendParam("password", "password1")
@ -77,7 +110,7 @@ public class User_ITCase extends HttpClient4Test {
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query a user:
response = request("/nacos/v1/ns/auth/users",
response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("pageNo", "1")
.appendParam("pageSize", String.valueOf(Integer.MAX_VALUE))
@ -87,7 +120,8 @@ public class User_ITCase extends HttpClient4Test {
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
Page<User> userPage = JSON.parseObject(response.getBody(), new TypeReference<Page<User>>(){});
Page<User> userPage = JSON.parseObject(response.getBody(), new TypeReference<Page<User>>() {
});
Assert.assertNotNull(userPage);
Assert.assertNotNull(userPage.getPageItems());
@ -96,7 +130,7 @@ public class User_ITCase extends HttpClient4Test {
boolean found = false;
for (User user : userPage.getPageItems()) {
if ("username1".equals(user.getUsername()) &&
PasswordEncoderUtil.encode("password1").equals(user.getPassword())) {
PasswordEncoderUtil.matches("password1", user.getPassword())) {
found = true;
break;
}
@ -104,7 +138,7 @@ public class User_ITCase extends HttpClient4Test {
Assert.assertTrue(found);
// Update a user:
response = request("/nacos/v1/ns/auth/users",
response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("username", "username1")
.appendParam("newPassword", "password2")
@ -116,7 +150,7 @@ public class User_ITCase extends HttpClient4Test {
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query a user:
response = request("/nacos/v1/ns/auth/users",
response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("pageNo", "1")
.appendParam("pageSize", String.valueOf(Integer.MAX_VALUE))
@ -124,7 +158,8 @@ public class User_ITCase extends HttpClient4Test {
.done(),
String.class);
userPage = JSON.parseObject(response.getBody(), new TypeReference<Page<User>>(){});
userPage = JSON.parseObject(response.getBody(), new TypeReference<Page<User>>() {
});
Assert.assertNotNull(userPage);
Assert.assertNotNull(userPage.getPageItems());
@ -133,7 +168,7 @@ public class User_ITCase extends HttpClient4Test {
found = false;
for (User user : userPage.getPageItems()) {
if ("username1".equals(user.getUsername()) &&
PasswordEncoderUtil.encode("password2").equals(user.getPassword())) {
PasswordEncoderUtil.matches("password2", user.getPassword())) {
found = true;
break;
}
@ -141,7 +176,7 @@ public class User_ITCase extends HttpClient4Test {
Assert.assertTrue(found);
// Delete a user:
response = request("/nacos/v1/ns/auth/users",
response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("username", "username1")
.appendParam("accessToken", accessToken)
@ -152,7 +187,7 @@ public class User_ITCase extends HttpClient4Test {
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
// Query a user:
response = request("/nacos/v1/ns/auth/users",
response = request("/nacos/v1/auth/users",
Params.newParams()
.appendParam("pageNo", "1")
.appendParam("pageSize", String.valueOf(Integer.MAX_VALUE))
@ -162,7 +197,8 @@ public class User_ITCase extends HttpClient4Test {
Assert.assertTrue(response.getStatusCode().is2xxSuccessful());
userPage = JSON.parseObject(response.getBody(), new TypeReference<Page<User>>(){});
userPage = JSON.parseObject(response.getBody(), new TypeReference<Page<User>>() {
});
Assert.assertNotNull(userPage);
Assert.assertNotNull(userPage.getPageItems());
@ -177,5 +213,4 @@ public class User_ITCase extends HttpClient4Test {
}
Assert.assertFalse(found);
}
}

View File

@ -22,16 +22,7 @@ import com.alibaba.nacos.test.base.HttpClient4Test;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.junit.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URL;
import java.util.*;
/**

View File

@ -19,8 +19,8 @@ import java.net.URL;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.naming.NamingApp;
import com.alibaba.nacos.naming.NamingApp;
import com.alibaba.nacos.test.base.Params;
import org.junit.After;
import org.junit.Assert;

View File

@ -37,6 +37,5 @@ public class nacosSmoke_ITCase {
@Test
public void testSmoke() {
logger.info("nacosSmoke_ITCase :testSmoke");
}
}

View File

@ -26,10 +26,14 @@ nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/
nacos.core.auth.system.type=nacos
### If turn on auth system:
nacos.core.auth.enabled=false
nacos.core.auth.enabled=true
nacos.core.auth.caching.enabled=false
### The token expiration in seconds:
nacos.core.auth.default.token.expire.seconds=18000
### The default token:
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
tldSkipPatterns=derbyLocale_*.jar,jaxb-api.jar,jsr173_1.0_api.jar,jaxb1-impl.jar,activation.jar

View File

@ -1,4 +1,4 @@
CREATE SCHEMA diamond AUTHORIZATION diamond;
CREATE SCHEMA nacos AUTHORIZATION nacos;
CREATE TABLE config_info (
id bigint NOT NULL generated by default as identity,
@ -159,17 +159,38 @@ CREATE TABLE tenant_capacity (
constraint tenant_capacity_id_key PRIMARY KEY (id),
constraint uk_tenant_id UNIQUE (tenant_id));
CREATE TABLE tenant_info (
id bigint NOT NULL generated by default as identity,
kp varchar(128) NOT NULL,
tenant_id varchar(128) DEFAULT '',
tenant_name varchar(128) DEFAULT '',
tenant_desc varchar(256) DEFAULT NULL,
create_source varchar(32) DEFAULT NULL,
gmt_create bigint NOT NULL,
gmt_modified bigint NOT NULL,
constraint tenant_info_id_key PRIMARY KEY (id),
constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id));
CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id);
CREATE TABLE users (
username varchar(50) NOT NULL PRIMARY KEY,
password varchar(500) NOT NULL,
enabled boolean NOT NULL
enabled boolean NOT NULL DEFAULT true
);
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 (
role varchar(50) NOT NULL,
resource varchar(512) NOT NULL,
action varchar(8) NOT NULL,
constraint uk_role_permission UNIQUE (role,resource,action)
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
INSERT INTO roles (username, role) VALUES ('nacos', 'GLOBAL_ADMIN');