This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.2
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.2 by this push:
new 1b838281a4 QoS Support anonymous command allow list (#12082)
1b838281a4 is described below
commit 1b838281a44cd5afec07ef3cd69eb42a36d935c2
Author: Albumen Kevin <[email protected]>
AuthorDate: Wed Apr 19 10:13:09 2023 +0800
QoS Support anonymous command allow list (#12082)
* QoS Support anonymous command allow list
* Fix test
---
.../dubbo/common/constants/QosConstants.java | 2 ++
.../org/apache/dubbo/config/ApplicationConfig.java | 15 ++++++++++++++
.../src/main/resources/META-INF/dubbo.xsd | 6 ++++++
.../org/apache/dubbo/qos/api/QosConfiguration.java | 18 ++++++++++++++++
.../DefaultAnonymousAccessPermissionChecker.java | 14 ++++++++++++-
.../dubbo/qos/protocol/QosProtocolWrapper.java | 3 +++
.../java/org/apache/dubbo/qos/server/Server.java | 7 +++++++
...efaultAnonymousAccessPermissionCheckerTest.java | 24 +++++++++++++++++++++-
8 files changed, 87 insertions(+), 2 deletions(-)
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java
index e02ec74a65..29b1993ca6 100644
---
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java
@@ -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";
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
index 63dcfb5375..7336c6d144 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
@@ -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().
*
diff --git
a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 8ba022c68f..141b5d5169 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -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">
diff --git
a/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java
b/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java
index 476079aa14..69f9b10e19 100644
---
a/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java
+++
b/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java
@@ -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;
+ }
}
}
diff --git
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java
index 8efd756e00..61736f2247 100644
---
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java
+++
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java
@@ -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
diff --git
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java
index ef2f35c3dd..127fa8bb42 100644
---
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java
+++
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java
@@ -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) {
diff --git
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java
index 4dc03d1cd7..65e7e3b9fa 100644
---
a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java
+++
b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java
@@ -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;
}
diff --git
a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java
b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java
index 11f466ca39..eef2013fde 100644
---
a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java
+++
b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java
@@ -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));
}
}