diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/IdentifyConstants.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/IdentifyConstants.java index 3689b62cd..dea710158 100644 --- a/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/IdentifyConstants.java +++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/IdentifyConstants.java @@ -27,6 +27,8 @@ public class IdentifyConstants { public static final String SECRET_KEY = "secretKey"; + public static final String SECURITY_TOKEN_HEADER = "Spas-SecurityToken"; + public static final String TENANT_ID = "tenantId"; public static final String PROPERTIES_FILENAME = "spas.properties"; diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolder.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolder.java new file mode 100644 index 000000000..2fb316481 --- /dev/null +++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolder.java @@ -0,0 +1,98 @@ +/* + * 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.client.auth.ram.identify; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException; +import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager; +import com.alibaba.nacos.client.utils.LogUtils; +import com.alibaba.nacos.common.http.HttpRestResult; +import com.alibaba.nacos.common.http.param.Header; +import com.alibaba.nacos.common.http.param.Query; +import com.alibaba.nacos.common.utils.JacksonUtils; +import com.fasterxml.jackson.core.type.TypeReference; +import org.slf4j.Logger; + +/** + * Sts credential holder. + * + * @author xiweng.yy + */ +public class StsCredentialHolder { + + private static final Logger LOGGER = LogUtils.logger(StsCredentialHolder.class); + + private static final StsCredentialHolder INSTANCE = new StsCredentialHolder(); + + private StsCredential stsCredential; + + private StsCredentialHolder() { + } + + public static StsCredentialHolder getInstance() { + return INSTANCE; + } + + /** + * Get Sts Credential. + * + * @return StsCredential + */ + public StsCredential getStsCredential() { + boolean cacheSecurityCredentials = StsConfig.getInstance().isCacheSecurityCredentials(); + if (cacheSecurityCredentials && stsCredential != null) { + long currentTime = System.currentTimeMillis(); + long expirationTime = stsCredential.getExpiration().getTime(); + int timeToRefreshInMillisecond = StsConfig.getInstance().getTimeToRefreshInMillisecond(); + if (expirationTime - currentTime > timeToRefreshInMillisecond) { + return stsCredential; + } + } + String stsResponse = getStsResponse(); + stsCredential = JacksonUtils.toObj(stsResponse, new TypeReference() { + }); + LOGGER.info("[getSTSCredential] code:{}, accessKeyId:{}, lastUpdated:{}, expiration:{}", + stsCredential.getCode(), stsCredential.getAccessKeyId(), stsCredential.getLastUpdated(), + stsCredential.getExpiration()); + return stsCredential; + } + + private static String getStsResponse() { + String securityCredentials = StsConfig.getInstance().getSecurityCredentials(); + if (securityCredentials != null) { + return securityCredentials; + } + String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl(); + try { + HttpRestResult result = ConfigHttpClientManager.getInstance().getNacosRestTemplate() + .get(securityCredentialsUrl, Header.EMPTY, Query.EMPTY, String.class); + + if (!result.ok()) { + LOGGER.error( + "can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}", + securityCredentialsUrl, result.getCode(), result.getMessage()); + throw new NacosRuntimeException(NacosException.SERVER_ERROR, + "can not get security credentials, responseCode: " + result.getCode() + ", response: " + result + .getMessage()); + } + return result.getData(); + } catch (Exception e) { + LOGGER.error("can not get security credentials", e); + throw new NacosRuntimeException(NacosException.SERVER_ERROR, e); + } + } +} diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java index 7976eff76..f8d12577b 100644 --- a/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java +++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java @@ -16,23 +16,15 @@ package com.alibaba.nacos.client.auth.ram.injector; -import com.alibaba.nacos.api.exception.NacosException; -import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException; -import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; import com.alibaba.nacos.client.auth.ram.RamContext; -import com.alibaba.nacos.plugin.auth.api.RequestResource; -import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager; -import com.alibaba.nacos.client.auth.ram.utils.SpasAdapter; +import com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants; import com.alibaba.nacos.client.auth.ram.identify.StsConfig; import com.alibaba.nacos.client.auth.ram.identify.StsCredential; -import com.alibaba.nacos.client.utils.LogUtils; -import com.alibaba.nacos.common.http.HttpRestResult; -import com.alibaba.nacos.common.http.param.Header; -import com.alibaba.nacos.common.http.param.Query; -import com.alibaba.nacos.common.utils.JacksonUtils; +import com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder; +import com.alibaba.nacos.client.auth.ram.utils.SpasAdapter; import com.alibaba.nacos.common.utils.StringUtils; -import com.fasterxml.jackson.core.type.TypeReference; -import org.slf4j.Logger; +import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; +import com.alibaba.nacos.plugin.auth.api.RequestResource; import java.util.Map; @@ -43,26 +35,20 @@ import java.util.Map; */ public class ConfigResourceInjector extends AbstractResourceInjector { - private static final Logger LOGGER = LogUtils.logger(ConfigResourceInjector.class); - - private static final String SECURITY_TOKEN_HEADER = "Spas-SecurityToken"; - private static final String ACCESS_KEY_HEADER = "Spas-AccessKey"; private static final String DEFAULT_RESOURCE = ""; - private StsCredential stsCredential; - @Override public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) { String accessKey = context.getAccessKey(); String secretKey = context.getSecretKey(); // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权 if (StsConfig.getInstance().isStsOn()) { - StsCredential stsCredential = getStsCredential(); + StsCredential stsCredential = StsCredentialHolder.getInstance().getStsCredential(); accessKey = stsCredential.getAccessKeyId(); secretKey = stsCredential.getAccessKeySecret(); - result.setParameter(SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken()); + result.setParameter(IdentifyConstants.SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken()); } if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotBlank(secretKey)) { @@ -73,50 +59,6 @@ public class ConfigResourceInjector extends AbstractResourceInjector { result.setParameters(signHeaders); } - private StsCredential getStsCredential() { - boolean cacheSecurityCredentials = StsConfig.getInstance().isCacheSecurityCredentials(); - if (cacheSecurityCredentials && stsCredential != null) { - long currentTime = System.currentTimeMillis(); - long expirationTime = stsCredential.getExpiration().getTime(); - int timeToRefreshInMillisecond = StsConfig.getInstance().getTimeToRefreshInMillisecond(); - if (expirationTime - currentTime > timeToRefreshInMillisecond) { - return stsCredential; - } - } - String stsResponse = getStsResponse(); - stsCredential = JacksonUtils.toObj(stsResponse, new TypeReference() { - }); - LOGGER.info("[getSTSCredential] code:{}, accessKeyId:{}, lastUpdated:{}, expiration:{}", - stsCredential.getCode(), stsCredential.getAccessKeyId(), stsCredential.getLastUpdated(), - stsCredential.getExpiration()); - return stsCredential; - } - - private static String getStsResponse() { - String securityCredentials = StsConfig.getInstance().getSecurityCredentials(); - if (securityCredentials != null) { - return securityCredentials; - } - String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl(); - try { - HttpRestResult result = ConfigHttpClientManager.getInstance().getNacosRestTemplate() - .get(securityCredentialsUrl, Header.EMPTY, Query.EMPTY, String.class); - - if (!result.ok()) { - LOGGER.error( - "can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}", - securityCredentialsUrl, result.getCode(), result.getMessage()); - throw new NacosRuntimeException(NacosException.SERVER_ERROR, - "can not get security credentials, responseCode: " + result.getCode() + ", response: " + result - .getMessage()); - } - return result.getData(); - } catch (Exception e) { - LOGGER.error("can not get security credentials", e); - throw new NacosRuntimeException(NacosException.SERVER_ERROR, e); - } - } - private String getResource(String tenant, String group) { if (StringUtils.isNotBlank(tenant) && StringUtils.isNotBlank(group)) { return tenant + "+" + group; diff --git a/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjector.java b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjector.java index 3ea10f132..fa90cc0d7 100644 --- a/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjector.java +++ b/client/src/main/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjector.java @@ -18,6 +18,10 @@ package com.alibaba.nacos.client.auth.ram.injector; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.naming.utils.NamingUtils; +import com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants; +import com.alibaba.nacos.client.auth.ram.identify.StsConfig; +import com.alibaba.nacos.client.auth.ram.identify.StsCredential; +import com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder; import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; import com.alibaba.nacos.client.auth.ram.RamContext; import com.alibaba.nacos.plugin.auth.api.RequestResource; @@ -43,11 +47,20 @@ public class NamingResourceInjector extends AbstractResourceInjector { public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) { if (context.validate()) { try { + String accessKey = context.getAccessKey(); + String secretKey = context.getSecretKey(); + // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权 + if (StsConfig.getInstance().isStsOn()) { + StsCredential stsCredential = StsCredentialHolder.getInstance().getStsCredential(); + accessKey = stsCredential.getAccessKeyId(); + secretKey = stsCredential.getAccessKeySecret(); + result.setParameter(IdentifyConstants.SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken()); + } String signData = getSignData(getGroupedServiceName(resource)); - String signature = SignUtil.sign(signData, context.getSecretKey()); + String signature = SignUtil.sign(signData, secretKey); result.setParameter(SIGNATURE_FILED, signature); result.setParameter(DATA_FILED, signData); - result.setParameter(AK_FILED, context.getAccessKey()); + result.setParameter(AK_FILED, accessKey); } catch (Exception e) { NAMING_LOGGER.error("inject ak/sk failed.", e); } diff --git a/client/src/test/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolderTest.java b/client/src/test/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolderTest.java new file mode 100644 index 000000000..41440f2bc --- /dev/null +++ b/client/src/test/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolderTest.java @@ -0,0 +1,134 @@ +/* + * 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.client.auth.ram.identify; + +import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException; +import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager; +import com.alibaba.nacos.common.http.client.NacosRestTemplate; +import com.alibaba.nacos.common.http.client.request.HttpClientRequest; +import com.alibaba.nacos.common.http.client.response.HttpClientResponse; +import com.alibaba.nacos.common.http.param.Header; +import com.alibaba.nacos.common.utils.JacksonUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.io.ByteArrayInputStream; +import java.lang.reflect.Field; +import java.util.Date; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class StsCredentialHolderTest { + + private String securityCredentialsUrl; + + private HttpClientRequest httpClient; + + @Mock + private HttpClientRequest mockRest; + + @Before + public void setUp() throws Exception { + securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl(); + StsConfig.getInstance().setSecurityCredentialsUrl("url"); + Field field = NacosRestTemplate.class.getDeclaredField("requestClient"); + field.setAccessible(true); + httpClient = (HttpClientRequest) field.get(ConfigHttpClientManager.getInstance().getNacosRestTemplate()); + field.set(ConfigHttpClientManager.getInstance().getNacosRestTemplate(), mockRest); + } + + @After + public void tearDown() throws Exception { + StsConfig.getInstance().setSecurityCredentials(null); + StsConfig.getInstance().setSecurityCredentialsUrl(securityCredentialsUrl); + Field field = NacosRestTemplate.class.getDeclaredField("requestClient"); + field.setAccessible(true); + field.set(ConfigHttpClientManager.getInstance().getNacosRestTemplate(), httpClient); + clearForSts(); + } + + private void clearForSts() throws NoSuchFieldException, IllegalAccessException { + StsConfig.getInstance().setSecurityCredentialsUrl(null); + Field field = StsCredentialHolder.class.getDeclaredField("stsCredential"); + field.setAccessible(true); + field.set(StsCredentialHolder.getInstance(), null); + } + + @Test + public void testGetStsCredentialFromCache() throws NoSuchFieldException, IllegalAccessException { + StsCredential stsCredential = buildMockStsCredential(); + setStsCredential(stsCredential); + assertEquals(stsCredential, StsCredentialHolder.getInstance().getStsCredential()); + } + + private void setStsCredential(StsCredential stsCredential) throws NoSuchFieldException, IllegalAccessException { + Field field = StsCredentialHolder.class.getDeclaredField("stsCredential"); + field.setAccessible(true); + field.set(StsCredentialHolder.getInstance(), stsCredential); + } + + @Test + public void testGetStsCredentialFromStringCache() throws NoSuchFieldException, IllegalAccessException { + StsCredential stsCredential = buildMockStsCredential(); + StsConfig.getInstance().setSecurityCredentials(JacksonUtils.toJson(stsCredential)); + assertEquals(stsCredential.toString(), StsCredentialHolder.getInstance().getStsCredential().toString()); + } + + @Test + public void testGetStsCredentialFromRequest() throws Exception { + StsCredential stsCredential = buildMockStsCredential(); + HttpClientResponse response = mock(HttpClientResponse.class); + when(response.getStatusCode()).thenReturn(200); + when(response.getHeaders()).thenReturn(Header.newInstance()); + when(response.getBody()).thenReturn(new ByteArrayInputStream(JacksonUtils.toJsonBytes(stsCredential))); + when(mockRest.execute(any(), any(), any())).thenReturn(response); + assertEquals(stsCredential.toString(), StsCredentialHolder.getInstance().getStsCredential().toString()); + } + + @Test(expected = NacosRuntimeException.class) + public void testGetStsCredentialFromRequestFailure() throws Exception { + HttpClientResponse response = mock(HttpClientResponse.class); + when(response.getStatusCode()).thenReturn(500); + when(response.getHeaders()).thenReturn(Header.newInstance()); + when(response.getBody()).thenReturn(new ByteArrayInputStream(new byte[0])); + when(mockRest.execute(any(), any(), any())).thenReturn(response); + StsCredentialHolder.getInstance().getStsCredential(); + } + + @Test(expected = NacosRuntimeException.class) + public void testGetStsCredentialFromRequestException() throws Exception { + when(mockRest.execute(any(), any(), any())).thenThrow(new RuntimeException("test")); + StsCredentialHolder.getInstance().getStsCredential(); + } + + private StsCredential buildMockStsCredential() { + StsCredential stsCredential = new StsCredential(); + stsCredential.setAccessKeyId("test-sts-ak"); + stsCredential.setAccessKeySecret("test-sts-sk"); + stsCredential.setSecurityToken("test-sts-token"); + stsCredential.setExpiration(new Date(System.currentTimeMillis() + 1000000)); + return stsCredential; + } +} \ No newline at end of file diff --git a/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjectorTest.java b/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjectorTest.java index 7a9495405..13a1c7421 100644 --- a/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjectorTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjectorTest.java @@ -17,16 +17,22 @@ package com.alibaba.nacos.client.auth.ram.injector; import com.alibaba.nacos.api.PropertyKeyConst; -import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; import com.alibaba.nacos.client.auth.ram.RamContext; -import com.alibaba.nacos.plugin.auth.api.RequestResource; +import com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants; import com.alibaba.nacos.client.auth.ram.identify.StsConfig; +import com.alibaba.nacos.client.auth.ram.identify.StsCredential; +import com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder; +import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; +import com.alibaba.nacos.plugin.auth.api.RequestResource; import com.alibaba.nacos.plugin.auth.constant.SignType; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.lang.reflect.Field; +import java.util.Date; + public class ConfigResourceInjectorTest { private ConfigResourceInjector configResourceInjector; @@ -39,6 +45,8 @@ public class ConfigResourceInjectorTest { private String cachedSecurityCredentials; + private StsCredential stsCredential; + @Before public void setUp() throws Exception { configResourceInjector = new ConfigResourceInjector(); @@ -53,16 +61,18 @@ public class ConfigResourceInjectorTest { cachedSecurityCredentials = StsConfig.getInstance().getSecurityCredentials(); StsConfig.getInstance().setSecurityCredentialsUrl(""); StsConfig.getInstance().setSecurityCredentials(""); + stsCredential = new StsCredential(); } @After - public void tearDown() { + public void tearDown() throws NoSuchFieldException, IllegalAccessException { StsConfig.getInstance().setSecurityCredentialsUrl(cachedSecurityCredentialsUrl); StsConfig.getInstance().setSecurityCredentials(cachedSecurityCredentials); + clearForSts(); } @Test - public void testDoInject() throws Exception { + public void testDoInjectWithFullResource() throws Exception { LoginIdentityContext actual = new LoginIdentityContext(); configResourceInjector.doInject(resource, ramContext, actual); Assert.assertEquals(3, actual.getAllKey().size()); @@ -70,4 +80,67 @@ public class ConfigResourceInjectorTest { Assert.assertTrue(actual.getAllKey().contains("Timestamp")); Assert.assertTrue(actual.getAllKey().contains("Spas-Signature")); } + + @Test + public void testDoInjectWithTenant() throws Exception { + resource.setGroup(""); + LoginIdentityContext actual = new LoginIdentityContext(); + configResourceInjector.doInject(resource, ramContext, actual); + Assert.assertEquals(3, actual.getAllKey().size()); + Assert.assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter("Spas-AccessKey")); + Assert.assertTrue(actual.getAllKey().contains("Timestamp")); + Assert.assertTrue(actual.getAllKey().contains("Spas-Signature")); + } + + @Test + public void testDoInjectWithGroup() throws Exception { + resource.setNamespace(""); + LoginIdentityContext actual = new LoginIdentityContext(); + configResourceInjector.doInject(resource, ramContext, actual); + Assert.assertEquals(3, actual.getAllKey().size()); + Assert.assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter("Spas-AccessKey")); + Assert.assertTrue(actual.getAllKey().contains("Timestamp")); + Assert.assertTrue(actual.getAllKey().contains("Spas-Signature")); + } + + @Test + public void testDoInjectWithoutResource() throws Exception { + resource = new RequestResource(); + LoginIdentityContext actual = new LoginIdentityContext(); + configResourceInjector.doInject(resource, ramContext, actual); + Assert.assertEquals(3, actual.getAllKey().size()); + Assert.assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter("Spas-AccessKey")); + Assert.assertTrue(actual.getAllKey().contains("Timestamp")); + Assert.assertTrue(actual.getAllKey().contains("Spas-Signature")); + } + + @Test + public void testDoInjectForSts() throws NoSuchFieldException, IllegalAccessException { + prepareForSts(); + LoginIdentityContext actual = new LoginIdentityContext(); + configResourceInjector.doInject(resource, ramContext, actual); + Assert.assertEquals(4, actual.getAllKey().size()); + Assert.assertEquals("test-sts-ak", actual.getParameter("Spas-AccessKey")); + Assert.assertTrue(actual.getAllKey().contains("Timestamp")); + Assert.assertTrue(actual.getAllKey().contains("Spas-Signature")); + Assert.assertTrue(actual.getAllKey().contains(IdentifyConstants.SECURITY_TOKEN_HEADER)); + } + + private void prepareForSts() throws NoSuchFieldException, IllegalAccessException { + StsConfig.getInstance().setSecurityCredentialsUrl("test"); + Field field = StsCredentialHolder.class.getDeclaredField("stsCredential"); + field.setAccessible(true); + field.set(StsCredentialHolder.getInstance(), stsCredential); + stsCredential.setAccessKeyId("test-sts-ak"); + stsCredential.setAccessKeySecret("test-sts-sk"); + stsCredential.setSecurityToken("test-sts-token"); + stsCredential.setExpiration(new Date(System.currentTimeMillis() + 1000000)); + } + + private void clearForSts() throws NoSuchFieldException, IllegalAccessException { + StsConfig.getInstance().setSecurityCredentialsUrl(null); + Field field = StsCredentialHolder.class.getDeclaredField("stsCredential"); + field.setAccessible(true); + field.set(StsCredentialHolder.getInstance(), null); + } } diff --git a/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java b/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java index c31f018ec..97f36ecd9 100644 --- a/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java @@ -17,14 +17,21 @@ package com.alibaba.nacos.client.auth.ram.injector; import com.alibaba.nacos.api.PropertyKeyConst; -import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; import com.alibaba.nacos.client.auth.ram.RamContext; -import com.alibaba.nacos.plugin.auth.api.RequestResource; +import com.alibaba.nacos.client.auth.ram.identify.StsConfig; +import com.alibaba.nacos.client.auth.ram.identify.StsCredential; +import com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder; import com.alibaba.nacos.client.auth.ram.utils.SignUtil; +import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; +import com.alibaba.nacos.plugin.auth.api.RequestResource; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.lang.reflect.Field; +import java.util.Date; + public class NamingResourceInjectorTest { private NamingResourceInjector namingResourceInjector; @@ -33,12 +40,32 @@ public class NamingResourceInjectorTest { private RequestResource resource; + private StsCredential stsCredential; + @Before public void setUp() throws Exception { namingResourceInjector = new NamingResourceInjector(); ramContext = new RamContext(); ramContext.setAccessKey(PropertyKeyConst.ACCESS_KEY); ramContext.setSecretKey(PropertyKeyConst.SECRET_KEY); + stsCredential = new StsCredential(); + } + + @After + public void tearDown() throws NoSuchFieldException, IllegalAccessException { + clearForSts(); + } + + @Test + public void testDoInjectWithEmpty() throws Exception { + resource = RequestResource.namingBuilder().setResource("").build(); + LoginIdentityContext actual = new LoginIdentityContext(); + namingResourceInjector.doInject(resource, ramContext, actual); + String expectSign = SignUtil.sign(actual.getParameter("data"), PropertyKeyConst.SECRET_KEY); + Assert.assertEquals(3, actual.getAllKey().size()); + Assert.assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter("ak")); + Assert.assertTrue(Long.parseLong(actual.getParameter("data")) - System.currentTimeMillis() < 100); + Assert.assertEquals(expectSign, actual.getParameter("signature")); } @Test @@ -46,10 +73,10 @@ public class NamingResourceInjectorTest { resource = RequestResource.namingBuilder().setResource("test@@aaa").setGroup("group").build(); LoginIdentityContext actual = new LoginIdentityContext(); namingResourceInjector.doInject(resource, ramContext, actual); + String expectSign = SignUtil.sign(actual.getParameter("data"), PropertyKeyConst.SECRET_KEY); Assert.assertEquals(3, actual.getAllKey().size()); Assert.assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter("ak")); Assert.assertTrue(actual.getParameter("data").endsWith("@@test@@aaa")); - String expectSign = SignUtil.sign(actual.getParameter("data"), PropertyKeyConst.SECRET_KEY); Assert.assertEquals(expectSign, actual.getParameter("signature")); } @@ -58,10 +85,64 @@ public class NamingResourceInjectorTest { resource = RequestResource.namingBuilder().setResource("aaa").setGroup("group").build(); LoginIdentityContext actual = new LoginIdentityContext(); namingResourceInjector.doInject(resource, ramContext, actual); + Assert.assertTrue(actual.getParameter("data").endsWith("@@group@@aaa")); Assert.assertEquals(3, actual.getAllKey().size()); Assert.assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter("ak")); - Assert.assertTrue(actual.getParameter("data").endsWith("@@group@@aaa")); String expectSign = SignUtil.sign(actual.getParameter("data"), PropertyKeyConst.SECRET_KEY); Assert.assertEquals(expectSign, actual.getParameter("signature")); } + + @Test + public void testDoInjectWithGroupForSts() throws Exception { + prepareForSts(); + resource = RequestResource.namingBuilder().setResource("test@@aaa").setGroup("group").build(); + LoginIdentityContext actual = new LoginIdentityContext(); + namingResourceInjector.doInject(resource, ramContext, actual); + String expectSign = SignUtil.sign(actual.getParameter("data"), "test-sts-sk"); + Assert.assertEquals(4, actual.getAllKey().size()); + Assert.assertEquals("test-sts-ak", actual.getParameter("ak")); + Assert.assertTrue(actual.getParameter("data").endsWith("@@test@@aaa")); + Assert.assertEquals(expectSign, actual.getParameter("signature")); + } + + @Test + public void testDoInjectWithoutGroupForSts() throws Exception { + prepareForSts(); + resource = RequestResource.namingBuilder().setResource("aaa").setGroup("group").build(); + LoginIdentityContext actual = new LoginIdentityContext(); + namingResourceInjector.doInject(resource, ramContext, actual); + String expectSign = SignUtil.sign(actual.getParameter("data"), "test-sts-sk"); + Assert.assertEquals(4, actual.getAllKey().size()); + Assert.assertEquals("test-sts-ak", actual.getParameter("ak")); + Assert.assertTrue(actual.getParameter("data").endsWith("@@group@@aaa")); + Assert.assertEquals(expectSign, actual.getParameter("signature")); + } + + @Test + public void testDoInjectForStsWithException() throws Exception { + prepareForSts(); + stsCredential.setExpiration(new Date()); + resource = RequestResource.namingBuilder().setResource("aaa").setGroup("group").build(); + LoginIdentityContext actual = new LoginIdentityContext(); + namingResourceInjector.doInject(resource, ramContext, actual); + Assert.assertEquals(0, actual.getAllKey().size()); + } + + private void prepareForSts() throws NoSuchFieldException, IllegalAccessException { + StsConfig.getInstance().setSecurityCredentialsUrl("test"); + Field field = StsCredentialHolder.class.getDeclaredField("stsCredential"); + field.setAccessible(true); + field.set(StsCredentialHolder.getInstance(), stsCredential); + stsCredential.setAccessKeyId("test-sts-ak"); + stsCredential.setAccessKeySecret("test-sts-sk"); + stsCredential.setSecurityToken("test-sts-token"); + stsCredential.setExpiration(new Date(System.currentTimeMillis() + 1000000)); + } + + private void clearForSts() throws NoSuchFieldException, IllegalAccessException { + StsConfig.getInstance().setSecurityCredentialsUrl(null); + Field field = StsCredentialHolder.class.getDeclaredField("stsCredential"); + field.setAccessible(true); + field.set(StsCredentialHolder.getInstance(), null); + } } diff --git a/client/src/test/java/com/alibaba/nacos/client/env/NacosClientPropertiesTest.java b/client/src/test/java/com/alibaba/nacos/client/env/NacosClientPropertiesTest.java index 871d84d1b..8b6d3eff6 100644 --- a/client/src/test/java/com/alibaba/nacos/client/env/NacosClientPropertiesTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/env/NacosClientPropertiesTest.java @@ -320,7 +320,7 @@ public class NacosClientPropertiesTest { "/home/properties_args"); Assert.assertEquals( NacosClientProperties.PROTOTYPE.getPropertyFrom(null, "nacos.home.default.test"), - "/home/jvm_args"); + NacosClientProperties.PROTOTYPE.getProperty("nacos.home.default.test")); } }