Http request use new plugin.

This commit is contained in:
KomachiSion 2022-01-20 17:59:05 +08:00
parent 88818d0816
commit 80a6821bb7
9 changed files with 166 additions and 66 deletions

View File

@ -22,6 +22,7 @@ import com.alibaba.nacos.auth.api.Permission;
import com.alibaba.nacos.auth.api.Resource; import com.alibaba.nacos.auth.api.Resource;
import com.alibaba.nacos.auth.config.AuthConfigs; import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.auth.constant.Constants; import com.alibaba.nacos.auth.constant.Constants;
import com.alibaba.nacos.auth.constant.SignType;
import com.alibaba.nacos.auth.exception.AccessException; import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.auth.util.Loggers; import com.alibaba.nacos.auth.util.Loggers;
@ -79,6 +80,6 @@ public abstract class AbstractProtocolAuthService<R> implements ProtocolAuthServ
* @return resource * @return resource
*/ */
protected Resource parseSpecifiedResource(Secured secured) { protected Resource parseSpecifiedResource(Secured secured) {
return new Resource(null, null, secured.resource(), secured.signType(), null); return new Resource(null, null, secured.resource(), SignType.SPECIFIED, null);
} }
} }

View File

@ -28,4 +28,6 @@ public class SignType {
public static final String CONFIG = "config"; public static final String CONFIG = "config";
public static final String CONSOLE = "console"; public static final String CONSOLE = "console";
public static final String SPECIFIED = "specified";
} }

View File

@ -83,7 +83,7 @@ public class GrpcProtocolAuthServiceTest {
Secured secured = getMethodSecure("testParseResourceWithSpecifiedResource"); Secured secured = getMethodSecure("testParseResourceWithSpecifiedResource");
Resource actual = protocolAuthService.parseResource(namingRequest, secured); Resource actual = protocolAuthService.parseResource(namingRequest, secured);
assertEquals("testResource", actual.getName()); assertEquals("testResource", actual.getName());
assertEquals(SignType.NAMING, actual.getType()); assertEquals(SignType.SPECIFIED, actual.getType());
assertNull(actual.getNamespaceId()); assertNull(actual.getNamespaceId());
assertNull(actual.getGroup()); assertNull(actual.getGroup());
assertNull(actual.getProperties()); assertNull(actual.getProperties());
@ -141,13 +141,13 @@ public class GrpcProtocolAuthServiceTest {
} }
@Test @Test
public void testValidateAuthorityWithoutPlugin() { public void testValidateAuthorityWithoutPlugin() throws AccessException {
assertTrue(protocolAuthService assertTrue(protocolAuthService
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, ""))); .validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));
} }
@Test @Test
public void testValidateAuthorityWithPlugin() { public void testValidateAuthorityWithPlugin() throws AccessException {
Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN); Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
assertFalse(protocolAuthService assertFalse(protocolAuthService
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, ""))); .validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));

View File

@ -73,7 +73,7 @@ public class HttpProtocolAuthServiceTest {
Secured secured = getMethodSecure("testParseResourceWithSpecifiedResource"); Secured secured = getMethodSecure("testParseResourceWithSpecifiedResource");
Resource actual = httpProtocolAuthService.parseResource(request, secured); Resource actual = httpProtocolAuthService.parseResource(request, secured);
assertEquals("testResource", actual.getName()); assertEquals("testResource", actual.getName());
assertEquals(SignType.NAMING, actual.getType()); assertEquals(SignType.SPECIFIED, actual.getType());
assertNull(actual.getNamespaceId()); assertNull(actual.getNamespaceId());
assertNull(actual.getGroup()); assertNull(actual.getGroup());
assertNull(actual.getProperties()); assertNull(actual.getProperties());
@ -131,13 +131,13 @@ public class HttpProtocolAuthServiceTest {
} }
@Test @Test
public void testValidateAuthorityWithoutPlugin() { public void testValidateAuthorityWithoutPlugin() throws AccessException {
assertTrue(httpProtocolAuthService assertTrue(httpProtocolAuthService
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, ""))); .validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));
} }
@Test @Test
public void testValidateAuthorityWithPlugin() { public void testValidateAuthorityWithPlugin() throws AccessException {
Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN); Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
assertFalse(httpProtocolAuthService assertFalse(httpProtocolAuthService
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, ""))); .validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));

View File

