From 0e4125e1563aff4abfa320706ac96b861ed80511 Mon Sep 17 00:00:00 2001 From: KomachiSion Date: Thu, 21 Nov 2024 18:03:55 +0800 Subject: [PATCH] Support grpc inner api force check server identity info. --- .../nacos/auth/GrpcProtocolAuthService.java | 10 ++ .../auth/GrpcProtocolAuthServiceTest.java | 16 +- ...ConfigChangeClusterSyncRequestHandler.java | 4 + .../core/auth/RemoteRequestAuthFilter.java | 31 ++-- .../cluster/remote/MemberReportHandler.java | 4 + .../core/ServerLoaderInfoRequestHandler.java | 4 + .../core/ServerReloaderRequestHandler.java | 4 + .../auth/RemoteRequestAuthFilterTest.java | 160 +++++++++++++++--- .../rpc/handler/DistroDataRequestHandler.java | 3 + 9 files changed, 200 insertions(+), 36 deletions(-) diff --git a/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java b/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java index c8dd925d6d..15c0e24ffe 100644 --- a/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java +++ b/auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java @@ -19,9 +19,11 @@ import com.alibaba.nacos.api.remote.request.Request; import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.auth.serveridentity.ServerIdentity; +import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult; import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.plugin.auth.api.Resource; import com.alibaba.nacos.auth.config.AuthConfigs; +import com.alibaba.nacos.plugin.auth.constant.ApiType; import com.alibaba.nacos.plugin.auth.constant.SignType; import com.alibaba.nacos.auth.context.GrpcIdentityContextBuilder; import com.alibaba.nacos.auth.parser.grpc.AbstractGrpcResourceParser; @@ -76,6 +78,14 @@ public IdentityContext parseIdentity(Request request) { return identityContextBuilder.build(request); } + @Override + public ServerIdentityResult checkServerIdentity(Request request, Secured secured) { + if (ApiType.INNER_API != secured.apiType()) { + return ServerIdentityResult.noMatched(); + } + return super.checkServerIdentity(request, secured); + } + @Override protected ServerIdentity parseServerIdentity(Request request) { String serverIdentityKey = authConfigs.getServerIdentityKey(); diff --git a/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java b/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java index 034914f71c..5da5a40659 100644 --- a/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java +++ b/auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java @@ -26,6 +26,7 @@ import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.plugin.auth.api.Permission; import com.alibaba.nacos.plugin.auth.api.Resource; +import com.alibaba.nacos.plugin.auth.constant.ApiType; import com.alibaba.nacos.plugin.auth.constant.SignType; import com.alibaba.nacos.plugin.auth.exception.AccessException; import org.junit.jupiter.api.BeforeEach; @@ -181,7 +182,7 @@ void testEnabledAuthWithoutPlugin() throws NoSuchMethodException { } @Test - @Secured + @Secured(apiType = ApiType.INNER_API) void testCheckServerIdentityWithoutIdentityConfig() throws NoSuchMethodException { Secured secured = getMethodSecure("testCheckServerIdentityWithoutIdentityConfig"); ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured); @@ -198,7 +199,7 @@ void testCheckServerIdentityWithoutIdentityConfig() throws NoSuchMethodException } @Test - @Secured + @Secured(apiType = ApiType.INNER_API) void testCheckServerIdentityNotMatched() throws NoSuchMethodException { Secured secured = getMethodSecure("testCheckServerIdentityNotMatched"); when(authConfigs.getServerIdentityKey()).thenReturn("1"); @@ -211,7 +212,7 @@ void testCheckServerIdentityNotMatched() throws NoSuchMethodException { } @Test - @Secured + @Secured(apiType = ApiType.INNER_API) void testCheckServerIdentityMatched() throws NoSuchMethodException { when(authConfigs.getServerIdentityKey()).thenReturn("1"); when(authConfigs.getServerIdentityValue()).thenReturn("2"); @@ -221,6 +222,15 @@ void testCheckServerIdentityMatched() throws NoSuchMethodException { assertEquals(ServerIdentityResult.ResultStatus.MATCHED, result.getStatus()); } + @Test + @Secured + void testCheckServerIdentityForOtherTypeApi() throws NoSuchMethodException { + namingRequest.putHeader("1", "2"); + Secured secured = getMethodSecure("testCheckServerIdentityForOtherTypeApi"); + ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured); + assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus()); + } + private Secured getMethodSecure(String methodName) throws NoSuchMethodException { Method method = GrpcProtocolAuthServiceTest.class.getDeclaredMethod(methodName); return method.getAnnotation(Secured.class); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java index 5dd9994c82..ca6dfe015b 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java @@ -21,6 +21,7 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.RemoteConstants; import com.alibaba.nacos.api.remote.request.RequestMeta; +import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; import com.alibaba.nacos.config.server.model.gray.TagGrayRule; @@ -34,6 +35,8 @@ import com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor; import com.alibaba.nacos.core.remote.RequestHandler; import com.alibaba.nacos.core.remote.grpc.InvokeSource; +import com.alibaba.nacos.plugin.auth.constant.ApiType; +import com.alibaba.nacos.plugin.auth.constant.SignType; import org.springframework.stereotype.Component; /** @@ -60,6 +63,7 @@ public ConfigChangeClusterSyncRequestHandler(DumpService dumpService, @TpsControl(pointName = "ClusterConfigChangeNotify") @Override @ExtractorManager.Extractor(rpcExtractor = ConfigRequestParamExtractor.class) + @Secured(signType = SignType.CONFIG, apiType = ApiType.INNER_API) public ConfigChangeClusterSyncResponse handle(ConfigChangeClusterSyncRequest configChangeSyncRequest, RequestMeta meta) throws NacosException { diff --git a/core/src/main/java/com/alibaba/nacos/core/auth/RemoteRequestAuthFilter.java b/core/src/main/java/com/alibaba/nacos/core/auth/RemoteRequestAuthFilter.java index 4290711d69..9e7004e1cb 100644 --- a/core/src/main/java/com/alibaba/nacos/core/auth/RemoteRequestAuthFilter.java +++ b/core/src/main/java/com/alibaba/nacos/core/auth/RemoteRequestAuthFilter.java @@ -23,7 +23,7 @@ import com.alibaba.nacos.auth.GrpcProtocolAuthService; import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.auth.config.AuthConfigs; -import com.alibaba.nacos.plugin.auth.constant.ApiType; +import com.alibaba.nacos.auth.serveridentity.ServerIdentityResult; import com.alibaba.nacos.common.utils.ExceptionUtil; import com.alibaba.nacos.core.context.RequestContext; import com.alibaba.nacos.core.context.RequestContextHolder; @@ -32,6 +32,7 @@ import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.plugin.auth.api.Permission; import com.alibaba.nacos.plugin.auth.api.Resource; +import com.alibaba.nacos.plugin.auth.constant.ApiType; import com.alibaba.nacos.plugin.auth.constant.Constants; import com.alibaba.nacos.plugin.auth.exception.AccessException; import org.springframework.stereotype.Component; @@ -63,20 +64,25 @@ public Response filter(Request request, RequestMeta meta, Class handlerClazz) th try { Method method = getHandleMethod(handlerClazz); - boolean isAuthEnabled = authConfigs.isConsoleAuthEnabled() || authConfigs.isAuthEnabled(); - if (method.isAnnotationPresent(Secured.class) && isAuthEnabled) { - - if (Loggers.AUTH.isDebugEnabled()) { - Loggers.AUTH.debug("auth start, request: {}", request.getClass().getSimpleName()); - } - + if (method.isAnnotationPresent(Secured.class)) { Secured secured = method.getAnnotation(Secured.class); - ApiType apiType = secured.apiType(); - if (apiType == ApiType.CONSOLE_API && !authConfigs.isConsoleAuthEnabled()) { + // Inner API must do check server identity. So judge api type not inner api and whether auth is enabled. + if (ApiType.INNER_API != secured.apiType() && !authConfigs.isAuthEnabled()) { return null; } - if (apiType == ApiType.OPEN_API && !authConfigs.isAuthEnabled()) { - return null; + if (Loggers.AUTH.isDebugEnabled()) { + Loggers.AUTH.debug("auth start, request: {}", request.getClass().getSimpleName()); + } + ServerIdentityResult identityResult = protocolAuthService.checkServerIdentity(request, secured); + switch (identityResult.getStatus()) { + case FAIL: + Response defaultResponseInstance = getDefaultResponseInstance(handlerClazz); + defaultResponseInstance.setErrorInfo(NacosException.NO_RIGHT, identityResult.getMessage()); + return defaultResponseInstance; + case MATCHED: + return null; + default: + break; } if (!protocolAuthService.enableAuth(secured)) { return null; @@ -113,7 +119,6 @@ public Response filter(Request request, RequestMeta meta, Class handlerClazz) th return defaultResponseInstance; } catch (Exception e) { Response defaultResponseInstance = getDefaultResponseInstance(handlerClazz); - defaultResponseInstance.setErrorInfo(NacosException.SERVER_ERROR, ExceptionUtil.getAllExceptionMsg(e)); return defaultResponseInstance; } diff --git a/core/src/main/java/com/alibaba/nacos/core/cluster/remote/MemberReportHandler.java b/core/src/main/java/com/alibaba/nacos/core/cluster/remote/MemberReportHandler.java index a2e9372c56..09c87db5b4 100644 --- a/core/src/main/java/com/alibaba/nacos/core/cluster/remote/MemberReportHandler.java +++ b/core/src/main/java/com/alibaba/nacos/core/cluster/remote/MemberReportHandler.java @@ -21,6 +21,7 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.RemoteConstants; import com.alibaba.nacos.api.remote.request.RequestMeta; +import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.common.utils.LoggerUtils; import com.alibaba.nacos.core.cluster.Member; import com.alibaba.nacos.core.cluster.NodeState; @@ -30,6 +31,8 @@ import com.alibaba.nacos.core.remote.RequestHandler; import com.alibaba.nacos.core.remote.grpc.InvokeSource; import com.alibaba.nacos.core.utils.Loggers; +import com.alibaba.nacos.plugin.auth.constant.ApiType; +import com.alibaba.nacos.plugin.auth.constant.SignType; import org.springframework.stereotype.Component; /** @@ -48,6 +51,7 @@ public MemberReportHandler(ServerMemberManager memberManager) { } @Override + @Secured(resource = "report", signType = SignType.SPECIFIED, apiType = ApiType.INNER_API) public MemberReportResponse handle(MemberReportRequest request, RequestMeta meta) throws NacosException { Member node = request.getNode(); if (!node.check()) { diff --git a/core/src/main/java/com/alibaba/nacos/core/remote/core/ServerLoaderInfoRequestHandler.java b/core/src/main/java/com/alibaba/nacos/core/remote/core/ServerLoaderInfoRequestHandler.java index 0cf208e038..2c1badc8ca 100644 --- a/core/src/main/java/com/alibaba/nacos/core/remote/core/ServerLoaderInfoRequestHandler.java +++ b/core/src/main/java/com/alibaba/nacos/core/remote/core/ServerLoaderInfoRequestHandler.java @@ -21,9 +21,12 @@ import com.alibaba.nacos.api.remote.request.RequestMeta; import com.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest; import com.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse; +import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.core.remote.ConnectionManager; import com.alibaba.nacos.core.remote.RequestHandler; import com.alibaba.nacos.core.remote.grpc.InvokeSource; +import com.alibaba.nacos.plugin.auth.constant.ApiType; +import com.alibaba.nacos.plugin.auth.constant.SignType; import com.alibaba.nacos.sys.env.EnvUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -45,6 +48,7 @@ public class ServerLoaderInfoRequestHandler extends RequestHandler { - try { - Response healthCheckResponse = remoteRequestAuthFilter.filter(healthCheckRequest, new RequestMeta(), MockRequestHandler.class); - assertNull(healthCheckResponse); - } catch (NacosException e) { - e.printStackTrace(); - fail(e.getMessage()); + @Secured(resource = "xxx") + @Override + public HealthCheckResponse handle(Request request, RequestMeta meta) throws NacosException { + return new HealthCheckResponse(); } } - class MockRequestHandler extends RequestHandler { + static class MockInnerRequestHandler extends RequestHandler { - @Secured(resource = "xxx") + @Secured(resource = "xxx", apiType = ApiType.INNER_API) @Override - public Response handle(Request request, RequestMeta meta) throws NacosException { - return null; + public HealthCheckResponse handle(Request request, RequestMeta meta) throws NacosException { + return new HealthCheckResponse(); } } } diff --git a/naming/src/main/java/com/alibaba/nacos/naming/remote/rpc/handler/DistroDataRequestHandler.java b/naming/src/main/java/com/alibaba/nacos/naming/remote/rpc/handler/DistroDataRequestHandler.java index 765b06b804..3b589b02a3 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/remote/rpc/handler/DistroDataRequestHandler.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/remote/rpc/handler/DistroDataRequestHandler.java @@ -20,6 +20,7 @@ import com.alibaba.nacos.api.remote.RemoteConstants; import com.alibaba.nacos.api.remote.request.RequestMeta; import com.alibaba.nacos.api.remote.response.ResponseCode; +import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.core.distributed.distro.DistroProtocol; import com.alibaba.nacos.core.distributed.distro.entity.DistroData; import com.alibaba.nacos.core.distributed.distro.entity.DistroKey; @@ -29,6 +30,7 @@ import com.alibaba.nacos.naming.cluster.remote.response.DistroDataResponse; import com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientDataProcessor; import com.alibaba.nacos.naming.misc.Loggers; +import com.alibaba.nacos.plugin.auth.constant.ApiType; import org.springframework.stereotype.Component; /** @@ -47,6 +49,7 @@ public DistroDataRequestHandler(DistroProtocol distroProtocol) { } @Override + @Secured(apiType = ApiType.INNER_API) public DistroDataResponse handle(DistroDataRequest request, RequestMeta meta) throws NacosException { try { switch (request.getDataOperation()) {