mirror of https://github.com/alibaba/nacos.git
【Fix issue #13600】 auth error when non-admin users clone config (#13674)
* Fix #13600 auth error when non-admin users clone config * Fix #13600 auth error when non-admin users clone config * Fix #13600 auth error when non-admin users clone config * Fix #13600 auth error when non-admin users clone config
This commit is contained in:
parent
5536ceb683
commit
7f0e9310fb
|
@ -52,9 +52,11 @@ public class Constants {
|
|||
public static final String GROUP = "group";
|
||||
|
||||
public static final String GROUP_NAME = "groupName";
|
||||
|
||||
|
||||
public static final String NAMESPACE_ID = "namespaceId";
|
||||
|
||||
public static final String TARGET_NAMESPACE_ID = "targetNamespaceId";
|
||||
|
||||
public static final String LAST_MODIFIED = "Last-Modified";
|
||||
|
||||
public static final String ACCEPT_ENCODING = "Accept-Encoding";
|
||||
|
|
|
@ -32,7 +32,7 @@ public abstract class AbstractResourceParser<R> implements ResourceParser<R> {
|
|||
|
||||
@Override
|
||||
public Resource parse(R request, Secured secured) {
|
||||
String namespaceId = getNamespaceId(request);
|
||||
String namespaceId = getNamespaceId(request, secured);
|
||||
String group = getGroup(request);
|
||||
String name = getResourceName(request);
|
||||
Properties properties = getProperties(request);
|
||||
|
@ -50,6 +50,18 @@ public abstract class AbstractResourceParser<R> implements ResourceParser<R> {
|
|||
*/
|
||||
protected abstract String getNamespaceId(R request);
|
||||
|
||||
/**
|
||||
* Get namespaceId from request and secured. No implementation is required by default,this method can be rewrited
|
||||
* with special processing.
|
||||
*
|
||||
* @param request request
|
||||
* @param secured secured
|
||||
* @return namespaceId
|
||||
*/
|
||||
protected String getNamespaceId(R request, Secured secured) {
|
||||
return getNamespaceId(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get group name from request.
|
||||
*
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
package com.alibaba.nacos.auth.parser.http;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
|
@ -39,6 +41,14 @@ public class ConfigHttpResourceParser extends AbstractHttpResourceParser {
|
|||
return NamespaceUtil.processNamespaceParameter(namespaceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNamespaceId(HttpServletRequest request, Secured secured) {
|
||||
return Arrays.stream(secured.tags()).filter(tag -> tag.startsWith(Constants.NAMESPACE_ID))
|
||||
.map(tag -> tag.split(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.SPLITTER))
|
||||
.filter(splitTags -> splitTags.length >= 2).map(splitTags -> request.getParameter(splitTags[1]))
|
||||
.filter(StringUtils::isNotBlank).findFirst().orElseGet(() -> getNamespaceId(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getGroup(HttpServletRequest request) {
|
||||
String groupName = request.getParameter(Constants.GROUP_NAME);
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.lang.reflect.Method;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
// todo remove this
|
||||
|
@ -139,4 +140,65 @@ class ConfigHttpResourceParserTest {
|
|||
Method method = this.getClass().getDeclaredMethod(methodName);
|
||||
return method.getAnnotation(Secured.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(tags = {"namespaceId:customNsParam"})
|
||||
void testParseWithSecuredTags() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure();
|
||||
when(request.getParameter("customNsParam")).thenReturn("tagNs");
|
||||
|
||||
String actualNamespaceId = resourceParser.getNamespaceId(request, secured);
|
||||
assertEquals("tagNs", actualNamespaceId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(tags = {"namespaceId:emptyParam"})
|
||||
void testParseWithSecuredTagsButEmptyParam() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure();
|
||||
when(request.getParameter("emptyParam")).thenReturn(StringUtils.EMPTY);
|
||||
when(request.getParameter(Constants.NAMESPACE_ID)).thenReturn("defaultNs");
|
||||
|
||||
String actualNamespaceId = resourceParser.getNamespaceId(request, secured);
|
||||
assertEquals("defaultNs", actualNamespaceId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(tags = {"invalidTag:param", "namespaceId:multiTag"})
|
||||
void testParseWithMultipleTags() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure();
|
||||
when(request.getParameter("multiTag")).thenReturn("multiNs");
|
||||
|
||||
String actualNamespaceId = resourceParser.getNamespaceId(request, secured);
|
||||
assertEquals("multiNs", actualNamespaceId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(tags = {"namespaceId:splitTag:extra"})
|
||||
void testParseWithInvalidSplitTag() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure();
|
||||
when(request.getParameter("splitTag")).thenReturn("splitNs");
|
||||
|
||||
String actualNamespaceId = resourceParser.getNamespaceId(request, secured);
|
||||
assertEquals("splitNs", actualNamespaceId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(tags = {"normalTag"})
|
||||
void testParseWithNoNamespaceTag() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure();
|
||||
when(request.getParameter(Constants.NAMESPACE_ID)).thenReturn("defaultNs");
|
||||
|
||||
String actualNamespaceId = resourceParser.getNamespaceId(request, secured);
|
||||
assertEquals("defaultNs", actualNamespaceId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Secured(tags = {"namespaceId"})
|
||||
void testParseWithInvalidSplitTag1() throws NoSuchMethodException {
|
||||
Secured secured = getMethodSecure();
|
||||
when(request.getParameter(Constants.NAMESPACE_ID)).thenReturn("defaultNs");
|
||||
|
||||
String actualNamespaceId = resourceParser.getNamespaceId(request, secured);
|
||||
assertEquals("defaultNs", actualNamespaceId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -593,7 +593,7 @@ public class ConfigControllerV3 {
|
|||
* Execute clone config operation.
|
||||
*/
|
||||
@PostMapping("/clone")
|
||||
@Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)
|
||||
@Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)
|
||||
public Result<Map<String, Object>> cloneConfig(HttpServletRequest request,
|
||||
@RequestParam(value = "src_user", required = false) String srcUser,
|
||||
@RequestParam(value = "namespaceId") String namespaceId, @RequestBody List<ConfigCloneInfo> cloneInfos,
|
||||
|
|
|
@ -357,7 +357,8 @@ public class ConsoleConfigController {
|
|||
* @throws NacosException If a Nacos-specific error occurs.
|
||||
*/
|
||||
@PostMapping("/clone")
|
||||
@Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)
|
||||
@Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API, tags = {
|
||||
com.alibaba.nacos.plugin.auth.constant.Constants.Tag.SECURED_SPECIAL_TAGS})
|
||||
public Result<Map<String, Object>> cloneConfig(HttpServletRequest request,
|
||||
@RequestParam(required = false) String srcUser,
|
||||
@RequestParam(value = "targetNamespaceId") String namespaceId,
|
||||
|
|
|
@ -66,5 +66,9 @@ public class Constants {
|
|||
public static class Tag {
|
||||
|
||||
public static final String ONLY_IDENTITY = "only_identity";
|
||||
|
||||
public static final String SECURED_SPECIAL_TAGS =
|
||||
com.alibaba.nacos.api.common.Constants.NAMESPACE_ID + Resource.SPLITTER
|
||||
+ com.alibaba.nacos.api.common.Constants.TARGET_NAMESPACE_ID;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue