From 64dcc0ed0a1c3e696951643a7089afc085f0f5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E7=BF=8A=20SionYang?= Date: Wed, 9 Feb 2022 17:57:39 +0800 Subject: [PATCH] [ISSUE#5696] IdentityContext build from resource and remote ip. (#7745) * validateIdentity add Resource input for extension. * IdentityContext parse remoteIp. --- .../auth/AbstractProtocolAuthService.java | 4 ++-- .../nacos/auth/ProtocolAuthService.java | 5 +++-- .../context/GrpcIdentityContextBuilder.java | 10 ++++++++-- .../context/HttpIdentityContextBuilder.java | 20 +++++++++++++++++++ .../auth/GrpcProtocolAuthServiceTest.java | 4 ++-- .../auth/HttpProtocolAuthServiceTest.java | 4 ++-- .../GrpcIdentityContextBuilderTest.java | 3 +++ .../HtppIdentityContextBuilderTest.java | 3 +++ .../auth/mock/MockAuthPluginService.java | 3 ++- .../alibaba/nacos/core/auth/AuthFilter.java | 2 +- .../core/auth/RemoteRequestAuthFilter.java | 5 ++++- .../auth/impl/NacosAuthPluginService.java | 3 ++- .../nacos/plugin/auth/constant/Constants.java | 4 ++++ .../auth/spi/server/AuthPluginService.java | 4 +++- 14 files changed, 59 insertions(+), 15 deletions(-) diff --git a/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java b/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java index ee1c416fc..7a53fa522 100644 --- a/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java +++ b/auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java @@ -46,14 +46,14 @@ public abstract class AbstractProtocolAuthService implements ProtocolAuthServ } @Override - public boolean validateIdentity(IdentityContext identityContext) throws AccessException { + public boolean validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException { if (!authConfigs.isAuthEnabled()) { return true; } Optional authPluginService = AuthPluginManager.getInstance() .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType()); if (authPluginService.isPresent()) { - return authPluginService.get().validateIdentity(identityContext); + return authPluginService.get().validateIdentity(identityContext, resource); } 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); diff --git a/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java b/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java index d3e3afa82..8b4cea5b9 100644 --- a/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java +++ b/auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java @@ -55,16 +55,17 @@ public interface ProtocolAuthService { * Validate identity whether is legal. * * @param identityContext identity context + * @param resource resource * @return {@code true} if legal, otherwise {@code false} * @throws AccessException exception during validating */ - boolean validateIdentity(IdentityContext identityContext) throws AccessException; + boolean validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException; /** * Validate identity whether had permission for the resource and action. * * @param identityContext identity context - * @param permission permssion include resource and action + * @param permission permission include resource and action * @return {@code true} if legal, otherwise {@code false} * @throws AccessException exception during validating */ diff --git a/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java b/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java index f67c06b8d..bfa3af630 100644 --- a/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java +++ b/auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java @@ -17,10 +17,11 @@ package com.alibaba.nacos.auth.context; import com.alibaba.nacos.api.remote.request.Request; +import com.alibaba.nacos.auth.config.AuthConfigs; +import com.alibaba.nacos.plugin.auth.api.IdentityContext; +import com.alibaba.nacos.plugin.auth.constant.Constants; import com.alibaba.nacos.plugin.auth.spi.server.AuthPluginManager; import com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService; -import com.alibaba.nacos.plugin.auth.api.IdentityContext; -import com.alibaba.nacos.auth.config.AuthConfigs; import java.util.HashSet; import java.util.Map; @@ -52,6 +53,7 @@ public class GrpcIdentityContextBuilder implements IdentityContextBuilder authPluginService = AuthPluginManager.getInstance() .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType()); IdentityContext result = new IdentityContext(); + getRemoteIp(request, result); if (!authPluginService.isPresent()) { return result; } @@ -64,4 +66,8 @@ public class GrpcIdentityContextBuilder implements IdentityContextBuilder { + private static final String X_FORWARDED_FOR = "X-Forwarded-For"; + + private static final String X_FORWARDED_FOR_SPLIT_SYMBOL = ","; + private final AuthConfigs authConfigs; public HttpIdentityContextBuilder(AuthConfigs authConfigs) { @@ -50,6 +56,7 @@ public class HttpIdentityContextBuilder implements IdentityContextBuilder authPluginService = AuthPluginManager.getInstance() .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType()); if (!authPluginService.isPresent()) { @@ -80,4 +87,17 @@ public class HttpIdentityContextBuilder implements IdentityContextBuilder headers = new HashMap<>(); headers.put(IDENTITY_TEST_KEY, IDENTITY_TEST_VALUE); when(request.getHeaders()).thenReturn(headers); + when(request.getHeader(Constants.Identity.X_REAL_IP)).thenReturn("1.1.1.1"); } @Test @@ -69,5 +71,6 @@ public class GrpcIdentityContextBuilderTest { public void testBuild() { IdentityContext actual = identityContextBuilder.build(request); assertEquals(IDENTITY_TEST_VALUE, actual.getParameter(IDENTITY_TEST_KEY)); + assertEquals("1.1.1.1", actual.getParameter(Constants.Identity.REMOTE_IP)); } } diff --git a/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java b/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java index 83a73afdb..602a46436 100644 --- a/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java +++ b/auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java @@ -18,6 +18,7 @@ package com.alibaba.nacos.auth.context; import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.auth.config.AuthConfigs; +import com.alibaba.nacos.plugin.auth.constant.Constants; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -75,6 +76,7 @@ public class HtppIdentityContextBuilderTest { mockParameter(false); IdentityContext actual = identityContextBuilder.build(request); assertEquals(IDENTITY_TEST_VALUE, actual.getParameter(IDENTITY_TEST_KEY)); + assertEquals("1.1.1.1", actual.getParameter(Constants.Identity.REMOTE_IP)); } @Test @@ -91,6 +93,7 @@ public class HtppIdentityContextBuilderTest { when(headerNames.hasMoreElements()).thenReturn(true, false); when(headerNames.nextElement()).thenReturn(IDENTITY_TEST_KEY, (String) null); when(request.getHeader(IDENTITY_TEST_KEY)).thenReturn(IDENTITY_TEST_VALUE); + when(request.getHeader(Constants.Identity.X_REAL_IP)).thenReturn("1.1.1.1"); } } diff --git a/auth/src/test/java/com/alibaba/nacos/auth/mock/MockAuthPluginService.java b/auth/src/test/java/com/alibaba/nacos/auth/mock/MockAuthPluginService.java index 8fa475fdf..fe2bb1fd6 100644 --- a/auth/src/test/java/com/alibaba/nacos/auth/mock/MockAuthPluginService.java +++ b/auth/src/test/java/com/alibaba/nacos/auth/mock/MockAuthPluginService.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.auth.mock; +import com.alibaba.nacos.plugin.auth.api.Resource; import com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService; import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.plugin.auth.api.Permission; @@ -36,7 +37,7 @@ public class MockAuthPluginService implements AuthPluginService { } @Override - public boolean validateIdentity(IdentityContext identityContext) throws AccessException { + public boolean validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException { return false; } diff --git a/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java b/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java index 496053f9c..3c828dd0f 100644 --- a/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java +++ b/core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java @@ -115,7 +115,7 @@ public class AuthFilter implements Filter { Secured secured = method.getAnnotation(Secured.class); Resource resource = protocolAuthService.parseResource(req, secured); IdentityContext identityContext = protocolAuthService.parseIdentity(req); - boolean result = protocolAuthService.validateIdentity(identityContext); + boolean result = protocolAuthService.validateIdentity(identityContext, resource); if (!result) { // TODO Get reason of failure throw new AccessException("Validate Identity failed."); 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 963699141..c37bc5c15 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 @@ -29,6 +29,7 @@ import com.alibaba.nacos.core.utils.Loggers; 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.Constants; import com.alibaba.nacos.plugin.auth.exception.AccessException; import org.springframework.stereotype.Component; @@ -66,9 +67,11 @@ public class RemoteRequestAuthFilter extends AbstractRequestFilter { } Secured secured = method.getAnnotation(Secured.class); + String clientIp = meta.getClientIp(); + request.putHeader(Constants.Identity.X_REAL_IP, clientIp); Resource resource = protocolAuthService.parseResource(request, secured); IdentityContext identityContext = protocolAuthService.parseIdentity(request); - boolean result = protocolAuthService.validateIdentity(identityContext); + boolean result = protocolAuthService.validateIdentity(identityContext, resource); if (!result) { // TODO Get reason of failure throw new AccessException("Validate Identity failed."); diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java index a9f55486f..e5bee6c3d 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.plugin.auth.impl; import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.plugin.auth.api.Resource; import com.alibaba.nacos.plugin.auth.impl.users.User; import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.plugin.auth.api.Permission; @@ -57,7 +58,7 @@ public class NacosAuthPluginService implements AuthPluginService { } @Override - public boolean validateIdentity(IdentityContext identityContext) throws AccessException { + public boolean validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException { checkNacosAuthManager(); User user = nacosAuthManager.login(identityContext); identityContext.setParameter(USER_IDENTITY_PARAM_KEY, user); diff --git a/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/constant/Constants.java b/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/constant/Constants.java index a5d80a819..2f2d95f7c 100644 --- a/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/constant/Constants.java +++ b/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/constant/Constants.java @@ -48,5 +48,9 @@ public class Constants { public static class Identity { public static final String IDENTITY_ID = "identity_id"; + + public static final String X_REAL_IP = "X-Real-IP"; + + public static final String REMOTE_IP = "remote_ip"; } } diff --git a/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java b/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java index c7ffca86d..c780cf575 100644 --- a/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java +++ b/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java @@ -18,6 +18,7 @@ package com.alibaba.nacos.plugin.auth.spi.server; 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.exception.AccessException; import java.util.Collection; @@ -40,10 +41,11 @@ public interface AuthPluginService { * To validate whether the identity context from request is legal or illegal. * * @param identityContext where we can find the user information + * @param resource resource about this user information * @return {@code true} if legal, otherwise {@code false} * @throws AccessException if authentication is failed */ - boolean validateIdentity(IdentityContext identityContext) throws AccessException; + boolean validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException; /** * Validate the identity whether has the resource authority.