@ -19,7 +19,6 @@ package com.alibaba.nacos.console.security.nacos;
import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.api.remote.request.Request;
import com.alibaba.nacos.auth.AuthManager; import com.alibaba.nacos.auth.AuthManager;
import com.alibaba.nacos.auth.AuthPluginService;
import com.alibaba.nacos.auth.api.IdentityContext; import com.alibaba.nacos.auth.api.IdentityContext;
import com.alibaba.nacos.auth.api.Permission; import com.alibaba.nacos.auth.api.Permission;
import com.alibaba.nacos.auth.exception.AccessException; import com.alibaba.nacos.auth.exception.AccessException;
@ -41,8 +40,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List; import java.util.List;
/** /**
@ -52,21 +49,7 @@ import java.util.List;
* @since 1.2.0 * @since 1.2.0
*/ */
@Component @Component
@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule") public class NacosAuthManager implements AuthManager {
public class NacosAuthManager implements AuthManager, AuthPluginService {
private static final String AUTH_PLUGIN_TYPE = "nacos";
private static final String USER_IDENTITY_PARAM_KEY = "user";
private static final List<String> IDENTITY_NAMES = new LinkedList<String>() {
{
add(AuthConstants.AUTHORIZATION_HEADER);
add(Constants.ACCESS_TOKEN);
add(AuthConstants.PARAM_USERNAME);
add(AuthConstants.PARAM_PASSWORD);
}
};
@Autowired @Autowired
private JwtTokenManager tokenManager; private JwtTokenManager tokenManager;
@ -87,6 +70,12 @@ public class NacosAuthManager implements AuthManager, AuthPluginService {
return user; return user;
} }
User login(IdentityContext identityContext) throws AccessException {
String token = resolveToken(identityContext);
validate0(token);
return getNacosUser(token);
}
@Override @Override
public User loginRemote(Object request) throws AccessException { public User loginRemote(Object request) throws AccessException {
Request req = (Request) request; Request req = (Request) request;
@ -97,33 +86,13 @@ public class NacosAuthManager implements AuthManager, AuthPluginService {
@Override @Override
public void auth(Permission permission, User user) throws AccessException { public void auth(Permission permission, User user) throws AccessException {
auth0(permission, user); if (Loggers.AUTH.isDebugEnabled()) {
Loggers.AUTH.debug("auth permission: {}, user: {}", permission, user);
} }
@Override if (!roleService.hasPermission(user.getUserName(), permission)) {
public Collection<String> identityNames() { throw new AccessException("authorization failed!");
return IDENTITY_NAMES;
} }
@Override
public boolean validateIdentity(IdentityContext identityContext) throws AccessException {
String token = resolveToken(identityContext);
validate0(token);
NacosUser user = getNacosUser(token);
identityContext.setParameter(USER_IDENTITY_PARAM_KEY, user);
return true;
}
@Override
public Boolean validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException {
NacosUser user = (NacosUser) identityContext.getParameter(USER_IDENTITY_PARAM_KEY);
auth0(permission, user);
return true;
}
@Override
public String getAuthServiceName() {
return AUTH_PLUGIN_TYPE;
} }
/** /**
@ -228,14 +197,4 @@ public class NacosAuthManager implements AuthManager, AuthPluginService {
} }
return user; return user;
} }
private void auth0(Permission permission, User user) throws AccessException {
if (Loggers.AUTH.isDebugEnabled()) {
Loggers.AUTH.debug("auth permission: {}, user: {}", permission, user);
}
if (!roleService.hasPermission(user.getUserName(), permission)) {
throw new AccessException("authorization failed!");
}
}
} }

View File

@ -0,0 +1,86 @@
/*
* Copyright 1999-2021 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.console.security.nacos;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.auth.AuthPluginService;
import com.alibaba.nacos.auth.api.IdentityContext;
import com.alibaba.nacos.auth.api.Permission;
import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.auth.model.User;
import com.alibaba.nacos.console.security.nacos.constant.AuthConstants;
import com.alibaba.nacos.console.security.nacos.users.NacosUser;
import com.alibaba.nacos.sys.utils.ApplicationUtils;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/**
* Nacos default auth plugin service implementation.
*
* @author xiweng.yy
*/
@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule")
public class NacosAuthPluginService implements AuthPluginService {
private static final String AUTH_PLUGIN_TYPE = "nacos";
private static final String USER_IDENTITY_PARAM_KEY = "user";
private static final List<String> IDENTITY_NAMES = new LinkedList<String>() {
{
add(AuthConstants.AUTHORIZATION_HEADER);
add(Constants.ACCESS_TOKEN);
add(AuthConstants.PARAM_USERNAME);
add(AuthConstants.PARAM_PASSWORD);
}
};
private NacosAuthManager nacosAuthManager;
@Override
public Collection<String> identityNames() {
return IDENTITY_NAMES;
}
@Override
public boolean validateIdentity(IdentityContext identityContext) throws AccessException {
checkNacosAuthManager();
User user = nacosAuthManager.login(identityContext);
identityContext.setParameter(USER_IDENTITY_PARAM_KEY, user);
return true;
}
@Override
public Boolean validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException {
NacosUser user = (NacosUser) identityContext.getParameter(USER_IDENTITY_PARAM_KEY);
nacosAuthManager.auth(permission, user);
return true;
}
@Override
public String getAuthServiceName() {
return AUTH_PLUGIN_TYPE;
}
private void checkNacosAuthManager() {
if (null == nacosAuthManager) {
nacosAuthManager = ApplicationUtils.getBean(NacosAuthManager.class);
}
}
}

View File

@ -16,8 +16,11 @@
package com.alibaba.nacos.console.security.nacos.roles; package com.alibaba.nacos.console.security.nacos.roles;
import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.auth.api.Permission; import com.alibaba.nacos.auth.api.Permission;
import com.alibaba.nacos.auth.api.Resource;
import com.alibaba.nacos.auth.config.AuthConfigs;
import com.alibaba.nacos.auth.constant.Constants;
import com.alibaba.nacos.auth.constant.SignType;
import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.config.server.auth.PermissionInfo; import com.alibaba.nacos.config.server.auth.PermissionInfo;
import com.alibaba.nacos.config.server.auth.PermissionPersistService; import com.alibaba.nacos.config.server.auth.PermissionPersistService;
@ -115,7 +118,7 @@ public class NacosRoleServiceImpl {
*/ */
public boolean hasPermission(String username, Permission permission) { public boolean hasPermission(String username, Permission permission) {
//update password //update password
if (AuthConstants.UPDATE_PASSWORD_ENTRY_POINT.equals(permission.getResource())) { if (AuthConstants.UPDATE_PASSWORD_ENTRY_POINT.equals(permission.getResource().getName())) {
return true; return true;
} }
@ -146,7 +149,7 @@ public class NacosRoleServiceImpl {
String permissionResource = permissionInfo.getResource().replaceAll("\\*", ".*"); String permissionResource = permissionInfo.getResource().replaceAll("\\*", ".*");
String permissionAction = permissionInfo.getAction(); String permissionAction = permissionInfo.getAction();
if (permissionAction.contains(permission.getAction()) && Pattern if (permissionAction.contains(permission.getAction()) && Pattern
.matches(permissionResource, permission.getResource().getName())) { .matches(permissionResource, joinResource(permission.getResource()))) {
return true; return true;
} }
} }
@ -251,4 +254,29 @@ public class NacosRoleServiceImpl {
public List<String> findRolesLikeRoleName(String role) { public List<String> findRolesLikeRoleName(String role) {
return rolePersistService.findRolesLikeRoleName(role); return rolePersistService.findRolesLikeRoleName(role);
} }
private String joinResource(Resource resource) {
if (SignType.SPECIFIED.equals(resource.getType())) {
return resource.getName();
}
StringBuilder result = new StringBuilder();
String namespaceId = resource.getNamespaceId();
if (StringUtils.isNotBlank(namespaceId)) {
result.append(namespaceId);
}
String group = resource.getGroup();
if (StringUtils.isBlank(group)) {
result.append(Constants.Resource.SPLITTER).append('*');
} else {
result.append(Constants.Resource.SPLITTER).append(group);
}
String resourceName = resource.getName();
if (StringUtils.isBlank(resourceName)) {
result.append(Constants.Resource.SPLITTER).append(resource.getType().toLowerCase()).append("/*");
} else {
result.append(Constants.Resource.SPLITTER).append(resource.getType().toLowerCase()).append('/')
.append(resourceName);
}
return result.toString();
}
} }

View File

@ -0,0 +1,17 @@
#
# Copyright 1999-2021 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.
#
com.alibaba.nacos.console.security.nacos.NacosAuthPluginService

View File

@ -19,6 +19,9 @@ package com.alibaba.nacos.core.auth;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
/** /**
@ -27,12 +30,16 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
* @author chenglu * @author chenglu
* @date 2021-07-06 13:36 * @date 2021-07-06 13:36
*/ */
@RunWith(MockitoJUnitRunner.class)
public class AuthConfigTest { public class AuthConfigTest {
@Mock
private AuthFilter authFilter;
@Test @Test
public void testAuthFilterRegistration() { public void testAuthFilterRegistration() {
AuthConfig config = new AuthConfig(); AuthConfig config = new AuthConfig();
FilterRegistrationBean filter = config.authFilterRegistration(); FilterRegistrationBean filter = config.authFilterRegistration(authFilter);
Assert.assertTrue(filter.getFilter() instanceof AuthFilter); Assert.assertTrue(filter.getFilter() instanceof AuthFilter);
Assert.assertTrue(filter.getUrlPatterns().contains("/*")); Assert.assertTrue(filter.getUrlPatterns().contains("/*"));