Add new ProtocolAuthService to replace AuthManager.
This commit is contained in:
parent
347494c380
commit
d2e11a3de7
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.IdentityContext;
|
||||
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.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.util.Loggers;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Abstract protocol auth service.
|
||||
*
|
||||
* <p>Implement #validateIdentity and #validateAuthority method template.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public abstract class AbstractProtocolAuthService<R> implements ProtocolAuthService<R> {
|
||||
|
||||
protected final AuthConfigs authConfigs;
|
||||
|
||||
protected AbstractProtocolAuthService(AuthConfigs authConfigs) {
|
||||
this.authConfigs = authConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateIdentity(IdentityContext identityContext) throws AccessException {
|
||||
if (!authConfigs.isAuthEnabled()) {
|
||||
return true;
|
||||
}
|
||||
Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()
|
||||
.findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
|
||||
if (authPluginService.isPresent()) {
|
||||
return authPluginService.get().validateIdentity(identityContext);
|
||||
}
|
||||
Loggers.AUTH.warn("Can't find auth plugin for type {}, please add plugin to classpath or set {} as false",
|
||||
authConfigs.getNacosAuthSystemType(), Constants.Auth.NACOS_CORE_AUTH_ENABLED);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateAuthority(IdentityContext identityContext, Permission permission) {
|
||||
if (!authConfigs.isAuthEnabled()) {
|
||||
return true;
|
||||
}
|
||||
Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()
|
||||
.findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());
|
||||
if (authPluginService.isPresent()) {
|
||||
return authPluginService.get().validateAuthority(identityContext, permission);
|
||||
}
|
||||
Loggers.AUTH.warn("Can't find auth plugin for type {}, please add plugin to classpath or set {} as false",
|
||||
authConfigs.getNacosAuthSystemType(), Constants.Auth.NACOS_CORE_AUTH_ENABLED);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resource from secured annotation specified resource.
|
||||
*
|
||||
* @param secured secured annotation
|
||||
* @return resource
|
||||
*/
|
||||
protected Resource parseSpecifiedResource(Secured secured) {
|
||||
return new Resource(null, null, secured.resource(), secured.signType(), null);
|
||||
}
|
||||
}
|
@ -40,10 +40,10 @@ public interface AuthPluginService {
|
||||
* To validate whether the identity context from request is legal or illegal.
|
||||
*
|
||||
* @param identityContext where we can find the user information
|
||||
* @return IdentityContext user auth result
|
||||
* @return {@code true} if legal, otherwise {@code false}
|
||||
* @throws AccessException if authentication is failed
|
||||
*/
|
||||
IdentityContext validateIdentity(IdentityContext identityContext) throws AccessException;
|
||||
boolean validateIdentity(IdentityContext identityContext) throws AccessException;
|
||||
|
||||
/**
|
||||
* Validate the identity whether has the resource authority.
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import com.alibaba.nacos.api.remote.request.Request;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.IdentityContext;
|
||||
import com.alibaba.nacos.auth.api.Resource;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.constant.SignType;
|
||||
import com.alibaba.nacos.auth.context.GrpcIdentityContextBuilder;
|
||||
import com.alibaba.nacos.auth.parser.grpc.AbstractGrpcResourceParser;
|
||||
import com.alibaba.nacos.auth.parser.grpc.ConfigGrpcResourceParser;
|
||||
import com.alibaba.nacos.auth.parser.grpc.NamingGrpcResourceParser;
|
||||
import com.alibaba.nacos.auth.util.Loggers;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Auth Service for Http protocol.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class GrpcProtocolAuthService extends AbstractProtocolAuthService<Request> {
|
||||
|
||||
private final Map<String, AbstractGrpcResourceParser> resourceParserMap;
|
||||
|
||||
private final GrpcIdentityContextBuilder identityContextBuilder;
|
||||
|
||||
protected GrpcProtocolAuthService(AuthConfigs authConfigs) {
|
||||
super(authConfigs);
|
||||
resourceParserMap = new HashMap<>(2);
|
||||
identityContextBuilder = new GrpcIdentityContextBuilder(authConfigs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
resourceParserMap.put(SignType.NAMING, new NamingGrpcResourceParser());
|
||||
resourceParserMap.put(SignType.CONFIG, new ConfigGrpcResourceParser());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource parseResource(Request request, Secured secured) {
|
||||
if (StringUtils.isNotBlank(secured.resource())) {
|
||||
return parseSpecifiedResource(secured);
|
||||
}
|
||||
String type = secured.signType();
|
||||
if (!resourceParserMap.containsKey(type)) {
|
||||
Loggers.AUTH.warn("Can't find Grpc request resourceParser for type {}", type);
|
||||
return Resource.EMPTY_RESOURCE;
|
||||
}
|
||||
return resourceParserMap.get(type).parse(request, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityContext parseIdentity(Request request) {
|
||||
return identityContextBuilder.build(request);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.IdentityContext;
|
||||
import com.alibaba.nacos.auth.api.Resource;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.constant.SignType;
|
||||
import com.alibaba.nacos.auth.context.HttpIdentityContextBuilder;
|
||||
import com.alibaba.nacos.auth.parser.http.AbstractHttpResourceParser;
|
||||
import com.alibaba.nacos.auth.parser.http.ConfigHttpResourceParser;
|
||||
import com.alibaba.nacos.auth.parser.http.NamingHttpResourceParser;
|
||||
import com.alibaba.nacos.auth.util.Loggers;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Auth Service for Http protocol.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class HttpProtocolAuthService extends AbstractProtocolAuthService<HttpServletRequest> {
|
||||
|
||||
private final Map<String, AbstractHttpResourceParser> resourceParserMap;
|
||||
|
||||
private final HttpIdentityContextBuilder identityContextBuilder;
|
||||
|
||||
protected HttpProtocolAuthService(AuthConfigs authConfigs) {
|
||||
super(authConfigs);
|
||||
resourceParserMap = new HashMap<>(2);
|
||||
identityContextBuilder = new HttpIdentityContextBuilder(authConfigs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
resourceParserMap.put(SignType.NAMING, new NamingHttpResourceParser());
|
||||
resourceParserMap.put(SignType.CONFIG, new ConfigHttpResourceParser());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource parseResource(HttpServletRequest request, Secured secured) {
|
||||
if (StringUtils.isNotBlank(secured.resource())) {
|
||||
return parseSpecifiedResource(secured);
|
||||
}
|
||||
String type = secured.signType();
|
||||
if (!resourceParserMap.containsKey(type)) {
|
||||
Loggers.AUTH.warn("Can't find Http request resourceParser for type {}", type);
|
||||
return Resource.EMPTY_RESOURCE;
|
||||
}
|
||||
return resourceParserMap.get(type).parse(request, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityContext parseIdentity(HttpServletRequest request) {
|
||||
return identityContextBuilder.build(request);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.IdentityContext;
|
||||
import com.alibaba.nacos.auth.api.Permission;
|
||||
import com.alibaba.nacos.auth.api.Resource;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
|
||||
/**
|
||||
* Protocol auth service.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public interface ProtocolAuthService<R> {
|
||||
|
||||
/**
|
||||
* Init protocol auth service.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Parse resource from protocol request and secured annotation.
|
||||
*
|
||||
* @param request protocol request
|
||||
* @param secured api secured annotation
|
||||
* @return resource
|
||||
*/
|
||||
Resource parseResource(R request, Secured secured);
|
||||
|
||||
/**
|
||||
* Parse identity context from protocol request.
|
||||
*
|
||||
* @param request protocol request
|
||||
* @return identity context
|
||||
*/
|
||||
IdentityContext parseIdentity(R request);
|
||||
|
||||
/**
|
||||
* Validate identity whether is legal.
|
||||
*
|
||||
* @param identityContext identity context
|
||||
* @return {@code true} if legal, otherwise {@code false}
|
||||
* @throws AccessException exception during validating
|
||||
*/
|
||||
boolean validateIdentity(IdentityContext identityContext) throws AccessException;
|
||||
|
||||
/**
|
||||
* Validate identity whether had permission for the resource and action.
|
||||
*
|
||||
* @param identityContext identity context
|
||||
* @param permission permssion include resource and action
|
||||
* @return {@code true} if legal, otherwise {@code false}
|
||||
* @throws AccessException exception during validating
|
||||
*/
|
||||
boolean validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException;
|
||||
}
|
@ -23,6 +23,7 @@ import java.io.Serializable;
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @author xiweng.yy
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class Permission implements Serializable {
|
||||
@ -32,7 +33,7 @@ public class Permission implements Serializable {
|
||||
/**
|
||||
* An unique key of resource.
|
||||
*/
|
||||
private String resource;
|
||||
private Resource resource;
|
||||
|
||||
/**
|
||||
* Action on resource, refer to class ActionTypes.
|
||||
@ -43,16 +44,16 @@ public class Permission implements Serializable {
|
||||
|
||||
}
|
||||
|
||||
public Permission(String resource, String action) {
|
||||
public Permission(Resource resource, String action) {
|
||||
this.resource = resource;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
public void setResource(Resource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.auth.api;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
@ -30,6 +32,9 @@ public class Resource implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 925971662931204553L;
|
||||
|
||||
public static final Resource EMPTY_RESOURCE = new Resource(StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY,
|
||||
StringUtils.EMPTY, null);
|
||||
|
||||
private final String namespaceId;
|
||||
|
||||
private final String group;
|
||||
|
41
auth/src/main/java/com/alibaba/nacos/auth/util/Loggers.java
Normal file
41
auth/src/main/java/com/alibaba/nacos/auth/util/Loggers.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.auth.util;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Loggers for core.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class Loggers {
|
||||
|
||||
private static final String AUTH_LOG_NAME = "auth";
|
||||
|
||||
public static final Logger AUTH = LoggerFactory.getLogger("com.alibaba.nacos.auth");
|
||||
|
||||
public static void setLogLevel(String logName, String level) {
|
||||
|
||||
if (AUTH_LOG_NAME.equals(logName)) {
|
||||
((ch.qos.logback.classic.Logger) AUTH).setLevel(Level.valueOf(level));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;
|
||||
import com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.IdentityContext;
|
||||
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.SignType;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.mock.MockAuthPluginService;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GrpcProtocolAuthServiceTest {
|
||||
|
||||
@Mock
|
||||
private AuthConfigs authConfigs;
|
||||
|
||||
private ConfigPublishRequest configRequest;
|
||||
|
||||
private AbstractNamingRequest namingRequest;
|
||||
|
||||
private GrpcProtocolAuthService protocolAuthService;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
protocolAuthService = new GrpcProtocolAuthService(authConfigs);
|
||||
protocolAuthService.initialize();
|
||||
mockConfigRequest();
|
||||
mockNamingRequest();
|
||||
Mockito.when(authConfigs.isAuthEnabled()).thenReturn(true);
|
||||
}
|
||||
|
||||
private void mockConfigRequest() {
|
||||
configRequest = new ConfigPublishRequest();
|
||||
configRequest.setTenant("testCNs");
|
||||
configRequest.setGroup("testCG");
|
||||
configRequest.setDataId("testD");
|
||||
}
|
||||
|
||||
private void mockNamingRequest() {
|
||||
namingRequest = new AbstractNamingRequest() {
|
||||
};
|
||||
namingRequest.setNamespace("testNNs");
|
||||
namingRequest.setGroupName("testNG");
|
||||
namingRequest.setServiceName("testS");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(resource = "testResource")
|
||||
public void testParseResourceWithSpecifiedResource() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithSpecifiedResource");
|
||||
Resource actual = protocolAuthService.parseResource(namingRequest, secured);
|
||||
assertEquals("testResource", actual.getName());
|
||||
assertEquals(SignType.NAMING, actual.getType());
|
||||
assertNull(actual.getNamespaceId());
|
||||
assertNull(actual.getGroup());
|
||||
assertNull(actual.getProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(signType = "non-exist")
|
||||
public void testParseResourceWithNonExistType() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithNonExistType");
|
||||
Resource actual = protocolAuthService.parseResource(namingRequest, secured);
|
||||
assertEquals(Resource.EMPTY_RESOURCE, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured()
|
||||
public void testParseResourceWithNamingType() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithNamingType");
|
||||
Resource actual = protocolAuthService.parseResource(namingRequest, secured);
|
||||
assertEquals(SignType.NAMING, actual.getType());
|
||||
assertEquals("testS", actual.getName());
|
||||
assertEquals("testNNs", actual.getNamespaceId());
|
||||
assertEquals("testNG", actual.getGroup());
|
||||
assertNotNull(actual.getProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(signType = SignType.CONFIG)
|
||||
public void testParseResourceWithConfigType() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithConfigType");
|
||||
Resource actual = protocolAuthService.parseResource(configRequest, secured);
|
||||
assertEquals(SignType.CONFIG, actual.getType());
|
||||
assertEquals("testD", actual.getName());
|
||||
assertEquals("testCNs", actual.getNamespaceId());
|
||||
assertEquals("testCG", actual.getGroup());
|
||||
assertNotNull(actual.getProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIdentity() {
|
||||
IdentityContext actual = protocolAuthService.parseIdentity(namingRequest);
|
||||
assertNotNull(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateIdentityWithoutPlugin() throws AccessException {
|
||||
IdentityContext identityContext = new IdentityContext();
|
||||
assertTrue(protocolAuthService.validateIdentity(identityContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateIdentityWithPlugin() throws AccessException {
|
||||
Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
|
||||
IdentityContext identityContext = new IdentityContext();
|
||||
assertFalse(protocolAuthService.validateIdentity(identityContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAuthorityWithoutPlugin() {
|
||||
assertTrue(protocolAuthService
|
||||
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAuthorityWithPlugin() {
|
||||
Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
|
||||
assertFalse(protocolAuthService
|
||||
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));
|
||||
}
|
||||
|
||||
private Secured getMethodSecure(String methodName) throws NoSuchMethodException {
|
||||
Method method = GrpcProtocolAuthServiceTest.class.getMethod(methodName);
|
||||
return method.getAnnotation(Secured.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.naming.CommonParams;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.IdentityContext;
|
||||
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.SignType;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.mock.MockAuthPluginService;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class HttpProtocolAuthServiceTest {
|
||||
|
||||
@Mock
|
||||
private AuthConfigs authConfigs;
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
private HttpProtocolAuthService httpProtocolAuthService;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
httpProtocolAuthService = new HttpProtocolAuthService(authConfigs);
|
||||
httpProtocolAuthService.initialize();
|
||||
Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn("testNNs");
|
||||
Mockito.when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn("testNG");
|
||||
Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn("testS");
|
||||
Mockito.when(request.getParameter(eq("tenant"))).thenReturn("testCNs");
|
||||
Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn("testCG");
|
||||
Mockito.when(request.getParameter(eq(Constants.DATAID))).thenReturn("testD");
|
||||
Mockito.when(authConfigs.isAuthEnabled()).thenReturn(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(resource = "testResource")
|
||||
public void testParseResourceWithSpecifiedResource() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithSpecifiedResource");
|
||||
Resource actual = httpProtocolAuthService.parseResource(request, secured);
|
||||
assertEquals("testResource", actual.getName());
|
||||
assertEquals(SignType.NAMING, actual.getType());
|
||||
assertNull(actual.getNamespaceId());
|
||||
assertNull(actual.getGroup());
|
||||
assertNull(actual.getProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(signType = "non-exist")
|
||||
public void testParseResourceWithNonExistType() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithNonExistType");
|
||||
Resource actual = httpProtocolAuthService.parseResource(request, secured);
|
||||
assertEquals(Resource.EMPTY_RESOURCE, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured()
|
||||
public void testParseResourceWithNamingType() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithNamingType");
|
||||
Resource actual = httpProtocolAuthService.parseResource(request, secured);
|
||||
assertEquals(SignType.NAMING, actual.getType());
|
||||
assertEquals("testS", actual.getName());
|
||||
assertEquals("testNNs", actual.getNamespaceId());
|
||||
assertEquals("testNG", actual.getGroup());
|
||||
assertNotNull(actual.getProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(signType = SignType.CONFIG)
|
||||
public void testParseResourceWithConfigType() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure("testParseResourceWithConfigType");
|
||||
Resource actual = httpProtocolAuthService.parseResource(request, secured);
|
||||
assertEquals(SignType.CONFIG, actual.getType());
|
||||
assertEquals("testD", actual.getName());
|
||||
assertEquals("testCNs", actual.getNamespaceId());
|
||||
assertEquals("testCG", actual.getGroup());
|
||||
assertNotNull(actual.getProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIdentity() {
|
||||
IdentityContext actual = httpProtocolAuthService.parseIdentity(request);
|
||||
assertNotNull(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateIdentityWithoutPlugin() throws AccessException {
|
||||
IdentityContext identityContext = new IdentityContext();
|
||||
assertTrue(httpProtocolAuthService.validateIdentity(identityContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateIdentityWithPlugin() throws AccessException {
|
||||
Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
|
||||
IdentityContext identityContext = new IdentityContext();
|
||||
assertFalse(httpProtocolAuthService.validateIdentity(identityContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAuthorityWithoutPlugin() {
|
||||
assertTrue(httpProtocolAuthService
|
||||
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateAuthorityWithPlugin() {
|
||||
Mockito.when(authConfigs.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);
|
||||
assertFalse(httpProtocolAuthService
|
||||
.validateAuthority(new IdentityContext(), new Permission(Resource.EMPTY_RESOURCE, "")));
|
||||
}
|
||||
|
||||
private Secured getMethodSecure(String methodName) throws NoSuchMethodException {
|
||||
Method method = HttpProtocolAuthServiceTest.class.getMethod(methodName);
|
||||
return method.getAnnotation(Secured.class);
|
||||
}
|
||||
}
|
@ -132,7 +132,7 @@ public class NacosRoleServiceImpl {
|
||||
}
|
||||
|
||||
// Old global admin can pass resource 'console/':
|
||||
if (permission.getResource().startsWith(AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX)) {
|
||||
if (permission.getResource().getName().startsWith(AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ public class NacosRoleServiceImpl {
|
||||
String permissionResource = permissionInfo.getResource().replaceAll("\\*", ".*");
|
||||
String permissionAction = permissionInfo.getAction();
|
||||
if (permissionAction.contains(permission.getAction()) && Pattern
|
||||
.matches(permissionResource, permission.getResource())) {
|
||||
.matches(permissionResource, permission.getResource().getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package com.alibaba.nacos.core.auth;
|
||||
|
||||
import com.alibaba.nacos.auth.AuthManager;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.Resource;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.api.Permission;
|
||||
@ -126,7 +127,8 @@ public class AuthFilter implements Filter {
|
||||
throw new AccessException("resource name invalid!");
|
||||
}
|
||||
|
||||
authManager.auth(new Permission(resource, action), authManager.login(req));
|
||||
Resource resourceObj = new Resource(null, null, resource, secured.signType(), null);
|
||||
authManager.auth(new Permission(resourceObj, action), authManager.login(req));
|
||||
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
|
@ -22,6 +22,7 @@ import com.alibaba.nacos.api.remote.request.RequestMeta;
|
||||
import com.alibaba.nacos.api.remote.response.Response;
|
||||
import com.alibaba.nacos.auth.AuthManager;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.api.Resource;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.api.Permission;
|
||||
@ -76,7 +77,8 @@ public class RemoteRequestAuthFilter extends AbstractRequestFilter {
|
||||
throw new AccessException("resource name invalid!");
|
||||
}
|
||||
|
||||
authManager.auth(new Permission(resource, action), authManager.loginRemote(request));
|
||||
Resource resourceObj = new Resource(null, null, resource, secured.signType(), null);
|
||||
authManager.auth(new Permission(resourceObj, action), authManager.loginRemote(request));
|
||||
|
||||
}
|
||||
} catch (AccessException e) {
|
||||
|
Loading…
Reference in New Issue
Block a user