diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticationHelper.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java similarity index 80% rename from dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticationHelper.java rename to dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java index e5dae9996b..f4ece8bd5d 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticationHelper.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java @@ -17,9 +17,10 @@ package org.apache.dubbo.auth; import org.apache.dubbo.auth.exception.AccessKeyNotFoundException; +import org.apache.dubbo.auth.exception.RpcAuthenticationException; import org.apache.dubbo.auth.model.AccessKeyPair; import org.apache.dubbo.auth.spi.AccessKeyStorage; -import org.apache.dubbo.auth.spi.AuthenticationHelper; +import org.apache.dubbo.auth.spi.Authenticator; import org.apache.dubbo.auth.utils.SignatureUtils; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; @@ -27,20 +28,20 @@ import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.Invocation; -public class AccessKeyAuthenticationHelper implements AuthenticationHelper { +public class AccessKeyAuthenticator implements Authenticator { @Override - public void signForRequest(Invocation invocation, URL url) { + public void sign(Invocation invocation, URL url) { String currentTime = String.valueOf(System.currentTimeMillis()); String consumer = url.getParameter(CommonConstants.APPLICATION_KEY); AccessKeyPair accessKeyPair = getAccessKeyPair(invocation, url); - invocation.setAttachment(Constants.SIGNATURE_STRING_FORMAT, getSignature(url, invocation, accessKeyPair.getSecretKey(), currentTime)); + invocation.setAttachment(Constants.REQUEST_SIGNATURE_KEY, getSignature(url, invocation, accessKeyPair.getSecretKey(), currentTime)); invocation.setAttachment(Constants.REQUEST_TIMESTAMP_KEY, currentTime); invocation.setAttachment(Constants.AK_KEY, accessKeyPair.getAccessKey()); invocation.setAttachment(CommonConstants.CONSUMER, consumer); } @Override - public boolean authenticateRequest(Invocation invocation, URL url) { + public void authenticate(Invocation invocation, URL url) throws RpcAuthenticationException { String accessKeyId = String.valueOf(invocation.getAttachment(Constants.AK_KEY)); String requestTimestamp = String.valueOf(invocation.getAttachment(Constants.REQUEST_TIMESTAMP_KEY)); String originSignature = String.valueOf(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)); @@ -48,19 +49,22 @@ public class AccessKeyAuthenticationHelper implements AuthenticationHelper { if (StringUtils.isEmpty(accessKeyId) || StringUtils.isEmpty(consumer) || StringUtils.isEmpty(requestTimestamp) || StringUtils.isEmpty(originSignature)) { - throw new RuntimeException("Auth failed, maybe consumer not enable the auth"); + throw new RpcAuthenticationException("Failed to authenticate, maybe consumer not enable the auth"); + } + AccessKeyPair accessKeyPair = null; + try { + accessKeyPair = getAccessKeyPair(invocation, url); + } catch (Exception e) { + throw new RpcAuthenticationException("Failed to authenticate , can't load the accessKeyPair", e); } - AccessKeyPair accessKeyPair = getAccessKeyPair(invocation, url); String computeSignature = getSignature(url, invocation, accessKeyPair.getSecretKey(), requestTimestamp); boolean success = computeSignature.equals(originSignature); if (!success) { - throw new RuntimeException("Auth failed, signature is not correct"); + throw new RpcAuthenticationException("Failed to authenticate, signature is not correct"); } - return success; } - AccessKeyPair getAccessKeyPair(Invocation invocation, URL url) { AccessKeyStorage accessKeyStorage = ExtensionLoader.getExtensionLoader(AccessKeyStorage.class) .getExtension(url.getParameter(Constants.ACCESS_KEY_STORAGE_KEY, Constants.DEFAULT_ACCESS_KEY_STORAGE)); @@ -78,7 +82,7 @@ public class AccessKeyAuthenticationHelper implements AuthenticationHelper { } String getSignature(URL url, Invocation invocation, String secrectKey, String time) { - boolean parameterEncrypt = url.getParameter(Constants.PARAMTER_ENCRYPT_ENABLE_KEY, false); + boolean parameterEncrypt = url.getParameter(Constants.PARAMTER_SIGNATURE_ENABLE_KEY, false); String signature; String requestString = String.format(Constants.SIGNATURE_STRING_FORMAT, url.getColonSeparatedKey(), invocation.getMethodName(), secrectKey, time); diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/Constants.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/Constants.java index b7a76cb876..37a78b39e6 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/Constants.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/Constants.java @@ -18,13 +18,12 @@ package org.apache.dubbo.auth; public interface Constants { - String REFERENCE_AUTH = "reference.auth"; - String SERVICE_AUTH = "service.auth"; + String SERVICE_AUTH = "auth"; - String AUTH_HELPER = "auth.helper"; + String AUTHENTICATOR = "authenticator"; - String DEFAULT_AUTH_HELPER = "accesskey"; + String DEFAULT_AUTHENTICATOR = "accesskey"; String DEFAULT_ACCESS_KEY_STORAGE = "urlstorage"; @@ -42,5 +41,5 @@ public interface Constants { String SIGNATURE_STRING_FORMAT = "%s#%s#%s#%s"; - String PARAMTER_ENCRYPT_ENABLE_KEY = "paramater.sign"; + String PARAMTER_SIGNATURE_ENABLE_KEY = "param.sign"; } diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/exception/RpcAuthenticationException.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/exception/RpcAuthenticationException.java new file mode 100644 index 0000000000..9e0f5cf298 --- /dev/null +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/exception/RpcAuthenticationException.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.auth.exception; + + +public class RpcAuthenticationException extends Exception { + public RpcAuthenticationException() { + } + + public RpcAuthenticationException(String message) { + super(message); + } + + public RpcAuthenticationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java index d796595ebb..cf984a5cbf 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java @@ -17,7 +17,7 @@ package org.apache.dubbo.auth.filter; import org.apache.dubbo.auth.Constants; -import org.apache.dubbo.auth.spi.AuthenticationHelper; +import org.apache.dubbo.auth.spi.Authenticator; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; @@ -39,11 +39,11 @@ public class ConsumerSignFilter implements Filter { @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { URL url = invoker.getUrl(); - boolean shouldAuth = url.getParameter(Constants.REFERENCE_AUTH, false); + boolean shouldAuth = url.getParameter(Constants.SERVICE_AUTH, false); if (shouldAuth) { - AuthenticationHelper authenticationHelper = ExtensionLoader.getExtensionLoader(AuthenticationHelper.class) - .getExtension(url.getParameter(Constants.AUTH_HELPER, Constants.DEFAULT_AUTH_HELPER)); - authenticationHelper.signForRequest(invocation, url); + Authenticator authenticator = ExtensionLoader.getExtensionLoader(Authenticator.class) + .getExtension(url.getParameter(Constants.AUTHENTICATOR, Constants.DEFAULT_AUTHENTICATOR)); + authenticator.sign(invocation, url); } return invoker.invoke(invocation); } diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java index 278fa57c4a..fbb18a894b 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java @@ -16,13 +16,13 @@ */ package org.apache.dubbo.auth.filter; -import org.apache.dubbo.auth.spi.AuthenticationHelper; +import org.apache.dubbo.auth.Constants; +import org.apache.dubbo.auth.spi.Authenticator; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.AsyncRpcResult; -import org.apache.dubbo.auth.Constants; import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -37,18 +37,12 @@ public class ProviderAuthFilter implements Filter { URL url = invoker.getUrl(); boolean shouldAuth = url.getParameter(Constants.SERVICE_AUTH, false); if (shouldAuth) { - AuthenticationHelper authenticationHelper = ExtensionLoader.getExtensionLoader(AuthenticationHelper.class) - .getExtension(url.getParameter(Constants.AUTH_HELPER, Constants.DEFAULT_AUTH_HELPER)); - boolean authResult = false; + Authenticator authenticator = ExtensionLoader.getExtensionLoader(Authenticator.class) + .getExtension(url.getParameter(Constants.AUTHENTICATOR, Constants.DEFAULT_AUTHENTICATOR)); try { - authResult = authenticationHelper.authenticateRequest(invocation, url); - if (!authResult) { - SecurityException securityException = new SecurityException("Authenticate Request failed"); - return AsyncRpcResult.newDefaultAsyncResult(securityException, invocation); - } + authenticator.authenticate(invocation, url); } catch (Exception e) { - SecurityException securityException = new SecurityException("Authenticate Request failed,", e); - return AsyncRpcResult.newDefaultAsyncResult(securityException, invocation); + return AsyncRpcResult.newDefaultAsyncResult(e, invocation); } } return invoker.invoke(invocation); diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/AuthenticationHelper.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/Authenticator.java similarity index 78% rename from dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/AuthenticationHelper.java rename to dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/Authenticator.java index d86f3a6896..45fd9138e4 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/AuthenticationHelper.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/Authenticator.java @@ -17,12 +17,13 @@ package org.apache.dubbo.auth.spi; +import org.apache.dubbo.auth.exception.RpcAuthenticationException; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.rpc.Invocation; @SPI("accessKey") -public interface AuthenticationHelper { +public interface Authenticator { /** * give a sign to request @@ -30,14 +31,14 @@ public interface AuthenticationHelper { * @param invocation * @param url */ - void signForRequest(Invocation invocation, URL url); + void sign(Invocation invocation, URL url); + /** * verify the signature of the request is valid or not - * * @param invocation * @param url - * @return true if the signature is valid + * @throws RpcAuthenticationException when failed to authenticate current invocation */ - boolean authenticateRequest(Invocation invocation, URL url); + void authenticate(Invocation invocation, URL url) throws RpcAuthenticationException; } diff --git a/dubbo-plugin/dubbo-auth/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.auth.spi.AuthenticationHelper b/dubbo-plugin/dubbo-auth/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.auth.spi.AuthenticationHelper deleted file mode 100644 index 7a7f392132..0000000000 --- a/dubbo-plugin/dubbo-auth/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.auth.spi.AuthenticationHelper +++ /dev/null @@ -1 +0,0 @@ -accesskey=org.apache.dubbo.auth.AccessKeyAuthenticationHelper \ No newline at end of file diff --git a/dubbo-plugin/dubbo-auth/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.auth.spi.Authenticator b/dubbo-plugin/dubbo-auth/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.auth.spi.Authenticator new file mode 100644 index 0000000000..b4b2fbd0f2 --- /dev/null +++ b/dubbo-plugin/dubbo-auth/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.auth.spi.Authenticator @@ -0,0 +1 @@ +accesskey=org.apache.dubbo.auth.AccessKeyAuthenticator \ No newline at end of file diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java new file mode 100644 index 0000000000..38f7d43398 --- /dev/null +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.auth; + +import org.apache.dubbo.auth.exception.RpcAuthenticationException; +import org.apache.dubbo.auth.model.AccessKeyPair; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.RpcInvocation; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +class AccessKeyAuthenticatorTest { + + @Test + void testSignForRequest() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(CommonConstants.APPLICATION_KEY, "test") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk"); + Invocation invocation = new RpcInvocation(); + + AccessKeyAuthenticator helper = mock(AccessKeyAuthenticator.class); + doCallRealMethod().when(helper).sign(invocation, url); + when(helper.getSignature(eq(url), eq(invocation), eq("sk"), anyString())).thenReturn("dubbo"); + + AccessKeyPair accessKeyPair = mock(AccessKeyPair.class); + when(accessKeyPair.getSecretKey()).thenReturn("sk"); + when(helper.getAccessKeyPair(invocation, url)).thenReturn(accessKeyPair); + + helper.sign(invocation, url); + assertEquals(String.valueOf(invocation.getAttachment(CommonConstants.CONSUMER)), url.getParameter(CommonConstants.APPLICATION_KEY)); + assertNotNull(invocation.getAttachments().get(Constants.REQUEST_SIGNATURE_KEY)); + assertEquals(invocation.getAttachments().get(Constants.REQUEST_SIGNATURE_KEY), "dubbo"); + } + + @Test + void testAuthenticateRequest() throws RpcAuthenticationException { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(CommonConstants.APPLICATION_KEY, "test") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk"); + Invocation invocation = new RpcInvocation(); + invocation.setAttachment(Constants.ACCESS_KEY_ID_KEY, "ak"); + invocation.setAttachment(Constants.REQUEST_SIGNATURE_KEY, "dubbo"); + invocation.setAttachment(Constants.REQUEST_TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis())); + invocation.setAttachment(CommonConstants.CONSUMER, "test"); + + AccessKeyAuthenticator helper = mock(AccessKeyAuthenticator.class); + doCallRealMethod().when(helper).authenticate(invocation, url); + when(helper.getSignature(eq(url), eq(invocation), eq("sk"), anyString())).thenReturn("dubbo"); + + AccessKeyPair accessKeyPair = mock(AccessKeyPair.class); + when(accessKeyPair.getSecretKey()).thenReturn("sk"); + when(helper.getAccessKeyPair(invocation, url)).thenReturn(accessKeyPair); + + assertDoesNotThrow(() -> helper.authenticate(invocation, url)); + } + + @Test + void testAuthenticateRequestNoSignature() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(CommonConstants.APPLICATION_KEY, "test") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk"); + Invocation invocation = new RpcInvocation(); + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + assertThrows(RpcAuthenticationException.class, () -> helper.authenticate(invocation, url)); + } + + @Test + void testGetAccessKeyPairFailed() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak"); + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + Invocation invocation = mock(Invocation.class); + assertThrows(RuntimeException.class, () -> helper.getAccessKeyPair(invocation, url)); + } + + @Test + void testGetSignatureNoParameter() { + URL url = mock(URL.class); + Invocation invocation = mock(Invocation.class); + String secretKey = "123456"; + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + String signature = helper.getSignature(url, invocation, secretKey, String.valueOf(System.currentTimeMillis())); + assertNotNull(signature); + } + + @Test + void testGetSignatureWithParameter() { + URL url = mock(URL.class); + when(url.getParameter(Constants.PARAMTER_SIGNATURE_ENABLE_KEY, false)).thenReturn(true); + Invocation invocation = mock(Invocation.class); + String secretKey = "123456"; + Object[] params = {"dubbo", new ArrayList()}; + when(invocation.getArguments()).thenReturn(params); + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + String signature = helper.getSignature(url, invocation, secretKey, String.valueOf(System.currentTimeMillis())); + assertNotNull(signature); + + Object[] fakeParams = {"dubbo1", new ArrayList<>()}; + when(invocation.getArguments()).thenReturn(fakeParams); + String signature1 = helper.getSignature(url, invocation, secretKey, String.valueOf(System.currentTimeMillis())); + assertNotEquals(signature, signature1); + + } +} \ No newline at end of file diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/DefaultAccessKeyStorageTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/DefaultAccessKeyStorageTest.java new file mode 100644 index 0000000000..e757cc815b --- /dev/null +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/DefaultAccessKeyStorageTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.auth; + +import org.apache.dubbo.auth.model.AccessKeyPair; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; + + +class DefaultAccessKeyStorageTest { + + @Test + void testGetAccessKey() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk"); + DefaultAccessKeyStorage defaultAccessKeyStorage = new DefaultAccessKeyStorage(); + AccessKeyPair accessKey = defaultAccessKeyStorage.getAccessKey(url, mock(Invocation.class)); + assertNotNull(accessKey); + assertEquals(accessKey.getAccessKey(), "ak"); + assertEquals(accessKey.getSecretKey(), "sk"); + } +} \ No newline at end of file diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java new file mode 100644 index 0000000000..b335e3bfa2 --- /dev/null +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.auth.filter; + +import org.apache.dubbo.auth.Constants; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.junit.jupiter.api.Test; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +class ConsumerSignFilterTest { + + @Test + void testAuthDisabled() { + URL url = mock(URL.class); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invoker.getUrl()).thenReturn(url); + ConsumerSignFilter consumerSignFilter = new ConsumerSignFilter(); + consumerSignFilter.invoke(invoker, invocation); + verify(invocation, never()).setAttachment(eq(Constants.REQUEST_SIGNATURE_KEY), anyString()); + } + + @Test + void testAuthEnabled() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk") + .addParameter(CommonConstants.APPLICATION_KEY, "test") + .addParameter(Constants.SERVICE_AUTH, true); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invoker.getUrl()).thenReturn(url); + ConsumerSignFilter consumerSignFilter = new ConsumerSignFilter(); + consumerSignFilter.invoke(invoker, invocation); + verify(invocation, times(1)).setAttachment(eq(Constants.REQUEST_SIGNATURE_KEY), anyString()); + } +} \ No newline at end of file diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java new file mode 100644 index 0000000000..a0b197d983 --- /dev/null +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.auth.filter; + +import org.apache.dubbo.auth.Constants; +import org.apache.dubbo.auth.exception.RpcAuthenticationException; +import org.apache.dubbo.auth.utils.SignatureUtils; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +class ProviderAuthFilterTest { + @Test + void testAuthDisabled() { + URL url = mock(URL.class); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invoker.getUrl()).thenReturn(url); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + providerAuthFilter.invoke(invoker, invocation); + verify(url, never()).getParameter(eq(Constants.AUTHENTICATOR), eq(Constants.DEFAULT_AUTHENTICATOR)); + } + + @Test + void testAuthEnabled() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk") + .addParameter(CommonConstants.APPLICATION_KEY, "test") + .addParameter(Constants.SERVICE_AUTH, true); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invoker.getUrl()).thenReturn(url); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + providerAuthFilter.invoke(invoker, invocation); + verify(invocation, atLeastOnce()).getAttachment(anyString()); + } + + + @Test + void testAuthFailed() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk") + .addParameter(CommonConstants.APPLICATION_KEY, "test") + .addParameter(Constants.SERVICE_AUTH, true); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(null); + when(invoker.getUrl()).thenReturn(url); + + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + Result result = providerAuthFilter.invoke(invoker, invocation); + assertTrue(result.hasException()); + + } + + @Test + void testAuthFailedWhenNoSignature() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk") + .addParameter(CommonConstants.APPLICATION_KEY, "test") + .addParameter(Constants.SERVICE_AUTH, true); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(null); + when(invoker.getUrl()).thenReturn(url); + + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + Result result = providerAuthFilter.invoke(invoker, invocation); + assertTrue(result.hasException()); + } + + @Test + void testAuthFailedWhenNoAccessKeyPair() { + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .addParameter(CommonConstants.APPLICATION_KEY, "test-provider") + .addParameter(Constants.SERVICE_AUTH, true); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn("dubbo"); + when(invocation.getAttachment(Constants.AK_KEY)).thenReturn("ak"); + when(invocation.getAttachment(CommonConstants.CONSUMER)).thenReturn("test-consumer"); + when(invocation.getAttachment(Constants.REQUEST_TIMESTAMP_KEY)).thenReturn(System.currentTimeMillis()); + when(invoker.getUrl()).thenReturn(url); + + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + Result result = providerAuthFilter.invoke(invoker, invocation); + assertTrue(result.hasException()); + assertTrue(result.getException() instanceof RpcAuthenticationException); + } + + @Test + void testAuthFailedWhenParameterError() { + String service = "org.apache.dubbo.DemoService"; + String method = "test"; + Object[] originalParams = new Object[]{"dubbo1", "dubbo2"}; + long currentTimeMillis = System.currentTimeMillis(); + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .setServiceInterface(service) + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk") + .addParameter(CommonConstants.APPLICATION_KEY, "test-provider") + .addParameter(Constants.PARAMTER_SIGNATURE_ENABLE_KEY, true) + .addParameter(Constants.SERVICE_AUTH, true); + + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invocation.getAttachment(Constants.AK_KEY)).thenReturn("ak"); + when(invocation.getAttachment(CommonConstants.CONSUMER)).thenReturn("test-consumer"); + when(invocation.getAttachment(Constants.REQUEST_TIMESTAMP_KEY)).thenReturn(currentTimeMillis); + when(invocation.getMethodName()).thenReturn(method); + Object[] fakeParams = new Object[]{"dubbo1", "dubbo3"}; + when(invocation.getArguments()).thenReturn(fakeParams); + when(invoker.getUrl()).thenReturn(url); + + + String requestString = String.format(Constants.SIGNATURE_STRING_FORMAT, + url.getColonSeparatedKey(), invocation.getMethodName(), "sk", currentTimeMillis); + String sign = SignatureUtils.sign(originalParams, requestString, "sk"); + when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(sign); + + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + Result result = providerAuthFilter.invoke(invoker, invocation); + assertTrue(result.hasException()); + assertTrue(result.getException() instanceof RpcAuthenticationException); + } + + @Test + void testAuthSuccessfully() { + String service = "org.apache.dubbo.DemoService"; + String method = "test"; + long currentTimeMillis = System.currentTimeMillis(); + URL url = URL.valueOf("dubbo://10.10.10.10:2181") + .setServiceInterface(service) + .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak") + .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk") + .addParameter(CommonConstants.APPLICATION_KEY, "test-provider") + .addParameter(Constants.SERVICE_AUTH, true); + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + when(invocation.getAttachment(Constants.AK_KEY)).thenReturn("ak"); + when(invocation.getAttachment(CommonConstants.CONSUMER)).thenReturn("test-consumer"); + when(invocation.getAttachment(Constants.REQUEST_TIMESTAMP_KEY)).thenReturn(currentTimeMillis); + when(invocation.getMethodName()).thenReturn(method); + when(invoker.getUrl()).thenReturn(url); + + + String requestString = String.format(Constants.SIGNATURE_STRING_FORMAT, + url.getColonSeparatedKey(), invocation.getMethodName(), "sk", currentTimeMillis); + String sign = SignatureUtils.sign(requestString, "sk"); + when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(sign); + + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + Result result = providerAuthFilter.invoke(invoker, invocation); + assertNull(result); + } +} \ No newline at end of file