QoS Support anonymous command allow list (#12082)
* QoS Support anonymous command allow list * Fix test
This commit is contained in:
parent
9aa6a9e08c
commit
1b838281a4
|
|
@ -34,6 +34,8 @@ public interface QosConstants {
|
|||
|
||||
String ANONYMOUS_ACCESS_PERMISSION_LEVEL = "qos.anonymous.access.permission.level";
|
||||
|
||||
String ANONYMOUS_ACCESS_ALLOW_COMMANDS = "qos.anonymous.access.allow.commands";
|
||||
|
||||
String QOS_ENABLE_COMPATIBLE = "qos-enable";
|
||||
|
||||
String QOS_HOST_COMPATIBLE = "qos-host";
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
|
|||
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_COMPATIBLE;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST_COMPATIBLE;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_ALLOW_COMMANDS;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL_COMPATIBLE;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
|
||||
|
|
@ -170,6 +171,11 @@ public class ApplicationConfig extends AbstractConfig {
|
|||
*/
|
||||
private String qosAnonymousAccessPermissionLevel;
|
||||
|
||||
/**
|
||||
* the anonymous(any foreign ip) allow commands, default is empty, can not access any cmd
|
||||
*/
|
||||
private String qosAnonymousAllowCommands;
|
||||
|
||||
/**
|
||||
* Customized parameters
|
||||
*/
|
||||
|
|
@ -472,6 +478,15 @@ public class ApplicationConfig extends AbstractConfig {
|
|||
this.qosAnonymousAccessPermissionLevel = qosAnonymousAccessPermissionLevel;
|
||||
}
|
||||
|
||||
@Parameter(key = ANONYMOUS_ACCESS_ALLOW_COMMANDS)
|
||||
public String getQosAnonymousAllowCommands() {
|
||||
return qosAnonymousAllowCommands;
|
||||
}
|
||||
|
||||
public void setQosAnonymousAllowCommands(String qosAnonymousAllowCommands) {
|
||||
this.qosAnonymousAllowCommands = qosAnonymousAllowCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* The format is the same as the springboot, including: getQosEnableCompatible(), getQosPortCompatible(), getQosAcceptForeignIpCompatible().
|
||||
*
|
||||
|
|
|
|||
|
|
@ -547,6 +547,12 @@
|
|||
<![CDATA[ Anonymous (any foreign ip) access level, the default is NONE, can not access any cmd. ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="qos-anonymous-allow-commands" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[ Anonymous(any foreign ip) allow commands, default is empty, can not access any cmd. ]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="moduleType">
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ public class QosConfiguration {
|
|||
// the default value is Cmd.PermissionLevel.PUBLIC, can only access PUBLIC level cmd
|
||||
private PermissionLevel anonymousAccessPermissionLevel = PermissionLevel.PUBLIC;
|
||||
|
||||
// the allow commands for anonymous access, the delimiter is colon(,)
|
||||
private String anonymousAllowCommands;
|
||||
|
||||
private QosConfiguration() {
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +49,7 @@ public class QosConfiguration {
|
|||
this.acceptForeignIp = builder.isAcceptForeignIp();
|
||||
this.acceptForeignIpWhitelist = builder.getAcceptForeignIpWhitelist();
|
||||
this.anonymousAccessPermissionLevel = builder.getAnonymousAccessPermissionLevel();
|
||||
this.anonymousAllowCommands = builder.getAnonymousAllowCommands();
|
||||
buildPredicate();
|
||||
}
|
||||
|
||||
|
|
@ -93,6 +97,10 @@ public class QosConfiguration {
|
|||
return acceptForeignIp;
|
||||
}
|
||||
|
||||
public String getAnonymousAllowCommands() {
|
||||
return anonymousAllowCommands;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
|
@ -103,6 +111,7 @@ public class QosConfiguration {
|
|||
private boolean acceptForeignIp;
|
||||
private String acceptForeignIpWhitelist;
|
||||
private PermissionLevel anonymousAccessPermissionLevel = PermissionLevel.PUBLIC;
|
||||
private String anonymousAllowCommands;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
|
@ -127,6 +136,11 @@ public class QosConfiguration {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder anonymousAllowCommands(String anonymousAllowCommands) {
|
||||
this.anonymousAllowCommands = anonymousAllowCommands;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QosConfiguration build() {
|
||||
return new QosConfiguration(this);
|
||||
}
|
||||
|
|
@ -146,5 +160,9 @@ public class QosConfiguration {
|
|||
public PermissionLevel getAnonymousAccessPermissionLevel() {
|
||||
return anonymousAccessPermissionLevel;
|
||||
}
|
||||
|
||||
public String getAnonymousAllowCommands() {
|
||||
return anonymousAllowCommands;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,16 @@
|
|||
*/
|
||||
package org.apache.dubbo.qos.permission;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.qos.api.CommandContext;
|
||||
import org.apache.dubbo.qos.api.PermissionLevel;
|
||||
import org.apache.dubbo.qos.api.QosConfiguration;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
public class DefaultAnonymousAccessPermissionChecker implements PermissionChecker {
|
||||
|
|
@ -37,6 +40,15 @@ public class DefaultAnonymousAccessPermissionChecker implements PermissionChecke
|
|||
.orElse(null);
|
||||
|
||||
QosConfiguration qosConfiguration = commandContext.getQosConfiguration();
|
||||
String anonymousAllowCommands = qosConfiguration.getAnonymousAllowCommands();
|
||||
if (StringUtils.isNotEmpty(anonymousAllowCommands) &&
|
||||
Arrays.stream(anonymousAllowCommands.split(","))
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.map(String::trim)
|
||||
.anyMatch(cmd -> cmd.equals(commandContext.getCommandName()))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PermissionLevel currentLevel = qosConfiguration.getAnonymousAccessPermissionLevel();
|
||||
|
||||
// Local has private permission
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.QOS_FAILED_START_SERVER;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_ALLOW_COMMANDS;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
|
||||
import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST;
|
||||
|
|
@ -119,6 +120,7 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware {
|
|||
boolean acceptForeignIp = Boolean.parseBoolean(url.getParameter(ACCEPT_FOREIGN_IP, "false"));
|
||||
String acceptForeignIpWhitelist = url.getParameter(ACCEPT_FOREIGN_IP_WHITELIST, StringUtils.EMPTY_STRING);
|
||||
String anonymousAccessPermissionLevel = url.getParameter(ANONYMOUS_ACCESS_PERMISSION_LEVEL, PermissionLevel.PUBLIC.name());
|
||||
String anonymousAllowCommands = url.getParameter(ANONYMOUS_ACCESS_ALLOW_COMMANDS, StringUtils.EMPTY_STRING);
|
||||
Server server = frameworkModel.getBeanFactory().getBean(Server.class);
|
||||
|
||||
if (server.isStarted()) {
|
||||
|
|
@ -130,6 +132,7 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware {
|
|||
server.setAcceptForeignIp(acceptForeignIp);
|
||||
server.setAcceptForeignIpWhitelist(acceptForeignIpWhitelist);
|
||||
server.setAnonymousAccessPermissionLevel(anonymousAccessPermissionLevel);
|
||||
server.setAnonymousAllowCommands(anonymousAllowCommands);
|
||||
server.start();
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ public class Server {
|
|||
|
||||
private String anonymousAccessPermissionLevel = PermissionLevel.NONE.name();
|
||||
|
||||
private String anonymousAllowCommands = StringUtils.EMPTY_STRING;
|
||||
|
||||
private EventLoopGroup boss;
|
||||
|
||||
private EventLoopGroup worker;
|
||||
|
|
@ -108,6 +110,7 @@ public class Server {
|
|||
.acceptForeignIp(acceptForeignIp)
|
||||
.acceptForeignIpWhitelist(acceptForeignIpWhitelist)
|
||||
.anonymousAccessPermissionLevel(anonymousAccessPermissionLevel)
|
||||
.anonymousAllowCommands(anonymousAllowCommands)
|
||||
.build()
|
||||
));
|
||||
}
|
||||
|
|
@ -167,6 +170,10 @@ public class Server {
|
|||
this.anonymousAccessPermissionLevel = anonymousAccessPermissionLevel;
|
||||
}
|
||||
|
||||
public void setAnonymousAllowCommands(String anonymousAllowCommands) {
|
||||
this.anonymousAllowCommands = anonymousAllowCommands;
|
||||
}
|
||||
|
||||
public String getWelcome() {
|
||||
return welcome;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@
|
|||
*/
|
||||
package org.apache.dubbo.qos.permission;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.apache.dubbo.qos.api.CommandContext;
|
||||
import org.apache.dubbo.qos.api.PermissionLevel;
|
||||
import org.apache.dubbo.qos.api.QosConfiguration;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
|
@ -79,5 +80,26 @@ class DefaultAnonymousAccessPermissionCheckerTest {
|
|||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC));
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED));
|
||||
Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PRIVATE));
|
||||
|
||||
Mockito.when(qosConfiguration.getAcceptForeignIpWhitelistPredicate()).thenReturn(ip -> false);
|
||||
Mockito.when(qosConfiguration.getAnonymousAllowCommands()).thenReturn("test1,test2");
|
||||
|
||||
Mockito.when(commandContext.getCommandName()).thenReturn("test1");
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE));
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC));
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED));
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PRIVATE));
|
||||
|
||||
Mockito.when(commandContext.getCommandName()).thenReturn("test2");
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE));
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC));
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED));
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PRIVATE));
|
||||
|
||||
Mockito.when(commandContext.getCommandName()).thenReturn("test");
|
||||
Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE));
|
||||
Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PUBLIC));
|
||||
Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PROTECTED));
|
||||
Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PRIVATE));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue