mirror of
https://github.com/apache/rocketmq.git
synced 2026-08-29 04:13:00 +08:00
[ISSUE 9362] [RIP-77] Deprecate and Remove ACL 1.0 (#9363)
This commit is contained in:
committed by
RongtongJin
parent
50160bfdea
commit
f75dc5a4d2
@@ -1,75 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
load("//bazel:GenTestRules.bzl", "GenTestRules")
|
||||
|
||||
java_library(
|
||||
name = "acl",
|
||||
srcs = glob(["src/main/java/**/*.java"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//common",
|
||||
"//remoting",
|
||||
"//srvutil",
|
||||
"@maven//:com_alibaba_fastjson2_fastjson2",
|
||||
"@maven//:com_github_luben_zstd_jni",
|
||||
"@maven//:com_google_guava_guava",
|
||||
"@maven//:com_google_protobuf_protobuf_java",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:commons_validator_commons_validator",
|
||||
"@maven//:io_netty_netty_all",
|
||||
"@maven//:org_apache_commons_commons_lang3",
|
||||
"@maven//:org_apache_rocketmq_rocketmq_proto",
|
||||
"@maven//:org_lz4_lz4_java",
|
||||
"@maven//:org_yaml_snakeyaml",
|
||||
"@maven//:io_github_aliyunmq_rocketmq_slf4j_api",
|
||||
"@maven//:io_github_aliyunmq_rocketmq_logback_classic",
|
||||
],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = "tests",
|
||||
srcs = glob(["src/test/java/**/*.java"]),
|
||||
resources = glob(["src/test/resources/**/*.yml"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":acl",
|
||||
"//:test_deps",
|
||||
"//common",
|
||||
"//remoting",
|
||||
"@maven//:com_alibaba_fastjson2_fastjson2",
|
||||
"@maven//:com_google_guava_guava",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:io_netty_netty_all",
|
||||
"@maven//:org_apache_commons_commons_lang3",
|
||||
"@maven//:org_springframework_spring_core",
|
||||
"@maven//:org_yaml_snakeyaml",
|
||||
],
|
||||
)
|
||||
|
||||
GenTestRules(
|
||||
name = "GeneratedTestRules",
|
||||
# The following tests are not hermetic. Fix them later.
|
||||
exclude_tests = [
|
||||
],
|
||||
medium_tests = [
|
||||
"src/test/java/org/apache/rocketmq/acl/plain/PlainAccessValidatorTest",
|
||||
],
|
||||
test_files = glob(["src/test/java/**/*Test.java"]),
|
||||
deps = [
|
||||
":tests",
|
||||
],
|
||||
)
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
<!-- 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. -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-all</artifactId>
|
||||
<version>5.3.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>rocketmq-acl</artifactId>
|
||||
<name>rocketmq-acl ${project.version}</name>
|
||||
|
||||
<properties>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-proto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-remoting</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-srvutil</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.aliyunmq</groupId>
|
||||
<artifactId>rocketmq-slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.aliyunmq</groupId>
|
||||
<artifactId>rocketmq-logback-classic</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-validator</groupId>
|
||||
<artifactId>commons-validator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<forkCount>1</forkCount>
|
||||
<reuseForks>false</reuseForks>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl;
|
||||
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.rocketmq.acl.common.AuthenticationHeader;
|
||||
import org.apache.rocketmq.common.AclConfig;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.remoting.protocol.DataVersion;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
|
||||
public interface AccessValidator {
|
||||
|
||||
/**
|
||||
* Parse to get the AccessResource(user, resource, needed permission)
|
||||
*
|
||||
* @param request
|
||||
* @param remoteAddr
|
||||
* @return Plain access resource result,include access key,signature and some other access attributes.
|
||||
*/
|
||||
AccessResource parse(RemotingCommand request, String remoteAddr);
|
||||
|
||||
/**
|
||||
* Parse to get the AccessResource from gRPC protocol
|
||||
* @param messageV3
|
||||
* @param header
|
||||
* @return Plain access resource
|
||||
*/
|
||||
AccessResource parse(GeneratedMessageV3 messageV3, AuthenticationHeader header);
|
||||
|
||||
/**
|
||||
* Validate the access resource.
|
||||
*
|
||||
* @param accessResource
|
||||
*/
|
||||
void validate(AccessResource accessResource);
|
||||
|
||||
/**
|
||||
* Update the access resource config
|
||||
*
|
||||
* @param plainAccessConfig
|
||||
* @return
|
||||
*/
|
||||
boolean updateAccessConfig(PlainAccessConfig plainAccessConfig);
|
||||
|
||||
/**
|
||||
* Delete the access resource config
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean deleteAccessConfig(String accessKey);
|
||||
|
||||
/**
|
||||
* Get the access resource config version information
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
String getAclConfigVersion();
|
||||
|
||||
/**
|
||||
* Update globalWhiteRemoteAddresses in acl yaml config file
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList);
|
||||
|
||||
boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList, String aclFileFullPath);
|
||||
|
||||
/**
|
||||
* get broker cluster acl config information
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
AclConfig getAllAclConfig();
|
||||
|
||||
/**
|
||||
* get all access resource config version information
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Map<String, DataVersion> getAllAclConfigVersion();
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl;
|
||||
|
||||
public interface PermissionChecker {
|
||||
void check(AccessResource checkedAccess, AccessResource ownedAccess);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
public class AclConstants {
|
||||
|
||||
public static final String CONFIG_GLOBAL_WHITE_ADDRS = "globalWhiteRemoteAddresses";
|
||||
|
||||
public static final String CONFIG_ACCOUNTS = "accounts";
|
||||
|
||||
public static final String CONFIG_ACCESS_KEY = "accessKey";
|
||||
|
||||
public static final String CONFIG_SECRET_KEY = "secretKey";
|
||||
|
||||
public static final String CONFIG_WHITE_ADDR = "whiteRemoteAddress";
|
||||
|
||||
public static final String CONFIG_ADMIN_ROLE = "admin";
|
||||
|
||||
public static final String CONFIG_DEFAULT_TOPIC_PERM = "defaultTopicPerm";
|
||||
|
||||
public static final String CONFIG_DEFAULT_GROUP_PERM = "defaultGroupPerm";
|
||||
|
||||
public static final String CONFIG_TOPIC_PERMS = "topicPerms";
|
||||
|
||||
public static final String CONFIG_GROUP_PERMS = "groupPerms";
|
||||
|
||||
public static final String CONFIG_DATA_VERSION = "dataVersion";
|
||||
|
||||
public static final String CONFIG_COUNTER = "counter";
|
||||
|
||||
public static final String CONFIG_TIME_STAMP = "timestamp";
|
||||
|
||||
public static final String PUB = "PUB";
|
||||
|
||||
public static final String SUB = "SUB";
|
||||
|
||||
public static final String DENY = "DENY";
|
||||
|
||||
public static final String PUB_SUB = "PUB|SUB";
|
||||
|
||||
public static final String SUB_PUB = "SUB|PUB";
|
||||
|
||||
public static final int ACCESS_KEY_MIN_LENGTH = 6;
|
||||
|
||||
public static final int SECRET_KEY_MIN_LENGTH = 6;
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
public class AuthenticationHeader {
|
||||
private String remoteAddress;
|
||||
private String tenantId;
|
||||
private String namespace;
|
||||
private String authorization;
|
||||
private String datetime;
|
||||
private String sessionToken;
|
||||
private String requestId;
|
||||
private String language;
|
||||
private String clientVersion;
|
||||
private String protocol;
|
||||
private int requestCode;
|
||||
|
||||
AuthenticationHeader(final String remoteAddress, final String tenantId, final String namespace,
|
||||
final String authorization, final String datetime, final String sessionToken, final String requestId,
|
||||
final String language, final String clientVersion, final String protocol, final int requestCode) {
|
||||
this.remoteAddress = remoteAddress;
|
||||
this.tenantId = tenantId;
|
||||
this.namespace = namespace;
|
||||
this.authorization = authorization;
|
||||
this.datetime = datetime;
|
||||
this.sessionToken = sessionToken;
|
||||
this.requestId = requestId;
|
||||
this.language = language;
|
||||
this.clientVersion = clientVersion;
|
||||
this.protocol = protocol;
|
||||
this.requestCode = requestCode;
|
||||
}
|
||||
|
||||
public static class MetadataHeaderBuilder {
|
||||
private String remoteAddress;
|
||||
private String tenantId;
|
||||
private String namespace;
|
||||
private String authorization;
|
||||
private String datetime;
|
||||
private String sessionToken;
|
||||
private String requestId;
|
||||
private String language;
|
||||
private String clientVersion;
|
||||
private String protocol;
|
||||
private int requestCode;
|
||||
|
||||
MetadataHeaderBuilder() {
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder remoteAddress(final String remoteAddress) {
|
||||
this.remoteAddress = remoteAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder tenantId(final String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder namespace(final String namespace) {
|
||||
this.namespace = namespace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder authorization(final String authorization) {
|
||||
this.authorization = authorization;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder datetime(final String datetime) {
|
||||
this.datetime = datetime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder sessionToken(final String sessionToken) {
|
||||
this.sessionToken = sessionToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder requestId(final String requestId) {
|
||||
this.requestId = requestId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder language(final String language) {
|
||||
this.language = language;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder clientVersion(final String clientVersion) {
|
||||
this.clientVersion = clientVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder protocol(final String protocol) {
|
||||
this.protocol = protocol;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader.MetadataHeaderBuilder requestCode(final int requestCode) {
|
||||
this.requestCode = requestCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AuthenticationHeader build() {
|
||||
return new AuthenticationHeader(this.remoteAddress, this.tenantId, this.namespace, this.authorization,
|
||||
this.datetime, this.sessionToken, this.requestId, this.language, this.clientVersion, this.protocol,
|
||||
this.requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static AuthenticationHeader.MetadataHeaderBuilder builder() {
|
||||
return new AuthenticationHeader.MetadataHeaderBuilder();
|
||||
}
|
||||
|
||||
public String getRemoteAddress() {
|
||||
return this.remoteAddress;
|
||||
}
|
||||
|
||||
public String getTenantId() {
|
||||
return this.tenantId;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return this.namespace;
|
||||
}
|
||||
|
||||
public String getAuthorization() {
|
||||
return this.authorization;
|
||||
}
|
||||
|
||||
public String getDatetime() {
|
||||
return this.datetime;
|
||||
}
|
||||
|
||||
public String getSessionToken() {
|
||||
return this.sessionToken;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
return this.requestId;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return this.language;
|
||||
}
|
||||
|
||||
public String getClientVersion() {
|
||||
return this.clientVersion;
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return this.protocol;
|
||||
}
|
||||
|
||||
public int getRequestCode() {
|
||||
return this.requestCode;
|
||||
}
|
||||
|
||||
public void setRemoteAddress(final String remoteAddress) {
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
public void setTenantId(final String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
public void setNamespace(final String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public void setAuthorization(final String authorization) {
|
||||
this.authorization = authorization;
|
||||
}
|
||||
|
||||
public void setDatetime(final String datetime) {
|
||||
this.datetime = datetime;
|
||||
}
|
||||
|
||||
public void setSessionToken(final String sessionToken) {
|
||||
this.sessionToken = sessionToken;
|
||||
}
|
||||
|
||||
public void setRequestId(final String requestId) {
|
||||
this.requestId = requestId;
|
||||
}
|
||||
|
||||
public void setLanguage(final String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public void setClientVersion(final String clientVersion) {
|
||||
this.clientVersion = clientVersion;
|
||||
}
|
||||
|
||||
public void setProtocol(final String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public void setRequestCode(int requestCode) {
|
||||
this.requestCode = requestCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("remoteAddress", remoteAddress)
|
||||
.add("tenantId", tenantId)
|
||||
.add("namespace", namespace)
|
||||
.add("authorization", authorization)
|
||||
.add("datetime", datetime)
|
||||
.add("sessionToken", sessionToken)
|
||||
.add("requestId", requestId)
|
||||
.add("language", language)
|
||||
.add("clientVersion", clientVersion)
|
||||
.add("protocol", protocol)
|
||||
.add("requestCode", requestCode)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
public class AuthorizationHeader {
|
||||
private static final String HEADER_SEPARATOR = " ";
|
||||
private static final String CREDENTIALS_SEPARATOR = "/";
|
||||
private static final int AUTH_HEADER_KV_LENGTH = 2;
|
||||
private static final String CREDENTIAL = "Credential";
|
||||
private static final String SIGNED_HEADERS = "SignedHeaders";
|
||||
private static final String SIGNATURE = "Signature";
|
||||
private String method;
|
||||
private String accessKey;
|
||||
private String[] signedHeaders;
|
||||
private String signature;
|
||||
|
||||
/**
|
||||
* Parse authorization from gRPC header.
|
||||
*
|
||||
* @param header gRPC header string.
|
||||
* @throws Exception exception.
|
||||
*/
|
||||
public AuthorizationHeader(String header) throws DecoderException {
|
||||
String[] result = header.split(HEADER_SEPARATOR, 2);
|
||||
if (result.length != 2) {
|
||||
throw new DecoderException("authorization header is incorrect");
|
||||
}
|
||||
this.method = result[0];
|
||||
String[] keyValues = result[1].split(",");
|
||||
for (String keyValue : keyValues) {
|
||||
String[] kv = keyValue.trim().split("=", 2);
|
||||
int kvLength = kv.length;
|
||||
if (kv.length != AUTH_HEADER_KV_LENGTH) {
|
||||
throw new DecoderException("authorization keyValues length is incorrect, actual length=" + kvLength);
|
||||
}
|
||||
String authItem = kv[0];
|
||||
if (CREDENTIAL.equals(authItem)) {
|
||||
String[] credential = kv[1].split(CREDENTIALS_SEPARATOR);
|
||||
int credentialActualLength = credential.length;
|
||||
if (credentialActualLength == 0) {
|
||||
throw new DecoderException("authorization credential length is incorrect, actual length=" + credentialActualLength);
|
||||
}
|
||||
this.accessKey = credential[0];
|
||||
continue;
|
||||
}
|
||||
if (SIGNED_HEADERS.equals(authItem)) {
|
||||
this.signedHeaders = kv[1].split(";");
|
||||
continue;
|
||||
}
|
||||
if (SIGNATURE.equals(authItem)) {
|
||||
this.signature = this.hexToBase64(kv[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String hexToBase64(String input) throws DecoderException {
|
||||
byte[] bytes = Hex.decodeHex(input);
|
||||
return Base64.encodeBase64String(bytes);
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
public String getAccessKey() {
|
||||
return this.accessKey;
|
||||
}
|
||||
|
||||
public String[] getSignedHeaders() {
|
||||
return this.signedHeaders;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return this.signature;
|
||||
}
|
||||
|
||||
public void setMethod(final String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public void setAccessKey(final String accessKey) {
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
public void setSignedHeaders(final String[] signedHeaders) {
|
||||
this.signedHeaders = signedHeaders;
|
||||
}
|
||||
|
||||
public void setSignature(final String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("method", method)
|
||||
.add("accessKey", accessKey)
|
||||
.add("signedHeaders", signedHeaders)
|
||||
.add("signature", signature)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessResource;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
|
||||
public class Permission {
|
||||
|
||||
public static final byte DENY = 1;
|
||||
public static final byte ANY = 1 << 1;
|
||||
public static final byte PUB = 1 << 2;
|
||||
public static final byte SUB = 1 << 3;
|
||||
|
||||
public static final Set<Integer> ADMIN_CODE = new HashSet<>();
|
||||
|
||||
static {
|
||||
// UPDATE_AND_CREATE_TOPIC
|
||||
ADMIN_CODE.add(RequestCode.UPDATE_AND_CREATE_TOPIC);
|
||||
// UPDATE_BROKER_CONFIG
|
||||
ADMIN_CODE.add(RequestCode.UPDATE_BROKER_CONFIG);
|
||||
// DELETE_TOPIC_IN_BROKER
|
||||
ADMIN_CODE.add(RequestCode.DELETE_TOPIC_IN_BROKER);
|
||||
// UPDATE_AND_CREATE_SUBSCRIPTIONGROUP
|
||||
ADMIN_CODE.add(RequestCode.UPDATE_AND_CREATE_SUBSCRIPTIONGROUP);
|
||||
// DELETE_SUBSCRIPTIONGROUP
|
||||
ADMIN_CODE.add(RequestCode.DELETE_SUBSCRIPTIONGROUP);
|
||||
// UPDATE_AND_CREATE_STATIC_TOPIC
|
||||
ADMIN_CODE.add(RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC);
|
||||
// UPDATE_AND_CREATE_ACL_CONFIG
|
||||
ADMIN_CODE.add(RequestCode.UPDATE_AND_CREATE_ACL_CONFIG);
|
||||
// DELETE_ACL_CONFIG
|
||||
ADMIN_CODE.add(RequestCode.DELETE_ACL_CONFIG);
|
||||
// GET_BROKER_CLUSTER_ACL_INFO
|
||||
ADMIN_CODE.add(RequestCode.GET_BROKER_CLUSTER_ACL_INFO);
|
||||
}
|
||||
|
||||
public static boolean checkPermission(byte neededPerm, byte ownedPerm) {
|
||||
if ((ownedPerm & DENY) > 0) {
|
||||
return false;
|
||||
}
|
||||
if ((neededPerm & ANY) > 0) {
|
||||
return (ownedPerm & PUB) > 0 || (ownedPerm & SUB) > 0;
|
||||
}
|
||||
return (neededPerm & ownedPerm) > 0;
|
||||
}
|
||||
|
||||
public static byte parsePermFromString(String permString) {
|
||||
if (permString == null) {
|
||||
return Permission.DENY;
|
||||
}
|
||||
switch (permString.trim()) {
|
||||
case AclConstants.PUB:
|
||||
return Permission.PUB;
|
||||
case AclConstants.SUB:
|
||||
return Permission.SUB;
|
||||
case AclConstants.PUB_SUB:
|
||||
case AclConstants.SUB_PUB:
|
||||
return Permission.PUB | Permission.SUB;
|
||||
case AclConstants.DENY:
|
||||
return Permission.DENY;
|
||||
default:
|
||||
return Permission.DENY;
|
||||
}
|
||||
}
|
||||
|
||||
public static void parseResourcePerms(PlainAccessResource plainAccessResource, Boolean isTopic,
|
||||
List<String> resources) {
|
||||
if (resources == null || resources.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (String resource : resources) {
|
||||
String[] items = StringUtils.split(resource, "=");
|
||||
if (items.length == 2) {
|
||||
plainAccessResource.addResourceAndPerm(isTopic ? items[0].trim() : PlainAccessResource.getRetryTopic(items[0].trim()), parsePermFromString(items[1].trim()));
|
||||
} else {
|
||||
throw new AclException(String.format("Parse resource permission failed for %s:%s", isTopic ? "topic" : "group", resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkResourcePerms(List<String> resources) {
|
||||
if (resources == null || resources.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String resource : resources) {
|
||||
String[] items = StringUtils.split(resource, "=");
|
||||
if (items.length != 2) {
|
||||
throw new AclException(String.format("Parse Resource format error for %s.\n" +
|
||||
"The expected resource format is 'Res=Perm'. For example: topicA=SUB", resource));
|
||||
}
|
||||
|
||||
if (!AclConstants.DENY.equals(items[1].trim()) && Permission.DENY == Permission.parsePermFromString(items[1].trim())) {
|
||||
throw new AclException(String.format("Parse resource permission error for %s.\n" +
|
||||
"The expected permissions are 'SUB' or 'PUB' or 'SUB|PUB' or 'PUB|SUB'.", resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean needAdminPerm(Integer code) {
|
||||
return ADMIN_CODE.contains(code);
|
||||
}
|
||||
}
|
||||
@@ -1,471 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import apache.rocketmq.v2.AckMessageRequest;
|
||||
import apache.rocketmq.v2.ChangeInvisibleDurationRequest;
|
||||
import apache.rocketmq.v2.ClientType;
|
||||
import apache.rocketmq.v2.EndTransactionRequest;
|
||||
import apache.rocketmq.v2.ForwardMessageToDeadLetterQueueRequest;
|
||||
import apache.rocketmq.v2.HeartbeatRequest;
|
||||
import apache.rocketmq.v2.Message;
|
||||
import apache.rocketmq.v2.NotifyClientTerminationRequest;
|
||||
import apache.rocketmq.v2.QueryAssignmentRequest;
|
||||
import apache.rocketmq.v2.QueryRouteRequest;
|
||||
import apache.rocketmq.v2.RecallMessageRequest;
|
||||
import apache.rocketmq.v2.ReceiveMessageRequest;
|
||||
import apache.rocketmq.v2.Resource;
|
||||
import apache.rocketmq.v2.SendMessageRequest;
|
||||
import apache.rocketmq.v2.Subscription;
|
||||
import apache.rocketmq.v2.SubscriptionEntry;
|
||||
import apache.rocketmq.v2.TelemetryCommand;
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.rocketmq.acl.AccessResource;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.AclUtils;
|
||||
import org.apache.rocketmq.acl.common.AuthenticationHeader;
|
||||
import org.apache.rocketmq.acl.common.AuthorizationHeader;
|
||||
import org.apache.rocketmq.acl.common.Permission;
|
||||
import org.apache.rocketmq.acl.common.SessionCredentials;
|
||||
import org.apache.rocketmq.common.KeyBuilder;
|
||||
import org.apache.rocketmq.common.MQVersion;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.remoting.common.RemotingHelper;
|
||||
import org.apache.rocketmq.remoting.protocol.NamespaceUtil;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
import org.apache.rocketmq.remoting.protocol.ResponseCode;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumerListByGroupRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UnregisterClientRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateConsumerOffsetRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.heartbeat.ConsumerData;
|
||||
import org.apache.rocketmq.remoting.protocol.heartbeat.HeartbeatData;
|
||||
import org.apache.rocketmq.remoting.protocol.heartbeat.SubscriptionData;
|
||||
|
||||
public class PlainAccessResource implements AccessResource {
|
||||
|
||||
// Identify the user
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private String whiteRemoteAddress;
|
||||
|
||||
private boolean admin;
|
||||
|
||||
private byte defaultTopicPerm = 1;
|
||||
|
||||
private byte defaultGroupPerm = 1;
|
||||
|
||||
private Map<String, Byte> resourcePermMap;
|
||||
|
||||
private RemoteAddressStrategy remoteAddressStrategy;
|
||||
|
||||
private int requestCode;
|
||||
|
||||
// The content to calculate the content
|
||||
private byte[] content;
|
||||
|
||||
private String signature;
|
||||
|
||||
private String secretToken;
|
||||
|
||||
private String recognition;
|
||||
|
||||
public PlainAccessResource() {
|
||||
}
|
||||
|
||||
public static PlainAccessResource parse(RemotingCommand request, String remoteAddr) {
|
||||
PlainAccessResource accessResource = new PlainAccessResource();
|
||||
if (remoteAddr != null && remoteAddr.contains(":")) {
|
||||
accessResource.setWhiteRemoteAddress(remoteAddr.substring(0, remoteAddr.lastIndexOf(':')));
|
||||
} else {
|
||||
accessResource.setWhiteRemoteAddress(remoteAddr);
|
||||
}
|
||||
|
||||
accessResource.setRequestCode(request.getCode());
|
||||
|
||||
if (request.getExtFields() == null) {
|
||||
// If request's extFields is null,then return accessResource directly(users can use whiteAddress pattern)
|
||||
// The following logic codes depend on the request's extFields not to be null.
|
||||
return accessResource;
|
||||
}
|
||||
accessResource.setAccessKey(request.getExtFields().get(SessionCredentials.ACCESS_KEY));
|
||||
accessResource.setSignature(request.getExtFields().get(SessionCredentials.SIGNATURE));
|
||||
accessResource.setSecretToken(request.getExtFields().get(SessionCredentials.SECURITY_TOKEN));
|
||||
|
||||
try {
|
||||
switch (request.getCode()) {
|
||||
case RequestCode.SEND_MESSAGE:
|
||||
final String topic = request.getExtFields().get("topic");
|
||||
accessResource.addResourceAndPerm(topic, PlainAccessResource.isRetryTopic(topic) ? Permission.SUB : Permission.PUB);
|
||||
break;
|
||||
case RequestCode.SEND_MESSAGE_V2:
|
||||
case RequestCode.SEND_BATCH_MESSAGE:
|
||||
final String topicV2 = request.getExtFields().get("b");
|
||||
accessResource.addResourceAndPerm(topicV2, PlainAccessResource.isRetryTopic(topicV2) ? Permission.SUB : Permission.PUB);
|
||||
break;
|
||||
case RequestCode.RECALL_MESSAGE:
|
||||
accessResource.addResourceAndPerm(request.getExtFields().get("topic"), Permission.PUB);
|
||||
break;
|
||||
case RequestCode.CONSUMER_SEND_MSG_BACK:
|
||||
accessResource.addResourceAndPerm(getRetryTopic(request.getExtFields().get("group")), Permission.SUB);
|
||||
break;
|
||||
case RequestCode.PULL_MESSAGE:
|
||||
accessResource.addResourceAndPerm(request.getExtFields().get("topic"), Permission.SUB);
|
||||
accessResource.addResourceAndPerm(getRetryTopic(request.getExtFields().get("consumerGroup")), Permission.SUB);
|
||||
break;
|
||||
case RequestCode.QUERY_MESSAGE:
|
||||
accessResource.addResourceAndPerm(request.getExtFields().get("topic"), Permission.SUB);
|
||||
break;
|
||||
case RequestCode.HEART_BEAT:
|
||||
HeartbeatData heartbeatData = HeartbeatData.decode(request.getBody(), HeartbeatData.class);
|
||||
for (ConsumerData data : heartbeatData.getConsumerDataSet()) {
|
||||
accessResource.addResourceAndPerm(getRetryTopic(data.getGroupName()), Permission.SUB);
|
||||
for (SubscriptionData subscriptionData : data.getSubscriptionDataSet()) {
|
||||
accessResource.addResourceAndPerm(subscriptionData.getTopic(), Permission.SUB);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RequestCode.UNREGISTER_CLIENT:
|
||||
final UnregisterClientRequestHeader unregisterClientRequestHeader =
|
||||
(UnregisterClientRequestHeader) request
|
||||
.decodeCommandCustomHeader(UnregisterClientRequestHeader.class);
|
||||
accessResource.addResourceAndPerm(getRetryTopic(unregisterClientRequestHeader.getConsumerGroup()), Permission.SUB);
|
||||
break;
|
||||
case RequestCode.GET_CONSUMER_LIST_BY_GROUP:
|
||||
final GetConsumerListByGroupRequestHeader getConsumerListByGroupRequestHeader =
|
||||
(GetConsumerListByGroupRequestHeader) request
|
||||
.decodeCommandCustomHeader(GetConsumerListByGroupRequestHeader.class);
|
||||
accessResource.addResourceAndPerm(getRetryTopic(getConsumerListByGroupRequestHeader.getConsumerGroup()), Permission.SUB);
|
||||
break;
|
||||
case RequestCode.UPDATE_CONSUMER_OFFSET:
|
||||
final UpdateConsumerOffsetRequestHeader updateConsumerOffsetRequestHeader =
|
||||
(UpdateConsumerOffsetRequestHeader) request
|
||||
.decodeCommandCustomHeader(UpdateConsumerOffsetRequestHeader.class);
|
||||
accessResource.addResourceAndPerm(getRetryTopic(updateConsumerOffsetRequestHeader.getConsumerGroup()), Permission.SUB);
|
||||
accessResource.addResourceAndPerm(updateConsumerOffsetRequestHeader.getTopic(), Permission.SUB);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new AclException(t.getMessage(), t);
|
||||
}
|
||||
|
||||
// Content
|
||||
SortedMap<String, String> map = new TreeMap<>();
|
||||
for (Map.Entry<String, String> entry : request.getExtFields().entrySet()) {
|
||||
if (request.getVersion() <= MQVersion.Version.V4_9_3.ordinal() &&
|
||||
MixAll.UNIQUE_MSG_QUERY_FLAG.equals(entry.getKey())) {
|
||||
continue;
|
||||
}
|
||||
if (!SessionCredentials.SIGNATURE.equals(entry.getKey())) {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
accessResource.setContent(AclUtils.combineRequestContent(request, map));
|
||||
return accessResource;
|
||||
}
|
||||
|
||||
public static PlainAccessResource parse(GeneratedMessageV3 messageV3, AuthenticationHeader header) {
|
||||
PlainAccessResource accessResource = new PlainAccessResource();
|
||||
String remoteAddress = header.getRemoteAddress();
|
||||
if (remoteAddress != null && remoteAddress.contains(":")) {
|
||||
accessResource.setWhiteRemoteAddress(RemotingHelper.parseHostFromAddress(remoteAddress));
|
||||
} else {
|
||||
accessResource.setWhiteRemoteAddress(remoteAddress);
|
||||
}
|
||||
try {
|
||||
AuthorizationHeader authorizationHeader = new AuthorizationHeader(header.getAuthorization());
|
||||
accessResource.setAccessKey(authorizationHeader.getAccessKey());
|
||||
accessResource.setSignature(authorizationHeader.getSignature());
|
||||
} catch (DecoderException e) {
|
||||
throw new AclException(e.getMessage(), e);
|
||||
}
|
||||
accessResource.setSecretToken(header.getSessionToken());
|
||||
accessResource.setRequestCode(header.getRequestCode());
|
||||
accessResource.setContent(header.getDatetime().getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
try {
|
||||
String rpcFullName = messageV3.getDescriptorForType().getFullName();
|
||||
if (HeartbeatRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
HeartbeatRequest request = (HeartbeatRequest) messageV3;
|
||||
if (ClientType.PUSH_CONSUMER.equals(request.getClientType())
|
||||
|| ClientType.SIMPLE_CONSUMER.equals(request.getClientType())) {
|
||||
if (!request.hasGroup()) {
|
||||
throw new AclException("Consumer heartbeat doesn't have group");
|
||||
} else {
|
||||
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);
|
||||
}
|
||||
}
|
||||
} else if (SendMessageRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
SendMessageRequest request = (SendMessageRequest) messageV3;
|
||||
if (request.getMessagesCount() <= 0) {
|
||||
throw new AclException("SendMessageRequest, messageCount is zero", ResponseCode.MESSAGE_ILLEGAL);
|
||||
}
|
||||
Resource topic = request.getMessages(0).getTopic();
|
||||
for (Message message : request.getMessagesList()) {
|
||||
if (!message.getTopic().equals(topic)) {
|
||||
throw new AclException("SendMessageRequest, messages' topic is not consistent", ResponseCode.MESSAGE_ILLEGAL);
|
||||
}
|
||||
}
|
||||
accessResource.addResourceAndPerm(topic, Permission.PUB);
|
||||
} else if (RecallMessageRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
RecallMessageRequest request = (RecallMessageRequest) messageV3;
|
||||
accessResource.addResourceAndPerm(request.getTopic(), Permission.PUB);
|
||||
} else if (ReceiveMessageRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
ReceiveMessageRequest request = (ReceiveMessageRequest) messageV3;
|
||||
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);
|
||||
accessResource.addResourceAndPerm(request.getMessageQueue().getTopic(), Permission.SUB);
|
||||
} else if (AckMessageRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
AckMessageRequest request = (AckMessageRequest) messageV3;
|
||||
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);
|
||||
accessResource.addResourceAndPerm(request.getTopic(), Permission.SUB);
|
||||
} else if (ForwardMessageToDeadLetterQueueRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
ForwardMessageToDeadLetterQueueRequest request = (ForwardMessageToDeadLetterQueueRequest) messageV3;
|
||||
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);
|
||||
accessResource.addResourceAndPerm(request.getTopic(), Permission.SUB);
|
||||
} else if (EndTransactionRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
EndTransactionRequest request = (EndTransactionRequest) messageV3;
|
||||
accessResource.addResourceAndPerm(request.getTopic(), Permission.PUB);
|
||||
} else if (TelemetryCommand.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
TelemetryCommand command = (TelemetryCommand) messageV3;
|
||||
if (command.getCommandCase() == TelemetryCommand.CommandCase.SETTINGS) {
|
||||
if (command.getSettings().hasPublishing()) {
|
||||
List<Resource> topicList = command.getSettings().getPublishing().getTopicsList();
|
||||
for (Resource topic : topicList) {
|
||||
accessResource.addResourceAndPerm(topic, Permission.PUB);
|
||||
}
|
||||
}
|
||||
if (command.getSettings().hasSubscription()) {
|
||||
Subscription subscription = command.getSettings().getSubscription();
|
||||
accessResource.addGroupResourceAndPerm(subscription.getGroup(), Permission.SUB);
|
||||
for (SubscriptionEntry entry : subscription.getSubscriptionsList()) {
|
||||
accessResource.addResourceAndPerm(entry.getTopic(), Permission.SUB);
|
||||
}
|
||||
}
|
||||
if (!command.getSettings().hasPublishing() && !command.getSettings().hasSubscription()) {
|
||||
throw new AclException("settings command doesn't have publishing or subscription");
|
||||
}
|
||||
}
|
||||
} else if (NotifyClientTerminationRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
NotifyClientTerminationRequest request = (NotifyClientTerminationRequest) messageV3;
|
||||
if (StringUtils.isNotBlank(request.getGroup().getName())) {
|
||||
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);
|
||||
}
|
||||
} else if (QueryRouteRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
QueryRouteRequest request = (QueryRouteRequest) messageV3;
|
||||
accessResource.addResourceAndPerm(request.getTopic(), Permission.ANY);
|
||||
} else if (QueryAssignmentRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
QueryAssignmentRequest request = (QueryAssignmentRequest) messageV3;
|
||||
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);
|
||||
accessResource.addResourceAndPerm(request.getTopic(), Permission.SUB);
|
||||
} else if (ChangeInvisibleDurationRequest.getDescriptor().getFullName().equals(rpcFullName)) {
|
||||
ChangeInvisibleDurationRequest request = (ChangeInvisibleDurationRequest) messageV3;
|
||||
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);
|
||||
accessResource.addResourceAndPerm(request.getTopic(), Permission.SUB);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new AclException(t.getMessage(), t);
|
||||
}
|
||||
return accessResource;
|
||||
}
|
||||
|
||||
private void addResourceAndPerm(Resource resource, byte permission) {
|
||||
String resourceName = NamespaceUtil.wrapNamespace(resource.getResourceNamespace(), resource.getName());
|
||||
addResourceAndPerm(resourceName, permission);
|
||||
}
|
||||
|
||||
private void addGroupResourceAndPerm(Resource resource, byte permission) {
|
||||
String resourceName = NamespaceUtil.wrapNamespace(resource.getResourceNamespace(), resource.getName());
|
||||
addResourceAndPerm(getRetryTopic(resourceName), permission);
|
||||
}
|
||||
|
||||
public static PlainAccessResource build(PlainAccessConfig plainAccessConfig, RemoteAddressStrategy remoteAddressStrategy) {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setAccessKey(plainAccessConfig.getAccessKey());
|
||||
plainAccessResource.setSecretKey(plainAccessConfig.getSecretKey());
|
||||
plainAccessResource.setWhiteRemoteAddress(plainAccessConfig.getWhiteRemoteAddress());
|
||||
|
||||
plainAccessResource.setAdmin(plainAccessConfig.isAdmin());
|
||||
|
||||
plainAccessResource.setDefaultGroupPerm(Permission.parsePermFromString(plainAccessConfig.getDefaultGroupPerm()));
|
||||
plainAccessResource.setDefaultTopicPerm(Permission.parsePermFromString(plainAccessConfig.getDefaultTopicPerm()));
|
||||
|
||||
Permission.parseResourcePerms(plainAccessResource, false, plainAccessConfig.getGroupPerms());
|
||||
Permission.parseResourcePerms(plainAccessResource, true, plainAccessConfig.getTopicPerms());
|
||||
|
||||
plainAccessResource.setRemoteAddressStrategy(remoteAddressStrategy);
|
||||
return plainAccessResource;
|
||||
}
|
||||
|
||||
public static boolean isRetryTopic(String topic) {
|
||||
return null != topic && topic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX);
|
||||
}
|
||||
|
||||
public static String printStr(String resource, boolean isGroup) {
|
||||
if (resource == null) {
|
||||
return null;
|
||||
}
|
||||
if (isGroup) {
|
||||
return String.format("%s:%s", "group", getGroupFromRetryTopic(resource));
|
||||
} else {
|
||||
return String.format("%s:%s", "topic", resource);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getGroupFromRetryTopic(String retryTopic) {
|
||||
if (retryTopic == null) {
|
||||
return null;
|
||||
}
|
||||
return KeyBuilder.parseGroup(retryTopic);
|
||||
}
|
||||
|
||||
public static String getRetryTopic(String group) {
|
||||
if (group == null) {
|
||||
return null;
|
||||
}
|
||||
return MixAll.getRetryTopic(group);
|
||||
}
|
||||
|
||||
public void addResourceAndPerm(String resource, byte perm) {
|
||||
if (resource == null) {
|
||||
return;
|
||||
}
|
||||
if (resourcePermMap == null) {
|
||||
resourcePermMap = new HashMap<>();
|
||||
}
|
||||
resourcePermMap.put(resource, perm);
|
||||
}
|
||||
|
||||
public String getAccessKey() {
|
||||
return accessKey;
|
||||
}
|
||||
|
||||
public void setAccessKey(String accessKey) {
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public String getWhiteRemoteAddress() {
|
||||
return whiteRemoteAddress;
|
||||
}
|
||||
|
||||
public void setWhiteRemoteAddress(String whiteRemoteAddress) {
|
||||
this.whiteRemoteAddress = whiteRemoteAddress;
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return admin;
|
||||
}
|
||||
|
||||
public void setAdmin(boolean admin) {
|
||||
this.admin = admin;
|
||||
}
|
||||
|
||||
public byte getDefaultTopicPerm() {
|
||||
return defaultTopicPerm;
|
||||
}
|
||||
|
||||
public void setDefaultTopicPerm(byte defaultTopicPerm) {
|
||||
this.defaultTopicPerm = defaultTopicPerm;
|
||||
}
|
||||
|
||||
public byte getDefaultGroupPerm() {
|
||||
return defaultGroupPerm;
|
||||
}
|
||||
|
||||
public void setDefaultGroupPerm(byte defaultGroupPerm) {
|
||||
this.defaultGroupPerm = defaultGroupPerm;
|
||||
}
|
||||
|
||||
public Map<String, Byte> getResourcePermMap() {
|
||||
return resourcePermMap;
|
||||
}
|
||||
|
||||
public String getRecognition() {
|
||||
return recognition;
|
||||
}
|
||||
|
||||
public void setRecognition(String recognition) {
|
||||
this.recognition = recognition;
|
||||
}
|
||||
|
||||
public int getRequestCode() {
|
||||
return requestCode;
|
||||
}
|
||||
|
||||
public void setRequestCode(int requestCode) {
|
||||
this.requestCode = requestCode;
|
||||
}
|
||||
|
||||
public String getSecretToken() {
|
||||
return secretToken;
|
||||
}
|
||||
|
||||
public void setSecretToken(String secretToken) {
|
||||
this.secretToken = secretToken;
|
||||
}
|
||||
|
||||
public RemoteAddressStrategy getRemoteAddressStrategy() {
|
||||
return remoteAddressStrategy;
|
||||
}
|
||||
|
||||
public void setRemoteAddressStrategy(RemoteAddressStrategy remoteAddressStrategy) {
|
||||
this.remoteAddressStrategy = remoteAddressStrategy;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this);
|
||||
}
|
||||
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.rocketmq.acl.AccessResource;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.acl.common.AuthenticationHeader;
|
||||
import org.apache.rocketmq.common.AclConfig;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.remoting.protocol.DataVersion;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
|
||||
public class PlainAccessValidator implements AccessValidator {
|
||||
|
||||
private PlainPermissionManager aclPlugEngine;
|
||||
|
||||
public PlainAccessValidator() {
|
||||
aclPlugEngine = new PlainPermissionManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessResource parse(RemotingCommand request, String remoteAddr) {
|
||||
return PlainAccessResource.parse(request, remoteAddr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessResource parse(GeneratedMessageV3 messageV3, AuthenticationHeader header) {
|
||||
return PlainAccessResource.parse(messageV3, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(AccessResource accessResource) {
|
||||
aclPlugEngine.validate((PlainAccessResource) accessResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateAccessConfig(PlainAccessConfig plainAccessConfig) {
|
||||
return aclPlugEngine.updateAccessConfig(plainAccessConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteAccessConfig(String accessKey) {
|
||||
return aclPlugEngine.deleteAccessConfig(accessKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAclConfigVersion() {
|
||||
return aclPlugEngine.getAclConfigDataVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList) {
|
||||
return aclPlugEngine.updateGlobalWhiteAddrsConfig(globalWhiteAddrsList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList, String aclFileFullPath) {
|
||||
return aclPlugEngine.updateGlobalWhiteAddrsConfig(globalWhiteAddrsList, aclFileFullPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AclConfig getAllAclConfig() {
|
||||
return aclPlugEngine.getAllAclConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, DataVersion> getAllAclConfigVersion() {
|
||||
return aclPlugEngine.getDataVersionMap();
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import java.util.Map;
|
||||
import org.apache.rocketmq.acl.AccessResource;
|
||||
import org.apache.rocketmq.acl.PermissionChecker;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.Permission;
|
||||
|
||||
public class PlainPermissionChecker implements PermissionChecker {
|
||||
public void check(AccessResource checkedAccess, AccessResource ownedAccess) {
|
||||
PlainAccessResource checkedPlainAccess = (PlainAccessResource) checkedAccess;
|
||||
PlainAccessResource ownedPlainAccess = (PlainAccessResource) ownedAccess;
|
||||
|
||||
if (ownedPlainAccess.isAdmin()) {
|
||||
// admin user don't need verification
|
||||
return;
|
||||
}
|
||||
if (Permission.needAdminPerm(checkedPlainAccess.getRequestCode())) {
|
||||
throw new AclException(String.format("Need admin permission for request code=%d, but accessKey=%s is not", checkedPlainAccess.getRequestCode(), ownedPlainAccess.getAccessKey()));
|
||||
}
|
||||
|
||||
Map<String, Byte> needCheckedPermMap = checkedPlainAccess.getResourcePermMap();
|
||||
Map<String, Byte> ownedPermMap = ownedPlainAccess.getResourcePermMap();
|
||||
|
||||
if (needCheckedPermMap == null) {
|
||||
// If the needCheckedPermMap is null,then return
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Byte> needCheckedEntry : needCheckedPermMap.entrySet()) {
|
||||
String resource = needCheckedEntry.getKey();
|
||||
Byte neededPerm = needCheckedEntry.getValue();
|
||||
boolean isGroup = PlainAccessResource.isRetryTopic(resource);
|
||||
|
||||
if (ownedPermMap == null || !ownedPermMap.containsKey(resource)) {
|
||||
// Check the default perm
|
||||
byte ownedPerm = isGroup ? ownedPlainAccess.getDefaultGroupPerm() :
|
||||
ownedPlainAccess.getDefaultTopicPerm();
|
||||
if (!Permission.checkPermission(neededPerm, ownedPerm)) {
|
||||
throw new AclException(String.format("No default permission for %s", PlainAccessResource.printStr(resource, isGroup)));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!Permission.checkPermission(neededPerm, ownedPermMap.get(resource))) {
|
||||
throw new AclException(String.format("No permission for %s", PlainAccessResource.printStr(resource, isGroup)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,644 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.acl.PermissionChecker;
|
||||
import org.apache.rocketmq.acl.common.AclConstants;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.AclSigner;
|
||||
import org.apache.rocketmq.acl.common.AclUtils;
|
||||
import org.apache.rocketmq.acl.common.Permission;
|
||||
import org.apache.rocketmq.common.AclConfig;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.common.topic.TopicValidator;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
import org.apache.rocketmq.remoting.protocol.DataVersion;
|
||||
import org.apache.rocketmq.srvutil.AclFileWatchService;
|
||||
|
||||
public class PlainPermissionManager {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggerName.COMMON_LOGGER_NAME);
|
||||
|
||||
private String fileHome = System.getProperty(MixAll.ROCKETMQ_HOME_PROPERTY,
|
||||
System.getenv(MixAll.ROCKETMQ_HOME_ENV));
|
||||
|
||||
private String defaultAclDir;
|
||||
|
||||
private String defaultAclFile;
|
||||
|
||||
private Map<String/** fileFullPath **/, Map<String/** AccessKey **/, PlainAccessResource>> aclPlainAccessResourceMap = new HashMap<>();
|
||||
|
||||
private Map<String/** AccessKey **/, String/** fileFullPath **/> accessKeyTable = new HashMap<>();
|
||||
|
||||
private List<RemoteAddressStrategy> globalWhiteRemoteAddressStrategy = new ArrayList<>();
|
||||
|
||||
private RemoteAddressStrategyFactory remoteAddressStrategyFactory = new RemoteAddressStrategyFactory();
|
||||
|
||||
private Map<String/** fileFullPath **/, List<RemoteAddressStrategy>> globalWhiteRemoteAddressStrategyMap = new HashMap<>();
|
||||
|
||||
private boolean isWatchStart;
|
||||
|
||||
private Map<String/** fileFullPath **/, DataVersion> dataVersionMap = new HashMap<>();
|
||||
|
||||
@Deprecated
|
||||
private final DataVersion dataVersion = new DataVersion();
|
||||
|
||||
private List<String> fileList = new ArrayList<>();
|
||||
|
||||
private final PermissionChecker permissionChecker = new PlainPermissionChecker();
|
||||
|
||||
public PlainPermissionManager() {
|
||||
this.defaultAclDir = MixAll.dealFilePath(fileHome + File.separator + "conf" + File.separator + "acl");
|
||||
this.defaultAclFile = MixAll.dealFilePath(fileHome + File.separator + System.getProperty("rocketmq.acl.plain.file", "conf" + File.separator + "plain_acl.yml"));
|
||||
load();
|
||||
watch();
|
||||
}
|
||||
|
||||
public List<String> getAllAclFiles(String path) {
|
||||
if (!new File(path).exists()) {
|
||||
log.info("The default acl dir {} is not exist", path);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> allAclFileFullPath = new ArrayList<>();
|
||||
File file = new File(path);
|
||||
File[] files = file.listFiles();
|
||||
for (int i = 0; files != null && i < files.length; i++) {
|
||||
String fileName = files[i].getAbsolutePath();
|
||||
File f = new File(fileName);
|
||||
if (fileName.equals(fileHome + MixAll.ACL_CONF_TOOLS_FILE)) {
|
||||
continue;
|
||||
} else if (fileName.endsWith(".yml") || fileName.endsWith(".yaml")) {
|
||||
allAclFileFullPath.add(fileName);
|
||||
} else if (f.isDirectory()) {
|
||||
allAclFileFullPath.addAll(getAllAclFiles(fileName));
|
||||
}
|
||||
}
|
||||
return allAclFileFullPath;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (fileHome == null || fileHome.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Map<String, PlainAccessResource>> aclPlainAccessResourceMap = new HashMap<>();
|
||||
Map<String, String> accessKeyTable = new HashMap<>();
|
||||
List<RemoteAddressStrategy> globalWhiteRemoteAddressStrategy = new ArrayList<>();
|
||||
Map<String, List<RemoteAddressStrategy>> globalWhiteRemoteAddressStrategyMap = new HashMap<>();
|
||||
Map<String, DataVersion> dataVersionMap = new HashMap<>();
|
||||
|
||||
assureAclConfigFilesExist();
|
||||
|
||||
fileList = getAllAclFiles(defaultAclDir);
|
||||
if (new File(defaultAclFile).exists() && !fileList.contains(defaultAclFile)) {
|
||||
fileList.add(defaultAclFile);
|
||||
}
|
||||
|
||||
for (String path : fileList) {
|
||||
final String currentFile = MixAll.dealFilePath(path);
|
||||
PlainAccessData plainAclConfData = AclUtils.getYamlDataObject(currentFile, PlainAccessData.class);
|
||||
if (plainAclConfData == null) {
|
||||
log.warn("No data in file {}", currentFile);
|
||||
continue;
|
||||
}
|
||||
log.info("Broker plain acl conf data is : {}", plainAclConfData.toString());
|
||||
|
||||
List<RemoteAddressStrategy> globalWhiteRemoteAddressStrategyList = new ArrayList<>();
|
||||
List<String> globalWhiteRemoteAddressesList = plainAclConfData.getGlobalWhiteRemoteAddresses();
|
||||
if (globalWhiteRemoteAddressesList != null && !globalWhiteRemoteAddressesList.isEmpty()) {
|
||||
for (String address : globalWhiteRemoteAddressesList) {
|
||||
globalWhiteRemoteAddressStrategyList.add(remoteAddressStrategyFactory.getRemoteAddressStrategy(address));
|
||||
}
|
||||
}
|
||||
if (!globalWhiteRemoteAddressStrategyList.isEmpty()) {
|
||||
globalWhiteRemoteAddressStrategyMap.put(currentFile, globalWhiteRemoteAddressStrategyList);
|
||||
globalWhiteRemoteAddressStrategy.addAll(globalWhiteRemoteAddressStrategyList);
|
||||
}
|
||||
|
||||
List<PlainAccessConfig> accounts = plainAclConfData.getAccounts();
|
||||
Map<String, PlainAccessResource> plainAccessResourceMap = new HashMap<>();
|
||||
if (accounts != null && !accounts.isEmpty()) {
|
||||
for (PlainAccessConfig plainAccessConfig : accounts) {
|
||||
PlainAccessResource plainAccessResource = buildPlainAccessResource(plainAccessConfig);
|
||||
//AccessKey can not be defined in multiple ACL files
|
||||
if (accessKeyTable.get(plainAccessResource.getAccessKey()) == null) {
|
||||
plainAccessResourceMap.put(plainAccessResource.getAccessKey(), plainAccessResource);
|
||||
accessKeyTable.put(plainAccessResource.getAccessKey(), currentFile);
|
||||
} else {
|
||||
log.warn("The accessKey {} is repeated in multiple ACL files", plainAccessResource.getAccessKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!plainAccessResourceMap.isEmpty()) {
|
||||
aclPlainAccessResourceMap.put(currentFile, plainAccessResourceMap);
|
||||
}
|
||||
|
||||
List<PlainAccessData.DataVersion> dataVersions = plainAclConfData.getDataVersion();
|
||||
DataVersion dataVersion = new DataVersion();
|
||||
if (dataVersions != null && !dataVersions.isEmpty()) {
|
||||
DataVersion firstElement = new DataVersion();
|
||||
firstElement.setCounter(new AtomicLong(dataVersions.get(0).getCounter()));
|
||||
firstElement.setTimestamp(dataVersions.get(0).getTimestamp());
|
||||
dataVersion.assignNewOne(firstElement);
|
||||
}
|
||||
dataVersionMap.put(currentFile, dataVersion);
|
||||
}
|
||||
|
||||
if (dataVersionMap.containsKey(defaultAclFile)) {
|
||||
this.dataVersion.assignNewOne(dataVersionMap.get(defaultAclFile));
|
||||
}
|
||||
this.dataVersionMap = dataVersionMap;
|
||||
this.globalWhiteRemoteAddressStrategyMap = globalWhiteRemoteAddressStrategyMap;
|
||||
this.globalWhiteRemoteAddressStrategy = globalWhiteRemoteAddressStrategy;
|
||||
this.aclPlainAccessResourceMap = aclPlainAccessResourceMap;
|
||||
this.accessKeyTable = accessKeyTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently GlobalWhiteAddress is defined in {@link #defaultAclFile}, so make sure it exists.
|
||||
*/
|
||||
private void assureAclConfigFilesExist() {
|
||||
final Path defaultAclFilePath = Paths.get(this.defaultAclFile);
|
||||
if (!Files.exists(defaultAclFilePath)) {
|
||||
try {
|
||||
Files.createFile(defaultAclFilePath);
|
||||
} catch (FileAlreadyExistsException e) {
|
||||
// Maybe created by other threads
|
||||
} catch (IOException e) {
|
||||
log.error("Error in creating " + this.defaultAclFile, e);
|
||||
throw new AclException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void load(String aclFilePath) {
|
||||
aclFilePath = MixAll.dealFilePath(aclFilePath);
|
||||
Map<String, PlainAccessResource> plainAccessResourceMap = new HashMap<>();
|
||||
List<RemoteAddressStrategy> globalWhiteRemoteAddressStrategy = new ArrayList<>();
|
||||
|
||||
PlainAccessData plainAclConfData = AclUtils.getYamlDataObject(aclFilePath,
|
||||
PlainAccessData.class);
|
||||
if (plainAclConfData == null) {
|
||||
log.warn("No data in {}, skip it", aclFilePath);
|
||||
return;
|
||||
}
|
||||
log.info("Broker plain acl conf data is : {}", plainAclConfData.toString());
|
||||
List<String> globalWhiteRemoteAddressesList = plainAclConfData.getGlobalWhiteRemoteAddresses();
|
||||
if (globalWhiteRemoteAddressesList != null && !globalWhiteRemoteAddressesList.isEmpty()) {
|
||||
for (String address : globalWhiteRemoteAddressesList) {
|
||||
globalWhiteRemoteAddressStrategy.add(remoteAddressStrategyFactory.getRemoteAddressStrategy(address));
|
||||
}
|
||||
}
|
||||
|
||||
this.globalWhiteRemoteAddressStrategy.addAll(globalWhiteRemoteAddressStrategy);
|
||||
if (this.globalWhiteRemoteAddressStrategyMap.get(aclFilePath) != null) {
|
||||
List<RemoteAddressStrategy> remoteAddressStrategyList = this.globalWhiteRemoteAddressStrategyMap.get(aclFilePath);
|
||||
for (RemoteAddressStrategy remoteAddressStrategy : remoteAddressStrategyList) {
|
||||
this.globalWhiteRemoteAddressStrategy.remove(remoteAddressStrategy);
|
||||
}
|
||||
this.globalWhiteRemoteAddressStrategyMap.put(aclFilePath, globalWhiteRemoteAddressStrategy);
|
||||
}
|
||||
|
||||
List<PlainAccessConfig> accounts = plainAclConfData.getAccounts();
|
||||
if (accounts != null && !accounts.isEmpty()) {
|
||||
for (PlainAccessConfig plainAccessConfig : accounts) {
|
||||
PlainAccessResource plainAccessResource = buildPlainAccessResource(plainAccessConfig);
|
||||
//AccessKey can not be defined in multiple ACL files
|
||||
String oldPath = this.accessKeyTable.get(plainAccessResource.getAccessKey());
|
||||
if (oldPath == null || aclFilePath.equals(oldPath)) {
|
||||
plainAccessResourceMap.put(plainAccessResource.getAccessKey(), plainAccessResource);
|
||||
this.accessKeyTable.put(plainAccessResource.getAccessKey(), aclFilePath);
|
||||
} else {
|
||||
log.warn("The accessKey {} is repeated in multiple ACL files", plainAccessResource.getAccessKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For loading dataversion part just
|
||||
List<PlainAccessData.DataVersion> dataVersions = plainAclConfData.getDataVersion();
|
||||
DataVersion dataVersion = new DataVersion();
|
||||
if (dataVersions != null && !dataVersions.isEmpty()) {
|
||||
DataVersion firstElement = new DataVersion();
|
||||
firstElement.setCounter(new AtomicLong(dataVersions.get(0).getCounter()));
|
||||
firstElement.setTimestamp(dataVersions.get(0).getTimestamp());
|
||||
dataVersion.assignNewOne(firstElement);
|
||||
}
|
||||
|
||||
this.aclPlainAccessResourceMap.put(aclFilePath, plainAccessResourceMap);
|
||||
this.dataVersionMap.put(aclFilePath, dataVersion);
|
||||
if (aclFilePath.equals(defaultAclFile)) {
|
||||
this.dataVersion.assignNewOne(dataVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getAclConfigDataVersion() {
|
||||
return this.dataVersion.toJson();
|
||||
}
|
||||
|
||||
public Map<String, DataVersion> getDataVersionMap() {
|
||||
return this.dataVersionMap;
|
||||
}
|
||||
|
||||
public PlainAccessData updateAclConfigFileVersion(String aclFileName, PlainAccessData updateAclConfigMap) {
|
||||
|
||||
List<PlainAccessData.DataVersion> dataVersions = updateAclConfigMap.getDataVersion();
|
||||
DataVersion dataVersion = new DataVersion();
|
||||
if (dataVersions != null && !dataVersions.isEmpty()) {
|
||||
dataVersion.setTimestamp(dataVersions.get(0).getTimestamp());
|
||||
dataVersion.setCounter(new AtomicLong(dataVersions.get(0).getCounter()));
|
||||
}
|
||||
dataVersion.nextVersion();
|
||||
List<PlainAccessData.DataVersion> versionElement = new ArrayList<>();
|
||||
PlainAccessData.DataVersion dataVersionNew = new PlainAccessData.DataVersion();
|
||||
dataVersionNew.setTimestamp(dataVersion.getTimestamp());
|
||||
dataVersionNew.setCounter(dataVersion.getCounter().get());
|
||||
versionElement.add(dataVersionNew);
|
||||
updateAclConfigMap.setDataVersion(versionElement);
|
||||
|
||||
dataVersionMap.put(aclFileName, dataVersion);
|
||||
|
||||
return updateAclConfigMap;
|
||||
}
|
||||
|
||||
public boolean updateAccessConfig(PlainAccessConfig plainAccessConfig) {
|
||||
|
||||
if (plainAccessConfig == null) {
|
||||
log.error("Parameter value plainAccessConfig is null,Please check your parameter");
|
||||
throw new AclException("Parameter value plainAccessConfig is null, Please check your parameter");
|
||||
}
|
||||
checkPlainAccessConfig(plainAccessConfig);
|
||||
|
||||
Permission.checkResourcePerms(plainAccessConfig.getTopicPerms());
|
||||
Permission.checkResourcePerms(plainAccessConfig.getGroupPerms());
|
||||
|
||||
if (accessKeyTable.containsKey(plainAccessConfig.getAccessKey())) {
|
||||
PlainAccessConfig updateAccountMap = null;
|
||||
String aclFileName = accessKeyTable.get(plainAccessConfig.getAccessKey());
|
||||
PlainAccessData aclAccessConfigMap = AclUtils.getYamlDataObject(aclFileName, PlainAccessData.class);
|
||||
List<PlainAccessConfig> accounts = aclAccessConfigMap.getAccounts();
|
||||
if (null != accounts) {
|
||||
for (PlainAccessConfig account : accounts) {
|
||||
if (account.getAccessKey().equals(plainAccessConfig.getAccessKey())) {
|
||||
// Update acl access config elements
|
||||
accounts.remove(account);
|
||||
updateAccountMap = createAclAccessConfigMap(account, plainAccessConfig);
|
||||
accounts.add(updateAccountMap);
|
||||
aclAccessConfigMap.setAccounts(accounts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Maybe deleted in file, add it back
|
||||
accounts = new LinkedList<>();
|
||||
updateAccountMap = createAclAccessConfigMap(null, plainAccessConfig);
|
||||
accounts.add(updateAccountMap);
|
||||
aclAccessConfigMap.setAccounts(accounts);
|
||||
}
|
||||
Map<String, PlainAccessResource> accountMap = aclPlainAccessResourceMap.get(aclFileName);
|
||||
if (accountMap == null) {
|
||||
accountMap = new HashMap<>(1);
|
||||
accountMap.put(plainAccessConfig.getAccessKey(), buildPlainAccessResource(plainAccessConfig));
|
||||
} else if (accountMap.isEmpty()) {
|
||||
accountMap.put(plainAccessConfig.getAccessKey(), buildPlainAccessResource(plainAccessConfig));
|
||||
} else {
|
||||
for (Map.Entry<String, PlainAccessResource> entry : accountMap.entrySet()) {
|
||||
if (entry.getValue().getAccessKey().equals(plainAccessConfig.getAccessKey())) {
|
||||
PlainAccessResource plainAccessResource = buildPlainAccessResource(plainAccessConfig);
|
||||
accountMap.put(entry.getKey(), plainAccessResource);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
aclPlainAccessResourceMap.put(aclFileName, accountMap);
|
||||
return AclUtils.writeDataObject(aclFileName, updateAclConfigFileVersion(aclFileName, aclAccessConfigMap));
|
||||
} else {
|
||||
String fileName = MixAll.dealFilePath(defaultAclFile);
|
||||
//Create acl access config elements on the default acl file
|
||||
if (aclPlainAccessResourceMap.get(defaultAclFile) == null || aclPlainAccessResourceMap.get(defaultAclFile).size() == 0) {
|
||||
try {
|
||||
File defaultAclFile = new File(fileName);
|
||||
if (!defaultAclFile.exists()) {
|
||||
defaultAclFile.createNewFile();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("create default acl file has exception when update accessConfig. ", e);
|
||||
}
|
||||
}
|
||||
PlainAccessData aclAccessConfigMap = AclUtils.getYamlDataObject(defaultAclFile, PlainAccessData.class);
|
||||
if (aclAccessConfigMap == null) {
|
||||
aclAccessConfigMap = new PlainAccessData();
|
||||
}
|
||||
List<PlainAccessConfig> accounts = aclAccessConfigMap.getAccounts();
|
||||
// When no accounts defined
|
||||
if (null == accounts) {
|
||||
accounts = new ArrayList<>();
|
||||
}
|
||||
accounts.add(createAclAccessConfigMap(null, plainAccessConfig));
|
||||
aclAccessConfigMap.setAccounts(accounts);
|
||||
accessKeyTable.put(plainAccessConfig.getAccessKey(), fileName);
|
||||
if (aclPlainAccessResourceMap.get(fileName) == null) {
|
||||
Map<String, PlainAccessResource> plainAccessResourceMap = new HashMap<>(1);
|
||||
plainAccessResourceMap.put(plainAccessConfig.getAccessKey(), buildPlainAccessResource(plainAccessConfig));
|
||||
aclPlainAccessResourceMap.put(fileName, plainAccessResourceMap);
|
||||
} else {
|
||||
Map<String, PlainAccessResource> plainAccessResourceMap = aclPlainAccessResourceMap.get(fileName);
|
||||
plainAccessResourceMap.put(plainAccessConfig.getAccessKey(), buildPlainAccessResource(plainAccessConfig));
|
||||
aclPlainAccessResourceMap.put(fileName, plainAccessResourceMap);
|
||||
}
|
||||
return AclUtils.writeDataObject(defaultAclFile, updateAclConfigFileVersion(defaultAclFile, aclAccessConfigMap));
|
||||
}
|
||||
}
|
||||
|
||||
public PlainAccessConfig createAclAccessConfigMap(PlainAccessConfig existedAccountMap,
|
||||
PlainAccessConfig plainAccessConfig) {
|
||||
|
||||
PlainAccessConfig newAccountsMap = null;
|
||||
if (existedAccountMap == null) {
|
||||
newAccountsMap = new PlainAccessConfig();
|
||||
} else {
|
||||
newAccountsMap = existedAccountMap;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(plainAccessConfig.getAccessKey()) ||
|
||||
plainAccessConfig.getAccessKey().length() <= AclConstants.ACCESS_KEY_MIN_LENGTH) {
|
||||
throw new AclException(String.format(
|
||||
"The accessKey=%s cannot be null and length should longer than 6",
|
||||
plainAccessConfig.getAccessKey()));
|
||||
}
|
||||
newAccountsMap.setAccessKey(plainAccessConfig.getAccessKey());
|
||||
|
||||
if (!StringUtils.isEmpty(plainAccessConfig.getSecretKey())) {
|
||||
if (plainAccessConfig.getSecretKey().length() <= AclConstants.SECRET_KEY_MIN_LENGTH) {
|
||||
throw new AclException(String.format(
|
||||
"The secretKey=%s value length should longer than 6",
|
||||
plainAccessConfig.getSecretKey()));
|
||||
}
|
||||
newAccountsMap.setSecretKey(plainAccessConfig.getSecretKey());
|
||||
}
|
||||
if (plainAccessConfig.getWhiteRemoteAddress() != null) {
|
||||
newAccountsMap.setWhiteRemoteAddress(plainAccessConfig.getWhiteRemoteAddress());
|
||||
}
|
||||
if (!StringUtils.isEmpty(String.valueOf(plainAccessConfig.isAdmin()))) {
|
||||
newAccountsMap.setAdmin(plainAccessConfig.isAdmin());
|
||||
}
|
||||
if (!StringUtils.isEmpty(plainAccessConfig.getDefaultTopicPerm())) {
|
||||
newAccountsMap.setDefaultTopicPerm(plainAccessConfig.getDefaultTopicPerm());
|
||||
}
|
||||
if (!StringUtils.isEmpty(plainAccessConfig.getDefaultGroupPerm())) {
|
||||
newAccountsMap.setDefaultGroupPerm(plainAccessConfig.getDefaultGroupPerm());
|
||||
}
|
||||
if (plainAccessConfig.getTopicPerms() != null) {
|
||||
newAccountsMap.setTopicPerms(plainAccessConfig.getTopicPerms());
|
||||
}
|
||||
if (plainAccessConfig.getGroupPerms() != null) {
|
||||
newAccountsMap.setGroupPerms(plainAccessConfig.getGroupPerms());
|
||||
}
|
||||
|
||||
return newAccountsMap;
|
||||
}
|
||||
|
||||
public boolean deleteAccessConfig(String accessKey) {
|
||||
if (StringUtils.isEmpty(accessKey)) {
|
||||
log.error("Parameter value accessKey is null or empty String,Please check your parameter");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (accessKeyTable.containsKey(accessKey)) {
|
||||
String aclFileName = accessKeyTable.get(accessKey);
|
||||
PlainAccessData aclAccessConfigData = AclUtils.getYamlDataObject(aclFileName,
|
||||
PlainAccessData.class);
|
||||
if (aclAccessConfigData == null) {
|
||||
log.warn("No data found in {} when deleting access config of {}", aclFileName, accessKey);
|
||||
return true;
|
||||
}
|
||||
List<PlainAccessConfig> accounts = aclAccessConfigData.getAccounts();
|
||||
Iterator<PlainAccessConfig> itemIterator = accounts.iterator();
|
||||
while (itemIterator.hasNext()) {
|
||||
if (itemIterator.next().getAccessKey().equals(accessKey)) {
|
||||
// Delete the related acl config element
|
||||
itemIterator.remove();
|
||||
accessKeyTable.remove(accessKey);
|
||||
aclAccessConfigData.setAccounts(accounts);
|
||||
return AclUtils.writeDataObject(aclFileName, updateAclConfigFileVersion(aclFileName, aclAccessConfigData));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList) {
|
||||
return this.updateGlobalWhiteAddrsConfig(globalWhiteAddrsList, this.defaultAclFile);
|
||||
}
|
||||
|
||||
public boolean updateGlobalWhiteAddrsConfig(List<String> globalWhiteAddrsList, String fileName) {
|
||||
if (fileName == null || fileName.isEmpty()) {
|
||||
fileName = this.defaultAclFile;
|
||||
}
|
||||
|
||||
if (globalWhiteAddrsList == null) {
|
||||
log.error("Parameter value globalWhiteAddrsList is null,Please check your parameter");
|
||||
return false;
|
||||
}
|
||||
|
||||
File file = new File(fileName);
|
||||
if (!file.exists() || file.isDirectory()) {
|
||||
log.error("Parameter value " + fileName + " is not exist or is a directory, please check your parameter");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file.getAbsolutePath().startsWith(fileHome)) {
|
||||
log.error("Parameter value " + fileName + " is not in the directory rocketmq.home.dir " + fileHome);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fileName.endsWith(".yml") && fileName.endsWith(".yaml")) {
|
||||
log.error("Parameter value " + fileName + " is not a ACL configuration file");
|
||||
return false;
|
||||
}
|
||||
|
||||
PlainAccessData aclAccessConfigMap = AclUtils.getYamlDataObject(fileName, PlainAccessData.class);
|
||||
if (aclAccessConfigMap == null) {
|
||||
aclAccessConfigMap = new PlainAccessData();
|
||||
log.info("No data in {}, create a new aclAccessConfigMap", fileName);
|
||||
}
|
||||
// Update globalWhiteRemoteAddr element in memory map firstly
|
||||
aclAccessConfigMap.setGlobalWhiteRemoteAddresses(new ArrayList<>(globalWhiteAddrsList));
|
||||
return AclUtils.writeDataObject(fileName, updateAclConfigFileVersion(fileName, aclAccessConfigMap));
|
||||
|
||||
}
|
||||
|
||||
public AclConfig getAllAclConfig() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
List<PlainAccessConfig> configs = new ArrayList<>();
|
||||
List<String> whiteAddrs = new ArrayList<>();
|
||||
Set<String> accessKeySets = new HashSet<>();
|
||||
|
||||
for (String path : fileList) {
|
||||
PlainAccessData plainAclConfData = AclUtils.getYamlDataObject(path, PlainAccessData.class);
|
||||
if (plainAclConfData == null) {
|
||||
continue;
|
||||
}
|
||||
List<String> globalWhiteAddrs = plainAclConfData.getGlobalWhiteRemoteAddresses();
|
||||
if (globalWhiteAddrs != null && !globalWhiteAddrs.isEmpty()) {
|
||||
whiteAddrs.addAll(globalWhiteAddrs);
|
||||
}
|
||||
|
||||
List<PlainAccessConfig> plainAccessConfigs = plainAclConfData.getAccounts();
|
||||
if (plainAccessConfigs != null && !plainAccessConfigs.isEmpty()) {
|
||||
for (PlainAccessConfig accessConfig : plainAccessConfigs) {
|
||||
if (!accessKeySets.contains(accessConfig.getAccessKey())) {
|
||||
accessKeySets.add(accessConfig.getAccessKey());
|
||||
PlainAccessConfig plainAccessConfig = new PlainAccessConfig();
|
||||
plainAccessConfig.setGroupPerms(accessConfig.getGroupPerms());
|
||||
plainAccessConfig.setDefaultTopicPerm(accessConfig.getDefaultTopicPerm());
|
||||
plainAccessConfig.setDefaultGroupPerm(accessConfig.getDefaultGroupPerm());
|
||||
plainAccessConfig.setAccessKey(accessConfig.getAccessKey());
|
||||
plainAccessConfig.setSecretKey(accessConfig.getSecretKey());
|
||||
plainAccessConfig.setAdmin(accessConfig.isAdmin());
|
||||
plainAccessConfig.setTopicPerms(accessConfig.getTopicPerms());
|
||||
plainAccessConfig.setWhiteRemoteAddress(accessConfig.getWhiteRemoteAddress());
|
||||
configs.add(plainAccessConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aclConfig.setPlainAccessConfigs(configs);
|
||||
aclConfig.setGlobalWhiteAddrs(whiteAddrs);
|
||||
return aclConfig;
|
||||
}
|
||||
|
||||
private void watch() {
|
||||
try {
|
||||
AclFileWatchService aclFileWatchService = new AclFileWatchService(defaultAclDir, defaultAclFile, new AclFileWatchService.Listener() {
|
||||
@Override
|
||||
public void onFileChanged(String aclFileName) {
|
||||
load(aclFileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileNumChanged(String path) {
|
||||
load();
|
||||
}
|
||||
});
|
||||
aclFileWatchService.start();
|
||||
log.info("Succeed to start AclFileWatchService");
|
||||
this.isWatchStart = true;
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to start AclWatcherService", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void checkPerm(PlainAccessResource needCheckedAccess, PlainAccessResource ownedAccess) {
|
||||
permissionChecker.check(needCheckedAccess, ownedAccess);
|
||||
}
|
||||
|
||||
void clearPermissionInfo() {
|
||||
this.aclPlainAccessResourceMap.clear();
|
||||
this.accessKeyTable.clear();
|
||||
this.globalWhiteRemoteAddressStrategy.clear();
|
||||
}
|
||||
|
||||
public void checkPlainAccessConfig(PlainAccessConfig plainAccessConfig) throws AclException {
|
||||
if (plainAccessConfig.getAccessKey() == null
|
||||
|| plainAccessConfig.getSecretKey() == null
|
||||
|| plainAccessConfig.getAccessKey().length() <= AclConstants.ACCESS_KEY_MIN_LENGTH
|
||||
|| plainAccessConfig.getSecretKey().length() <= AclConstants.SECRET_KEY_MIN_LENGTH) {
|
||||
throw new AclException(String.format(
|
||||
"The accessKey=%s and secretKey=%s cannot be null and length should longer than 6",
|
||||
plainAccessConfig.getAccessKey(), plainAccessConfig.getSecretKey()));
|
||||
}
|
||||
}
|
||||
|
||||
public PlainAccessResource buildPlainAccessResource(PlainAccessConfig plainAccessConfig) throws AclException {
|
||||
checkPlainAccessConfig(plainAccessConfig);
|
||||
return PlainAccessResource.build(plainAccessConfig, remoteAddressStrategyFactory.
|
||||
getRemoteAddressStrategy(plainAccessConfig.getWhiteRemoteAddress()));
|
||||
}
|
||||
|
||||
public void validate(PlainAccessResource plainAccessResource) {
|
||||
|
||||
// Check the global white remote addr
|
||||
for (RemoteAddressStrategy remoteAddressStrategy : globalWhiteRemoteAddressStrategy) {
|
||||
if (remoteAddressStrategy.match(plainAccessResource)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (plainAccessResource.getAccessKey() == null) {
|
||||
throw new AclException("No accessKey is configured");
|
||||
}
|
||||
|
||||
if (!accessKeyTable.containsKey(plainAccessResource.getAccessKey())) {
|
||||
throw new AclException(String.format("No acl config for %s", plainAccessResource.getAccessKey()));
|
||||
}
|
||||
|
||||
// Check the white addr for accessKey
|
||||
String aclFileName = accessKeyTable.get(plainAccessResource.getAccessKey());
|
||||
PlainAccessResource ownedAccess = aclPlainAccessResourceMap.getOrDefault(aclFileName, new HashMap<>()).get(plainAccessResource.getAccessKey());
|
||||
if (ownedAccess == null) {
|
||||
throw new AclException(String.format("No PlainAccessResource for accessKey=%s", plainAccessResource.getAccessKey()));
|
||||
}
|
||||
if (ownedAccess.getRemoteAddressStrategy().match(plainAccessResource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the signature
|
||||
String signature = AclUtils.calSignature(plainAccessResource.getContent(), ownedAccess.getSecretKey());
|
||||
if (plainAccessResource.getSignature() == null
|
||||
|| !MessageDigest.isEqual(signature.getBytes(AclSigner.DEFAULT_CHARSET), plainAccessResource.getSignature().getBytes(AclSigner.DEFAULT_CHARSET))) {
|
||||
throw new AclException(String.format("Check signature failed for accessKey=%s", plainAccessResource.getAccessKey()));
|
||||
}
|
||||
|
||||
//Skip the topic RMQ_SYS_TRACE_TOPIC permission check,if the topic RMQ_SYS_TRACE_TOPIC is used for message trace
|
||||
Map<String, Byte> resourcePermMap = plainAccessResource.getResourcePermMap();
|
||||
if (resourcePermMap != null) {
|
||||
Byte permission = resourcePermMap.get(TopicValidator.RMQ_SYS_TRACE_TOPIC);
|
||||
if (permission != null && permission == Permission.PUB) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check perm of each resource
|
||||
checkPerm(plainAccessResource, ownedAccess);
|
||||
}
|
||||
|
||||
public boolean isWatchStart() {
|
||||
return isWatchStart;
|
||||
}
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.validator.routines.InetAddressValidator;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.AclUtils;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
|
||||
public class RemoteAddressStrategyFactory {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggerName.COMMON_LOGGER_NAME);
|
||||
|
||||
public static final NullRemoteAddressStrategy NULL_NET_ADDRESS_STRATEGY = new NullRemoteAddressStrategy();
|
||||
|
||||
public static final BlankRemoteAddressStrategy BLANK_NET_ADDRESS_STRATEGY = new BlankRemoteAddressStrategy();
|
||||
|
||||
public RemoteAddressStrategy getRemoteAddressStrategy(PlainAccessResource plainAccessResource) {
|
||||
return getRemoteAddressStrategy(plainAccessResource.getWhiteRemoteAddress());
|
||||
}
|
||||
|
||||
public RemoteAddressStrategy getRemoteAddressStrategy(String remoteAddr) {
|
||||
if (StringUtils.isBlank(remoteAddr)) {
|
||||
return BLANK_NET_ADDRESS_STRATEGY;
|
||||
}
|
||||
if ("*".equals(remoteAddr) || "*.*.*.*".equals(remoteAddr) || "*:*:*:*:*:*:*:*".equals(remoteAddr)) {
|
||||
return NULL_NET_ADDRESS_STRATEGY;
|
||||
}
|
||||
if (remoteAddr.endsWith("}")) {
|
||||
if (AclUtils.isColon(remoteAddr)) {
|
||||
String[] strArray = StringUtils.split(remoteAddr, ":");
|
||||
String last = strArray[strArray.length - 1];
|
||||
if (!last.startsWith("{")) {
|
||||
throw new AclException(String.format("MultipleRemoteAddressStrategy netAddress examine scope Exception netAddress: %s", remoteAddr));
|
||||
}
|
||||
return new MultipleRemoteAddressStrategy(AclUtils.getAddresses(remoteAddr, last));
|
||||
} else {
|
||||
String[] strArray = StringUtils.split(remoteAddr, ".");
|
||||
// However a right IP String provided by user,it always can be divided into 4 parts by '.'.
|
||||
if (strArray.length < 4) {
|
||||
throw new AclException(String.format("MultipleRemoteAddressStrategy has got a/some wrong format IP(s): %s ", remoteAddr));
|
||||
}
|
||||
String lastStr = strArray[strArray.length - 1];
|
||||
if (!lastStr.startsWith("{")) {
|
||||
throw new AclException(String.format("MultipleRemoteAddressStrategy netAddress examine scope Exception netAddress: %s", remoteAddr));
|
||||
}
|
||||
return new MultipleRemoteAddressStrategy(AclUtils.getAddresses(remoteAddr, lastStr));
|
||||
}
|
||||
} else if (AclUtils.isComma(remoteAddr)) {
|
||||
return new MultipleRemoteAddressStrategy(StringUtils.split(remoteAddr, ","));
|
||||
} else if (AclUtils.isAsterisk(remoteAddr) || AclUtils.isMinus(remoteAddr)) {
|
||||
return new RangeRemoteAddressStrategy(remoteAddr);
|
||||
}
|
||||
return new OneRemoteAddressStrategy(remoteAddr);
|
||||
|
||||
}
|
||||
|
||||
public static class NullRemoteAddressStrategy implements RemoteAddressStrategy {
|
||||
@Override
|
||||
public boolean match(PlainAccessResource plainAccessResource) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class BlankRemoteAddressStrategy implements RemoteAddressStrategy {
|
||||
@Override
|
||||
public boolean match(PlainAccessResource plainAccessResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MultipleRemoteAddressStrategy implements RemoteAddressStrategy {
|
||||
|
||||
private final Set<String> multipleSet = new HashSet<>();
|
||||
|
||||
public MultipleRemoteAddressStrategy(String[] strArray) {
|
||||
InetAddressValidator validator = InetAddressValidator.getInstance();
|
||||
for (String netAddress : strArray) {
|
||||
if (validator.isValidInet4Address(netAddress)) {
|
||||
multipleSet.add(netAddress);
|
||||
} else if (validator.isValidInet6Address(netAddress)) {
|
||||
multipleSet.add(AclUtils.expandIP(netAddress, 8));
|
||||
} else {
|
||||
throw new AclException(String.format("NetAddress examine Exception netAddress is %s", netAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(PlainAccessResource plainAccessResource) {
|
||||
InetAddressValidator validator = InetAddressValidator.getInstance();
|
||||
String whiteRemoteAddress = plainAccessResource.getWhiteRemoteAddress();
|
||||
if (validator.isValidInet6Address(whiteRemoteAddress)) {
|
||||
whiteRemoteAddress = AclUtils.expandIP(whiteRemoteAddress, 8);
|
||||
}
|
||||
return multipleSet.contains(whiteRemoteAddress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class OneRemoteAddressStrategy implements RemoteAddressStrategy {
|
||||
|
||||
private String netAddress;
|
||||
|
||||
public OneRemoteAddressStrategy(String netAddress) {
|
||||
this.netAddress = netAddress;
|
||||
InetAddressValidator validator = InetAddressValidator.getInstance();
|
||||
if (!(validator.isValidInet4Address(netAddress) || validator.isValidInet6Address(
|
||||
netAddress))) {
|
||||
throw new AclException(String.format("NetAddress examine Exception netAddress is %s",
|
||||
netAddress));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(PlainAccessResource plainAccessResource) {
|
||||
String writeRemoteAddress = AclUtils.expandIP(plainAccessResource.getWhiteRemoteAddress(), 8).toUpperCase();
|
||||
return AclUtils.expandIP(netAddress, 8).toUpperCase().equals(writeRemoteAddress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class RangeRemoteAddressStrategy implements RemoteAddressStrategy {
|
||||
|
||||
private String head;
|
||||
|
||||
private int start;
|
||||
|
||||
private int end;
|
||||
|
||||
private int index;
|
||||
|
||||
public RangeRemoteAddressStrategy(String remoteAddr) {
|
||||
// IPv6 Address
|
||||
if (AclUtils.isColon(remoteAddr)) {
|
||||
AclUtils.IPv6AddressCheck(remoteAddr);
|
||||
String[] strArray = StringUtils.split(remoteAddr, ":");
|
||||
for (int i = 1; i < strArray.length; i++) {
|
||||
if (ipv6Analysis(strArray, i)) {
|
||||
AclUtils.verify(remoteAddr, index - 1);
|
||||
String preAddress = AclUtils.v6ipProcess(remoteAddr);
|
||||
this.index = StringUtils.split(preAddress, ":").length;
|
||||
this.head = preAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String[] strArray = StringUtils.split(remoteAddr, ".");
|
||||
if (analysis(strArray, 1) || analysis(strArray, 2) || analysis(strArray, 3)) {
|
||||
AclUtils.verify(remoteAddr, index - 1);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int j = 0; j < index; j++) {
|
||||
sb.append(strArray[j].trim()).append(".");
|
||||
}
|
||||
this.head = sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean analysis(String[] strArray, int index) {
|
||||
String value = strArray[index].trim();
|
||||
this.index = index;
|
||||
if ("*".equals(value)) {
|
||||
setValue(0, 255);
|
||||
} else if (AclUtils.isMinus(value)) {
|
||||
if (value.indexOf("-") == 0) {
|
||||
throw new AclException(String.format("RangeRemoteAddressStrategy netAddress examine scope Exception value %s ", value));
|
||||
|
||||
}
|
||||
String[] valueArray = StringUtils.split(value, "-");
|
||||
this.start = Integer.parseInt(valueArray[0]);
|
||||
this.end = Integer.parseInt(valueArray[1]);
|
||||
if (!(AclUtils.isScope(end) && AclUtils.isScope(start) && start <= end)) {
|
||||
throw new AclException(String.format("RangeRemoteAddressStrategy netAddress examine scope Exception start is %s , end is %s", start, end));
|
||||
}
|
||||
}
|
||||
return this.end > 0;
|
||||
}
|
||||
|
||||
private boolean ipv6Analysis(String[] strArray, int index) {
|
||||
String value = strArray[index].trim();
|
||||
this.index = index;
|
||||
if ("*".equals(value)) {
|
||||
int min = Integer.parseInt("0", 16);
|
||||
int max = Integer.parseInt("ffff", 16);
|
||||
setValue(min, max);
|
||||
} else if (AclUtils.isMinus(value)) {
|
||||
if (value.indexOf("-") == 0) {
|
||||
throw new AclException(String.format("RangeRemoteAddressStrategy netAddress examine scope Exception value %s ", value));
|
||||
}
|
||||
String[] valueArray = StringUtils.split(value, "-");
|
||||
this.start = Integer.parseInt(valueArray[0], 16);
|
||||
this.end = Integer.parseInt(valueArray[1], 16);
|
||||
if (!(AclUtils.isIPv6Scope(end) && AclUtils.isIPv6Scope(start) && start <= end)) {
|
||||
throw new AclException(String.format("RangeRemoteAddressStrategy netAddress examine scope Exception start is %s , end is %s", start, end));
|
||||
}
|
||||
}
|
||||
return this.end > 0;
|
||||
}
|
||||
|
||||
private void setValue(int start, int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(PlainAccessResource plainAccessResource) {
|
||||
String netAddress = plainAccessResource.getWhiteRemoteAddress();
|
||||
InetAddressValidator validator = InetAddressValidator.getInstance();
|
||||
if (validator.isValidInet4Address(netAddress)) {
|
||||
if (netAddress.startsWith(this.head)) {
|
||||
String value;
|
||||
if (index == 3) {
|
||||
value = netAddress.substring(this.head.length());
|
||||
} else if (index == 2) {
|
||||
value = netAddress.substring(this.head.length(), netAddress.lastIndexOf('.'));
|
||||
} else {
|
||||
value = netAddress.substring(this.head.length(), netAddress.lastIndexOf('.', netAddress.lastIndexOf('.') - 1));
|
||||
}
|
||||
Integer address = Integer.valueOf(value);
|
||||
return address >= this.start && address <= this.end;
|
||||
}
|
||||
} else if (validator.isValidInet6Address(netAddress)) {
|
||||
netAddress = AclUtils.expandIP(netAddress, 8).toUpperCase();
|
||||
if (netAddress.startsWith(this.head)) {
|
||||
String value = netAddress.substring(5 * index, 5 * index + 4);
|
||||
Integer address = Integer.parseInt(value, 16);
|
||||
return address >= this.start && address <= this.end;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import org.apache.rocketmq.acl.common.AclClientRPCHook;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.SessionCredentials;
|
||||
import org.apache.rocketmq.acl.plain.AclTestHelper;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessResource;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessValidator;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
import org.apache.rocketmq.remoting.protocol.header.PullMessageRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeader;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RemotingClientAccessTest {
|
||||
|
||||
private PlainAccessValidator plainAccessValidator;
|
||||
private AclClientRPCHook aclClient;
|
||||
private SessionCredentials sessionCredentials;
|
||||
|
||||
private File confHome;
|
||||
|
||||
private String clientAddress = "10.7.1.3";
|
||||
|
||||
@Before
|
||||
public void init() throws IOException {
|
||||
String folder = "access_acl_conf";
|
||||
confHome = AclTestHelper.copyResources(folder, true);
|
||||
System.setProperty("rocketmq.home.dir", confHome.getAbsolutePath());
|
||||
System.setProperty("rocketmq.acl.plain.file", "/access_acl_conf/acl/plain_acl.yml".replace("/", File.separator));
|
||||
|
||||
plainAccessValidator = new PlainAccessValidator();
|
||||
sessionCredentials = new SessionCredentials();
|
||||
sessionCredentials.setAccessKey("rocketmq3");
|
||||
sessionCredentials.setSecretKey("12345678");
|
||||
aclClient = new AclClientRPCHook(sessionCredentials);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
AclTestHelper.recursiveDelete(confHome);
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void testProduceDenyTopic() {
|
||||
SendMessageRequestHeader messageRequestHeader = new SendMessageRequestHeader();
|
||||
messageRequestHeader.setTopic("topicD");
|
||||
RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, messageRequestHeader);
|
||||
aclClient.doBeforeRequest(clientAddress, remotingCommand);
|
||||
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(RemotingCommand.decode(buf), clientAddress);
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw IOException");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProduceAuthorizedTopic() {
|
||||
SendMessageRequestHeader messageRequestHeader = new SendMessageRequestHeader();
|
||||
messageRequestHeader.setTopic("topicA");
|
||||
RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, messageRequestHeader);
|
||||
aclClient.doBeforeRequest(clientAddress, remotingCommand);
|
||||
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(RemotingCommand.decode(buf), clientAddress);
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw IOException");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void testConsumeDenyTopic() {
|
||||
PullMessageRequestHeader pullMessageRequestHeader = new PullMessageRequestHeader();
|
||||
pullMessageRequestHeader.setTopic("topicD");
|
||||
pullMessageRequestHeader.setConsumerGroup("groupB");
|
||||
RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.PULL_MESSAGE, pullMessageRequestHeader);
|
||||
aclClient.doBeforeRequest("", remotingCommand);
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(RemotingCommand.decode(buf), "123.4.5.6");
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw IOException");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumeAuthorizedTopic() {
|
||||
PullMessageRequestHeader pullMessageRequestHeader = new PullMessageRequestHeader();
|
||||
pullMessageRequestHeader.setTopic("topicB");
|
||||
pullMessageRequestHeader.setConsumerGroup("groupB");
|
||||
RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.PULL_MESSAGE, pullMessageRequestHeader);
|
||||
aclClient.doBeforeRequest("", remotingCommand);
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(RemotingCommand.decode(buf), "123.4.5.6");
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw IOException");
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void testConsumeInDeniedGroup() {
|
||||
PullMessageRequestHeader pullMessageRequestHeader = new PullMessageRequestHeader();
|
||||
pullMessageRequestHeader.setTopic("topicB");
|
||||
pullMessageRequestHeader.setConsumerGroup("groupD");
|
||||
RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.PULL_MESSAGE, pullMessageRequestHeader);
|
||||
aclClient.doBeforeRequest("", remotingCommand);
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(RemotingCommand.decode(buf), "123.4.5.6");
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw IOException");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumeInAuthorizedGroup() {
|
||||
PullMessageRequestHeader pullMessageRequestHeader = new PullMessageRequestHeader();
|
||||
pullMessageRequestHeader.setTopic("topicB");
|
||||
pullMessageRequestHeader.setConsumerGroup("groupB");
|
||||
RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.PULL_MESSAGE, pullMessageRequestHeader);
|
||||
aclClient.doBeforeRequest("", remotingCommand);
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(RemotingCommand.decode(buf), "123.4.5.6");
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw IOException");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class AuthorizationHeaderTest {
|
||||
|
||||
private static final String AUTH_HEADER = "Signature Credential=1234567890/test, SignedHeaders=host, Signature=1234567890";
|
||||
private AuthorizationHeader authorizationHeader;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
authorizationHeader = new AuthorizationHeader(AUTH_HEADER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMethod() {
|
||||
Assert.assertEquals("Signature", authorizationHeader.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAccessKey() {
|
||||
Assert.assertEquals("1234567890", authorizationHeader.getAccessKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSignedHeaders() {
|
||||
String[] expectedHeaders = {"host"};
|
||||
Assert.assertArrayEquals(expectedHeaders, authorizationHeader.getSignedHeaders());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSignature() {
|
||||
Assert.assertEquals("EjRWeJA=", authorizationHeader.getSignature());
|
||||
}
|
||||
|
||||
@Test(expected = Exception.class)
|
||||
public void testInvalidAuthorizationHeader() throws Exception {
|
||||
new AuthorizationHeader("Invalid Header");
|
||||
}
|
||||
|
||||
@Test(expected = Exception.class)
|
||||
public void testMalformedAuthorizationHeader() throws Exception {
|
||||
new AuthorizationHeader("Malformed, Header");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessResource;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PermissionTest {
|
||||
|
||||
@Test
|
||||
public void fromStringGetPermissionTest() {
|
||||
byte perm = Permission.parsePermFromString("PUB");
|
||||
Assert.assertEquals(perm, Permission.PUB);
|
||||
|
||||
perm = Permission.parsePermFromString("SUB");
|
||||
Assert.assertEquals(perm, Permission.SUB);
|
||||
|
||||
perm = Permission.parsePermFromString("PUB|SUB");
|
||||
Assert.assertEquals(perm, Permission.PUB | Permission.SUB);
|
||||
|
||||
perm = Permission.parsePermFromString("SUB|PUB");
|
||||
Assert.assertEquals(perm, Permission.PUB | Permission.SUB);
|
||||
|
||||
perm = Permission.parsePermFromString("DENY");
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
perm = Permission.parsePermFromString("1");
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
perm = Permission.parsePermFromString(null);
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkPermissionTest() {
|
||||
boolean boo = Permission.checkPermission(Permission.DENY, Permission.DENY);
|
||||
Assert.assertFalse(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.PUB, Permission.PUB);
|
||||
Assert.assertTrue(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.SUB, Permission.SUB);
|
||||
Assert.assertTrue(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.PUB, (byte) (Permission.PUB | Permission.SUB));
|
||||
Assert.assertTrue(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.SUB, (byte) (Permission.PUB | Permission.SUB));
|
||||
Assert.assertTrue(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.ANY, (byte) (Permission.PUB | Permission.SUB));
|
||||
Assert.assertTrue(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.ANY, Permission.SUB);
|
||||
Assert.assertTrue(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.ANY, Permission.PUB);
|
||||
Assert.assertTrue(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.DENY, Permission.ANY);
|
||||
Assert.assertFalse(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.DENY, Permission.PUB);
|
||||
Assert.assertFalse(boo);
|
||||
|
||||
boo = Permission.checkPermission(Permission.DENY, Permission.SUB);
|
||||
Assert.assertFalse(boo);
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void setTopicPermTest() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
Map<String, Byte> resourcePermMap = plainAccessResource.getResourcePermMap();
|
||||
|
||||
Permission.parseResourcePerms(plainAccessResource, false, null);
|
||||
Assert.assertNull(resourcePermMap);
|
||||
|
||||
List<String> groups = new ArrayList<>();
|
||||
Permission.parseResourcePerms(plainAccessResource, false, groups);
|
||||
Assert.assertNull(resourcePermMap);
|
||||
|
||||
groups.add("groupA=DENY");
|
||||
groups.add("groupB=PUB|SUB");
|
||||
groups.add("groupC=PUB");
|
||||
Permission.parseResourcePerms(plainAccessResource, false, groups);
|
||||
resourcePermMap = plainAccessResource.getResourcePermMap();
|
||||
|
||||
byte perm = resourcePermMap.get(PlainAccessResource.getRetryTopic("groupA"));
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
perm = resourcePermMap.get(PlainAccessResource.getRetryTopic("groupB"));
|
||||
Assert.assertEquals(perm,Permission.PUB | Permission.SUB);
|
||||
|
||||
perm = resourcePermMap.get(PlainAccessResource.getRetryTopic("groupC"));
|
||||
Assert.assertEquals(perm, Permission.PUB);
|
||||
|
||||
List<String> topics = new ArrayList<>();
|
||||
topics.add("topicA=DENY");
|
||||
topics.add("topicB=PUB|SUB");
|
||||
topics.add("topicC=PUB");
|
||||
|
||||
Permission.parseResourcePerms(plainAccessResource, true, topics);
|
||||
|
||||
perm = resourcePermMap.get("topicA");
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
perm = resourcePermMap.get("topicB");
|
||||
Assert.assertEquals(perm, Permission.PUB | Permission.SUB);
|
||||
|
||||
perm = resourcePermMap.get("topicC");
|
||||
Assert.assertEquals(perm, Permission.PUB);
|
||||
|
||||
List<String> erron = new ArrayList<>();
|
||||
erron.add("");
|
||||
Permission.parseResourcePerms(plainAccessResource, false, erron);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkAdminCodeTest() {
|
||||
Set<Integer> code = new HashSet<>();
|
||||
code.add(RequestCode.UPDATE_AND_CREATE_TOPIC);
|
||||
code.add(RequestCode.UPDATE_BROKER_CONFIG);
|
||||
code.add(RequestCode.DELETE_TOPIC_IN_BROKER);
|
||||
code.add(RequestCode.UPDATE_AND_CREATE_SUBSCRIPTIONGROUP);
|
||||
code.add(RequestCode.DELETE_SUBSCRIPTIONGROUP);
|
||||
code.add(RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC);
|
||||
code.add(RequestCode.UPDATE_AND_CREATE_ACL_CONFIG);
|
||||
code.add(RequestCode.DELETE_ACL_CONFIG);
|
||||
code.add(RequestCode.GET_BROKER_CLUSTER_ACL_INFO);
|
||||
|
||||
for (int i = 0; i < 400; i++) {
|
||||
boolean boo = Permission.needAdminPerm(i);
|
||||
if (boo) {
|
||||
Assert.assertTrue(code.contains(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AclExceptionTest() {
|
||||
AclException aclException = new AclException("CAL_SIGNATURE_FAILED",10015);
|
||||
AclException aclExceptionWithMessage = new AclException("CAL_SIGNATURE_FAILED",10015,"CAL_SIGNATURE_FAILED Exception");
|
||||
Assert.assertEquals(aclException.getCode(),10015);
|
||||
Assert.assertEquals(aclExceptionWithMessage.getStatus(),"CAL_SIGNATURE_FAILED");
|
||||
aclException.setCode(10016);
|
||||
Assert.assertEquals(aclException.getCode(),10016);
|
||||
aclException.setStatus("netAddress examine scope Exception netAddress");
|
||||
Assert.assertEquals(aclException.getStatus(),"netAddress examine scope Exception netAddress");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkResourcePermsNormalTest() {
|
||||
Permission.checkResourcePerms(null);
|
||||
Permission.checkResourcePerms(new ArrayList<>());
|
||||
Permission.checkResourcePerms(Arrays.asList("topicA=PUB"));
|
||||
Permission.checkResourcePerms(Arrays.asList("topicA=PUB", "topicB=SUB", "topicC=PUB|SUB"));
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void checkResourcePermsExceptionTest1() {
|
||||
Permission.checkResourcePerms(Arrays.asList("topicA"));
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void checkResourcePermsExceptionTest2() {
|
||||
Permission.checkResourcePerms(Arrays.asList("topicA="));
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void checkResourcePermsExceptionTest3() {
|
||||
Permission.checkResourcePerms(Arrays.asList("topicA=DENY1"));
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.UUID;
|
||||
import java.util.Iterator;
|
||||
import org.junit.Assert;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
|
||||
public final class AclTestHelper {
|
||||
private AclTestHelper() {
|
||||
}
|
||||
|
||||
private static void copyTo(String path, InputStream src, File dstDir, String flag, boolean into)
|
||||
throws IOException {
|
||||
Preconditions.checkNotNull(flag);
|
||||
Iterator<String> iterator = Splitter.on(File.separatorChar).split(path).iterator();
|
||||
boolean found = false;
|
||||
File dir = dstDir;
|
||||
while (iterator.hasNext()) {
|
||||
String current = iterator.next();
|
||||
if (!found && flag.equals(current)) {
|
||||
found = true;
|
||||
if (into) {
|
||||
dir = new File(dir, flag);
|
||||
if (!dir.exists()) {
|
||||
Assert.assertTrue(dir.mkdirs());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (!iterator.hasNext()) {
|
||||
dir = new File(dir, current);
|
||||
} else {
|
||||
dir = new File(dir, current);
|
||||
if (!dir.exists()) {
|
||||
Assert.assertTrue(dir.mkdir());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertTrue(dir.createNewFile());
|
||||
byte[] buffer = new byte[4096];
|
||||
BufferedInputStream bis = new BufferedInputStream(src);
|
||||
int len = 0;
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(dir.toPath()))) {
|
||||
while ((len = bis.read(buffer)) > 0) {
|
||||
bos.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void recursiveDelete(File file) {
|
||||
if (file.isFile()) {
|
||||
file.delete();
|
||||
} else {
|
||||
File[] files = file.listFiles();
|
||||
if (null != files) {
|
||||
for (File f : files) {
|
||||
recursiveDelete(f);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static File copyResources(String folder) throws IOException {
|
||||
return copyResources(folder, false);
|
||||
}
|
||||
|
||||
public static File copyResources(String folder, boolean into) throws IOException {
|
||||
File home = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString().replace('-', '_'));
|
||||
if (!home.exists()) {
|
||||
Assert.assertTrue(home.mkdirs());
|
||||
}
|
||||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(AclTestHelper.class.getClassLoader());
|
||||
Resource[] resources = resolver.getResources(String.format("classpath:%s/**/*", folder));
|
||||
for (Resource resource : resources) {
|
||||
if (!resource.isReadable()) {
|
||||
continue;
|
||||
}
|
||||
String description = resource.getDescription();
|
||||
int start = description.indexOf('[');
|
||||
int end = description.lastIndexOf(']');
|
||||
String path = description.substring(start + 1, end);
|
||||
try (InputStream inputStream = resource.getInputStream()) {
|
||||
copyTo(path, inputStream, home, folder, into);
|
||||
}
|
||||
}
|
||||
return home;
|
||||
}
|
||||
}
|
||||
@@ -1,311 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import org.apache.rocketmq.acl.common.AclClientRPCHook;
|
||||
import org.apache.rocketmq.acl.common.AclConstants;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.AclUtils;
|
||||
import org.apache.rocketmq.acl.common.SessionCredentials;
|
||||
import org.apache.rocketmq.common.AclConfig;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
import org.apache.rocketmq.remoting.protocol.header.PullMessageRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeaderV2;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p> In this class, we'll test the following scenarios, each containing several consecutive operations on ACL,
|
||||
* <p> like updating and deleting ACL, changing config files and checking validations.
|
||||
* <p> Case 1: Only conf/plain_acl.yml exists;
|
||||
* <p> Case 2: Only conf/acl/plain_acl.yml exists;
|
||||
* <p> Case 3: Both conf/plain_acl.yml and conf/acl/plain_acl.yml exists.
|
||||
*/
|
||||
public class PlainAccessControlFlowTest {
|
||||
public static final String DEFAULT_TOPIC = "topic-acl";
|
||||
|
||||
public static final String DEFAULT_GROUP = "GID_acl";
|
||||
|
||||
public static final String DEFAULT_PRODUCER_AK = "ak11111";
|
||||
public static final String DEFAULT_PRODUCER_SK = "1234567";
|
||||
|
||||
public static final String DEFAULT_CONSUMER_SK = "7654321";
|
||||
public static final String DEFAULT_CONSUMER_AK = "ak22222";
|
||||
|
||||
public static final String DEFAULT_GLOBAL_WHITE_ADDR = "172.16.123.123";
|
||||
public static final List<String> DEFAULT_GLOBAL_WHITE_ADDRS_LIST = Collections.singletonList(DEFAULT_GLOBAL_WHITE_ADDR);
|
||||
|
||||
@Test
|
||||
public void testEmptyAclFolderCase() throws NoSuchFieldException, IllegalAccessException,
|
||||
IOException {
|
||||
String folder = "empty_acl_folder_conf";
|
||||
File home = AclTestHelper.copyResources(folder);
|
||||
System.setProperty("rocketmq.home.dir", home.getAbsolutePath());
|
||||
PlainAccessValidator plainAccessValidator = new PlainAccessValidator();
|
||||
checkDefaultAclFileExists();
|
||||
testValidationAfterConsecutiveUpdates(plainAccessValidator);
|
||||
testValidationAfterConfigFileChanged(plainAccessValidator);
|
||||
AclTestHelper.recursiveDelete(home);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyAclFolderCase() throws NoSuchFieldException, IllegalAccessException, IOException {
|
||||
String folder = "only_acl_folder_conf";
|
||||
File home = AclTestHelper.copyResources(folder);
|
||||
System.setProperty("rocketmq.home.dir", home.getAbsolutePath());
|
||||
PlainAccessValidator plainAccessValidator = new PlainAccessValidator();
|
||||
checkDefaultAclFileExists();
|
||||
testValidationAfterConsecutiveUpdates(plainAccessValidator);
|
||||
testValidationAfterConfigFileChanged(plainAccessValidator);
|
||||
AclTestHelper.recursiveDelete(home);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBothAclFileAndFolderCase() throws NoSuchFieldException, IllegalAccessException,
|
||||
IOException {
|
||||
String folder = "both_acl_file_folder_conf";
|
||||
File root = AclTestHelper.copyResources(folder);
|
||||
System.setProperty("rocketmq.home.dir", root.getAbsolutePath());
|
||||
PlainAccessValidator plainAccessValidator = new PlainAccessValidator();
|
||||
checkDefaultAclFileExists();
|
||||
testValidationAfterConsecutiveUpdates(plainAccessValidator);
|
||||
testValidationAfterConfigFileChanged(plainAccessValidator);
|
||||
AclTestHelper.recursiveDelete(root);
|
||||
}
|
||||
|
||||
private void testValidationAfterConfigFileChanged(
|
||||
PlainAccessValidator plainAccessValidator) throws NoSuchFieldException, IllegalAccessException {
|
||||
PlainAccessConfig producerAccessConfig = generateProducerAccessConfig();
|
||||
PlainAccessConfig consumerAccessConfig = generateConsumerAccessConfig();
|
||||
List<PlainAccessConfig> plainAccessConfigList = new LinkedList<>();
|
||||
plainAccessConfigList.add(producerAccessConfig);
|
||||
plainAccessConfigList.add(consumerAccessConfig);
|
||||
PlainAccessData ymlMap = new PlainAccessData();
|
||||
ymlMap.setAccounts(plainAccessConfigList);
|
||||
|
||||
// write prepared PlainAccessConfigs to file
|
||||
final String aclConfigFile = System.getProperty("rocketmq.home.dir") + File.separator + "conf/plain_acl.yml";
|
||||
AclUtils.writeDataObject(aclConfigFile, ymlMap);
|
||||
|
||||
loadConfigFile(plainAccessValidator, aclConfigFile);
|
||||
|
||||
// check if added successfully
|
||||
final AclConfig allAclConfig = plainAccessValidator.getAllAclConfig();
|
||||
final List<PlainAccessConfig> plainAccessConfigs = allAclConfig.getPlainAccessConfigs();
|
||||
checkPlainAccessConfig(producerAccessConfig, plainAccessConfigs);
|
||||
checkPlainAccessConfig(consumerAccessConfig, plainAccessConfigs);
|
||||
|
||||
//delete consumer account
|
||||
plainAccessConfigList.remove(consumerAccessConfig);
|
||||
AclUtils.writeDataObject(aclConfigFile, ymlMap);
|
||||
|
||||
loadConfigFile(plainAccessValidator, aclConfigFile);
|
||||
|
||||
// sending messages will be successful using prepared credentials
|
||||
SessionCredentials producerCredential = new SessionCredentials(DEFAULT_PRODUCER_AK, DEFAULT_PRODUCER_SK);
|
||||
AclClientRPCHook producerHook = new AclClientRPCHook(producerCredential);
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE, DEFAULT_TOPIC, producerHook, "", plainAccessValidator);
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE_V2, DEFAULT_TOPIC, producerHook, "", plainAccessValidator);
|
||||
|
||||
// consuming messages will be failed for account has been deleted
|
||||
SessionCredentials consumerCredential = new SessionCredentials(DEFAULT_CONSUMER_AK, DEFAULT_CONSUMER_SK);
|
||||
AclClientRPCHook consumerHook = new AclClientRPCHook(consumerCredential);
|
||||
boolean isConsumeFailed = false;
|
||||
try {
|
||||
validatePullMessage(DEFAULT_TOPIC, DEFAULT_GROUP, consumerHook, "", plainAccessValidator);
|
||||
} catch (AclException e) {
|
||||
isConsumeFailed = true;
|
||||
}
|
||||
Assert.assertTrue("Message should not be consumed after account deleted", isConsumeFailed);
|
||||
|
||||
}
|
||||
|
||||
private void testValidationAfterConsecutiveUpdates(
|
||||
PlainAccessValidator plainAccessValidator) throws NoSuchFieldException, IllegalAccessException {
|
||||
PlainAccessConfig producerAccessConfig = generateProducerAccessConfig();
|
||||
plainAccessValidator.updateAccessConfig(producerAccessConfig);
|
||||
|
||||
PlainAccessConfig consumerAccessConfig = generateConsumerAccessConfig();
|
||||
plainAccessValidator.updateAccessConfig(consumerAccessConfig);
|
||||
|
||||
plainAccessValidator.updateGlobalWhiteAddrsConfig(DEFAULT_GLOBAL_WHITE_ADDRS_LIST, null);
|
||||
|
||||
// check if the above config updated successfully
|
||||
final AclConfig allAclConfig = plainAccessValidator.getAllAclConfig();
|
||||
final List<PlainAccessConfig> plainAccessConfigs = allAclConfig.getPlainAccessConfigs();
|
||||
checkPlainAccessConfig(producerAccessConfig, plainAccessConfigs);
|
||||
checkPlainAccessConfig(consumerAccessConfig, plainAccessConfigs);
|
||||
|
||||
Assert.assertEquals(DEFAULT_GLOBAL_WHITE_ADDRS_LIST, allAclConfig.getGlobalWhiteAddrs());
|
||||
|
||||
// check sending and consuming messages
|
||||
SessionCredentials producerCredential = new SessionCredentials(DEFAULT_PRODUCER_AK, DEFAULT_PRODUCER_SK);
|
||||
AclClientRPCHook producerHook = new AclClientRPCHook(producerCredential);
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE, DEFAULT_TOPIC, producerHook, "", plainAccessValidator);
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE_V2, DEFAULT_TOPIC, producerHook, "", plainAccessValidator);
|
||||
|
||||
SessionCredentials consumerCredential = new SessionCredentials(DEFAULT_CONSUMER_AK, DEFAULT_CONSUMER_SK);
|
||||
AclClientRPCHook consumerHook = new AclClientRPCHook(consumerCredential);
|
||||
validatePullMessage(DEFAULT_TOPIC, DEFAULT_GROUP, consumerHook, "", plainAccessValidator);
|
||||
|
||||
// load from file
|
||||
loadConfigFile(plainAccessValidator,
|
||||
System.getProperty("rocketmq.home.dir") + File.separator + "conf/plain_acl.yml");
|
||||
SessionCredentials unmatchedCredential = new SessionCredentials("non_exists_sk", "non_exists_sk");
|
||||
AclClientRPCHook dummyHook = new AclClientRPCHook(unmatchedCredential);
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE, DEFAULT_TOPIC, dummyHook, DEFAULT_GLOBAL_WHITE_ADDR, plainAccessValidator);
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE_V2, DEFAULT_TOPIC, dummyHook, DEFAULT_GLOBAL_WHITE_ADDR, plainAccessValidator);
|
||||
validatePullMessage(DEFAULT_TOPIC, DEFAULT_GROUP, dummyHook, DEFAULT_GLOBAL_WHITE_ADDR, plainAccessValidator);
|
||||
|
||||
//recheck after reloading
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE, DEFAULT_TOPIC, producerHook, "", plainAccessValidator);
|
||||
validateSendMessage(RequestCode.SEND_MESSAGE_V2, DEFAULT_TOPIC, producerHook, "", plainAccessValidator);
|
||||
validatePullMessage(DEFAULT_TOPIC, DEFAULT_GROUP, consumerHook, "", plainAccessValidator);
|
||||
|
||||
}
|
||||
|
||||
private void loadConfigFile(PlainAccessValidator plainAccessValidator,
|
||||
String configFileName) throws NoSuchFieldException, IllegalAccessException {
|
||||
Class<PlainAccessValidator> clazz = PlainAccessValidator.class;
|
||||
Field f = clazz.getDeclaredField("aclPlugEngine");
|
||||
f.setAccessible(true);
|
||||
PlainPermissionManager aclPlugEngine = (PlainPermissionManager) f.get(plainAccessValidator);
|
||||
aclPlugEngine.load(configFileName);
|
||||
}
|
||||
|
||||
private PlainAccessConfig generateConsumerAccessConfig() {
|
||||
PlainAccessConfig plainAccessConfig2 = new PlainAccessConfig();
|
||||
plainAccessConfig2.setAccessKey(DEFAULT_CONSUMER_AK);
|
||||
plainAccessConfig2.setSecretKey(DEFAULT_CONSUMER_SK);
|
||||
plainAccessConfig2.setAdmin(false);
|
||||
plainAccessConfig2.setDefaultTopicPerm(AclConstants.DENY);
|
||||
plainAccessConfig2.setDefaultGroupPerm(AclConstants.DENY);
|
||||
plainAccessConfig2.setTopicPerms(Collections.singletonList(DEFAULT_TOPIC + "=" + AclConstants.SUB));
|
||||
plainAccessConfig2.setGroupPerms(Collections.singletonList(DEFAULT_GROUP + "=" + AclConstants.SUB));
|
||||
return plainAccessConfig2;
|
||||
}
|
||||
|
||||
private PlainAccessConfig generateProducerAccessConfig() {
|
||||
PlainAccessConfig plainAccessConfig = new PlainAccessConfig();
|
||||
plainAccessConfig.setAccessKey(DEFAULT_PRODUCER_AK);
|
||||
plainAccessConfig.setSecretKey(DEFAULT_PRODUCER_SK);
|
||||
plainAccessConfig.setAdmin(false);
|
||||
plainAccessConfig.setDefaultTopicPerm(AclConstants.DENY);
|
||||
plainAccessConfig.setDefaultGroupPerm(AclConstants.DENY);
|
||||
plainAccessConfig.setTopicPerms(Collections.singletonList(DEFAULT_TOPIC + "=" + AclConstants.PUB));
|
||||
return plainAccessConfig;
|
||||
}
|
||||
|
||||
public void validatePullMessage(String topic,
|
||||
String group,
|
||||
AclClientRPCHook aclClientRPCHook,
|
||||
String remoteAddr,
|
||||
PlainAccessValidator plainAccessValidator) {
|
||||
PullMessageRequestHeader pullMessageRequestHeader = new PullMessageRequestHeader();
|
||||
pullMessageRequestHeader.setTopic(topic);
|
||||
pullMessageRequestHeader.setConsumerGroup(group);
|
||||
RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.PULL_MESSAGE,
|
||||
pullMessageRequestHeader);
|
||||
aclClientRPCHook.doBeforeRequest(remoteAddr, remotingCommand);
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(
|
||||
RemotingCommand.decode(buf), remoteAddr);
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw RemotingCommandException");
|
||||
}
|
||||
}
|
||||
|
||||
public void validateSendMessage(int requestCode,
|
||||
String topic,
|
||||
AclClientRPCHook aclClientRPCHook,
|
||||
String remoteAddr,
|
||||
PlainAccessValidator plainAccessValidator) {
|
||||
SendMessageRequestHeader messageRequestHeader = new SendMessageRequestHeader();
|
||||
messageRequestHeader.setTopic(topic);
|
||||
RemotingCommand remotingCommand;
|
||||
if (RequestCode.SEND_MESSAGE == requestCode) {
|
||||
remotingCommand = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, messageRequestHeader);
|
||||
} else {
|
||||
remotingCommand = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE_V2,
|
||||
SendMessageRequestHeaderV2.createSendMessageRequestHeaderV2(messageRequestHeader));
|
||||
}
|
||||
|
||||
aclClientRPCHook.doBeforeRequest(remoteAddr, remotingCommand);
|
||||
|
||||
ByteBuffer buf = remotingCommand.encodeHeader();
|
||||
buf.getInt();
|
||||
buf = ByteBuffer.allocate(buf.limit() - buf.position()).put(buf);
|
||||
buf.position(0);
|
||||
try {
|
||||
PlainAccessResource accessResource = (PlainAccessResource) plainAccessValidator.parse(
|
||||
RemotingCommand.decode(buf), remoteAddr);
|
||||
plainAccessValidator.validate(accessResource);
|
||||
} catch (RemotingCommandException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Should not throw RemotingCommandException");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPlainAccessConfig(final PlainAccessConfig plainAccessConfig,
|
||||
final List<PlainAccessConfig> plainAccessConfigs) {
|
||||
for (PlainAccessConfig config : plainAccessConfigs) {
|
||||
if (config.getAccessKey().equals(plainAccessConfig.getAccessKey())) {
|
||||
Assert.assertEquals(plainAccessConfig.getSecretKey(), config.getSecretKey());
|
||||
Assert.assertEquals(plainAccessConfig.isAdmin(), config.isAdmin());
|
||||
Assert.assertEquals(plainAccessConfig.getDefaultGroupPerm(), config.getDefaultGroupPerm());
|
||||
Assert.assertEquals(plainAccessConfig.getDefaultGroupPerm(), config.getDefaultGroupPerm());
|
||||
Assert.assertEquals(plainAccessConfig.getWhiteRemoteAddress(), config.getWhiteRemoteAddress());
|
||||
if (null != plainAccessConfig.getTopicPerms()) {
|
||||
Assert.assertNotNull(config.getTopicPerms());
|
||||
Assert.assertTrue(config.getTopicPerms().containsAll(plainAccessConfig.getTopicPerms()));
|
||||
}
|
||||
if (null != plainAccessConfig.getGroupPerms()) {
|
||||
Assert.assertNotNull(config.getGroupPerms());
|
||||
Assert.assertTrue(config.getGroupPerms().containsAll(plainAccessConfig.getGroupPerms()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDefaultAclFileExists() {
|
||||
boolean isExists = Files.exists(Paths.get(System.getProperty("rocketmq.home.dir")
|
||||
+ File.separator + "conf" + File.separator + "plain_acl.yml"));
|
||||
Assert.assertTrue("default acl config file should exist", isExists);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import apache.rocketmq.v2.RecallMessageRequest;
|
||||
import apache.rocketmq.v2.Resource;
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import org.apache.rocketmq.acl.common.AuthenticationHeader;
|
||||
import org.apache.rocketmq.acl.common.Permission;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
import org.apache.rocketmq.remoting.protocol.header.RecallMessageRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeaderV2;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PlainAccessResourceTest {
|
||||
public static final String DEFAULT_TOPIC = "topic-acl";
|
||||
public static final String DEFAULT_PRODUCER_GROUP = "PID_acl";
|
||||
public static final String DEFAULT_CONSUMER_GROUP = "GID_acl";
|
||||
public static final String DEFAULT_REMOTE_ADDR = "192.128.1.1";
|
||||
public static final String AUTH_HEADER =
|
||||
"Signature Credential=1234567890/test, SignedHeaders=host, Signature=1234567890";
|
||||
|
||||
@Test
|
||||
public void testParseSendNormal() {
|
||||
SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
|
||||
requestHeader.setTopic(DEFAULT_TOPIC);
|
||||
requestHeader.setProducerGroup(DEFAULT_PRODUCER_GROUP);
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, requestHeader);
|
||||
request.makeCustomHeaderToNet();
|
||||
PlainAccessResource accessResource = PlainAccessResource.parse(request, DEFAULT_REMOTE_ADDR);
|
||||
|
||||
Map<String, Byte> permMap = new HashMap<>(1);
|
||||
permMap.put(DEFAULT_TOPIC, Permission.PUB);
|
||||
|
||||
Assert.assertEquals(permMap, accessResource.getResourcePermMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSendRetry() {
|
||||
SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
|
||||
requestHeader.setTopic(MixAll.getRetryTopic(DEFAULT_CONSUMER_GROUP));
|
||||
requestHeader.setProducerGroup(DEFAULT_PRODUCER_GROUP);
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, requestHeader);
|
||||
request.makeCustomHeaderToNet();
|
||||
PlainAccessResource accessResource = PlainAccessResource.parse(request, DEFAULT_REMOTE_ADDR);
|
||||
|
||||
Map<String, Byte> permMap = new HashMap<>(1);
|
||||
permMap.put(MixAll.getRetryTopic(DEFAULT_CONSUMER_GROUP), Permission.SUB);
|
||||
|
||||
Assert.assertEquals(permMap, accessResource.getResourcePermMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSendNormalV2() {
|
||||
SendMessageRequestHeaderV2 requestHeaderV2 = new SendMessageRequestHeaderV2();
|
||||
requestHeaderV2.setB(DEFAULT_TOPIC);
|
||||
requestHeaderV2.setA(DEFAULT_PRODUCER_GROUP);
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE_V2, requestHeaderV2);
|
||||
request.makeCustomHeaderToNet();
|
||||
PlainAccessResource accessResource = PlainAccessResource.parse(request, DEFAULT_REMOTE_ADDR);
|
||||
|
||||
Map<String, Byte> permMap = new HashMap<>(1);
|
||||
permMap.put(DEFAULT_TOPIC, Permission.PUB);
|
||||
|
||||
Assert.assertEquals(permMap, accessResource.getResourcePermMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSendRetryV2() {
|
||||
SendMessageRequestHeaderV2 requestHeaderV2 = new SendMessageRequestHeaderV2();
|
||||
requestHeaderV2.setB(MixAll.getRetryTopic(DEFAULT_CONSUMER_GROUP));
|
||||
requestHeaderV2.setA(DEFAULT_PRODUCER_GROUP);
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE_V2, requestHeaderV2);
|
||||
request.makeCustomHeaderToNet();
|
||||
PlainAccessResource accessResource = PlainAccessResource.parse(request, DEFAULT_REMOTE_ADDR);
|
||||
|
||||
Map<String, Byte> permMap = new HashMap<>(1);
|
||||
permMap.put(MixAll.getRetryTopic(DEFAULT_CONSUMER_GROUP), Permission.SUB);
|
||||
|
||||
Assert.assertEquals(permMap, accessResource.getResourcePermMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseRecallMessage() {
|
||||
// remoting
|
||||
RecallMessageRequestHeader requestHeader = new RecallMessageRequestHeader();
|
||||
requestHeader.setTopic(DEFAULT_TOPIC);
|
||||
requestHeader.setProducerGroup(DEFAULT_PRODUCER_GROUP);
|
||||
requestHeader.setRecallHandle("handle");
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.RECALL_MESSAGE, requestHeader);
|
||||
request.makeCustomHeaderToNet();
|
||||
|
||||
PlainAccessResource accessResource = PlainAccessResource.parse(request, DEFAULT_REMOTE_ADDR);
|
||||
Assert.assertTrue(Permission.PUB == accessResource.getResourcePermMap().get(DEFAULT_TOPIC));
|
||||
|
||||
// grpc
|
||||
GeneratedMessageV3 grpcRequest = RecallMessageRequest.newBuilder()
|
||||
.setTopic(Resource.newBuilder().setName(DEFAULT_TOPIC).build())
|
||||
.setRecallHandle("handle")
|
||||
.build();
|
||||
accessResource = PlainAccessResource.parse(grpcRequest, mockAuthenticationHeader());
|
||||
Assert.assertTrue(Permission.PUB == accessResource.getResourcePermMap().get(DEFAULT_TOPIC));
|
||||
}
|
||||
|
||||
private AuthenticationHeader mockAuthenticationHeader() {
|
||||
return AuthenticationHeader.builder()
|
||||
.remoteAddress(DEFAULT_REMOTE_ADDR)
|
||||
.authorization(AUTH_HEADER)
|
||||
.datetime("datetime")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.Permission;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class PlainPermissionCheckerTest {
|
||||
|
||||
private PlainPermissionChecker permissionChecker;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
permissionChecker = new PlainPermissionChecker();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheck_withAdminPermission_shouldPass() {
|
||||
PlainAccessResource checkedAccess = new PlainAccessResource();
|
||||
checkedAccess.setRequestCode(Permission.SUB);
|
||||
checkedAccess.addResourceAndPerm("topic1", Permission.PUB);
|
||||
PlainAccessResource ownedAccess = new PlainAccessResource();
|
||||
ownedAccess.setAccessKey("adminUser");
|
||||
ownedAccess.setAdmin(true);
|
||||
try {
|
||||
permissionChecker.check(checkedAccess, ownedAccess);
|
||||
} catch (AclException e) {
|
||||
Assert.fail("Should not throw any exception for admin user");
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void testCheck_withoutAdminPermissionAndNoDefaultPerm_shouldThrowAclException() {
|
||||
PlainAccessResource checkedAccess = new PlainAccessResource();
|
||||
checkedAccess.setRequestCode(Permission.SUB);
|
||||
checkedAccess.addResourceAndPerm("topic1", Permission.PUB);
|
||||
PlainAccessResource ownedAccess = new PlainAccessResource();
|
||||
ownedAccess.setAccessKey("nonAdminUser");
|
||||
ownedAccess.setAdmin(false);
|
||||
permissionChecker.check(checkedAccess, ownedAccess);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheck_withDefaultPermissions_shouldPass() {
|
||||
PlainAccessResource checkedAccess = new PlainAccessResource();
|
||||
checkedAccess.setRequestCode(Permission.SUB);
|
||||
checkedAccess.addResourceAndPerm("topic1", Permission.PUB);
|
||||
PlainAccessResource ownedAccess = new PlainAccessResource();
|
||||
ownedAccess.setAccessKey("nonAdminUser");
|
||||
ownedAccess.setAdmin(false);
|
||||
ownedAccess.setDefaultTopicPerm(Permission.PUB);
|
||||
try {
|
||||
permissionChecker.check(checkedAccess, ownedAccess);
|
||||
} catch (AclException e) {
|
||||
Assert.fail("Should not throw any exception for default permissions");
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void testCheck_withoutPermission_shouldThrowAclException() {
|
||||
PlainAccessResource checkedAccess = new PlainAccessResource();
|
||||
checkedAccess.setRequestCode(Permission.SUB);
|
||||
checkedAccess.addResourceAndPerm("topic1", Permission.PUB);
|
||||
PlainAccessResource ownedAccess = new PlainAccessResource();
|
||||
ownedAccess.setAccessKey("nonAdminUser");
|
||||
ownedAccess.setAdmin(false);
|
||||
ownedAccess.setDefaultTopicPerm(Permission.SUB);
|
||||
permissionChecker.check(checkedAccess, ownedAccess);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.apache.rocketmq.acl.common.AclConstants;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.AclUtils;
|
||||
import org.apache.rocketmq.acl.common.Permission;
|
||||
import org.apache.rocketmq.common.AclConfig;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.remoting.protocol.DataVersion;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class PlainPermissionManagerTest {
|
||||
|
||||
PlainPermissionManager plainPermissionManager;
|
||||
PlainAccessResource pubPlainAccessResource;
|
||||
PlainAccessResource subPlainAccessResource;
|
||||
PlainAccessResource anyPlainAccessResource;
|
||||
PlainAccessResource denyPlainAccessResource;
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
PlainAccessConfig plainAccessConfig = new PlainAccessConfig();
|
||||
Set<Integer> adminCode = new HashSet<>();
|
||||
|
||||
private static final String DEFAULT_TOPIC = "topic-acl";
|
||||
|
||||
private File confHome;
|
||||
|
||||
@Before
|
||||
public void init() throws NoSuchFieldException, SecurityException, IOException {
|
||||
// UPDATE_AND_CREATE_TOPIC
|
||||
adminCode.add(17);
|
||||
// UPDATE_BROKER_CONFIG
|
||||
adminCode.add(25);
|
||||
// DELETE_TOPIC_IN_BROKER
|
||||
adminCode.add(215);
|
||||
// UPDATE_AND_CREATE_SUBSCRIPTIONGROUP
|
||||
adminCode.add(200);
|
||||
// DELETE_SUBSCRIPTIONGROUP
|
||||
adminCode.add(207);
|
||||
|
||||
pubPlainAccessResource = clonePlainAccessResource(Permission.PUB);
|
||||
subPlainAccessResource = clonePlainAccessResource(Permission.SUB);
|
||||
anyPlainAccessResource = clonePlainAccessResource(Permission.ANY);
|
||||
denyPlainAccessResource = clonePlainAccessResource(Permission.DENY);
|
||||
|
||||
String folder = "conf";
|
||||
confHome = AclTestHelper.copyResources(folder, true);
|
||||
System.setProperty("rocketmq.home.dir", confHome.getAbsolutePath());
|
||||
plainPermissionManager = new PlainPermissionManager();
|
||||
}
|
||||
|
||||
public PlainAccessResource clonePlainAccessResource(byte perm) {
|
||||
PlainAccessResource painAccessResource = new PlainAccessResource();
|
||||
painAccessResource.setAccessKey("RocketMQ");
|
||||
painAccessResource.setSecretKey("12345678");
|
||||
painAccessResource.setWhiteRemoteAddress("127.0." + perm + ".*");
|
||||
painAccessResource.setDefaultGroupPerm(perm);
|
||||
painAccessResource.setDefaultTopicPerm(perm);
|
||||
painAccessResource.addResourceAndPerm(PlainAccessResource.getRetryTopic("groupA"), Permission.PUB);
|
||||
painAccessResource.addResourceAndPerm(PlainAccessResource.getRetryTopic("groupB"), Permission.SUB);
|
||||
painAccessResource.addResourceAndPerm(PlainAccessResource.getRetryTopic("groupC"), Permission.ANY);
|
||||
painAccessResource.addResourceAndPerm(PlainAccessResource.getRetryTopic("groupD"), Permission.DENY);
|
||||
|
||||
painAccessResource.addResourceAndPerm("topicA", Permission.PUB);
|
||||
painAccessResource.addResourceAndPerm("topicB", Permission.SUB);
|
||||
painAccessResource.addResourceAndPerm("topicC", Permission.ANY);
|
||||
painAccessResource.addResourceAndPerm("topicD", Permission.DENY);
|
||||
return painAccessResource;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildPlainAccessResourceTest() {
|
||||
PlainAccessResource plainAccessResource = null;
|
||||
PlainAccessConfig plainAccess = new PlainAccessConfig();
|
||||
|
||||
plainAccess.setAccessKey("RocketMQ");
|
||||
plainAccess.setSecretKey("12345678");
|
||||
plainAccessResource = plainPermissionManager.buildPlainAccessResource(plainAccess);
|
||||
Assert.assertEquals(plainAccessResource.getAccessKey(), "RocketMQ");
|
||||
Assert.assertEquals(plainAccessResource.getSecretKey(), "12345678");
|
||||
|
||||
plainAccess.setWhiteRemoteAddress("127.0.0.1");
|
||||
plainAccessResource = plainPermissionManager.buildPlainAccessResource(plainAccess);
|
||||
Assert.assertEquals(plainAccessResource.getWhiteRemoteAddress(), "127.0.0.1");
|
||||
|
||||
plainAccess.setAdmin(true);
|
||||
plainAccessResource = plainPermissionManager.buildPlainAccessResource(plainAccess);
|
||||
Assert.assertEquals(plainAccessResource.isAdmin(), true);
|
||||
|
||||
List<String> groups = new ArrayList<>();
|
||||
groups.add("groupA=DENY");
|
||||
groups.add("groupB=PUB|SUB");
|
||||
groups.add("groupC=PUB");
|
||||
plainAccess.setGroupPerms(groups);
|
||||
plainAccessResource = plainPermissionManager.buildPlainAccessResource(plainAccess);
|
||||
Map<String, Byte> resourcePermMap = plainAccessResource.getResourcePermMap();
|
||||
Assert.assertEquals(resourcePermMap.size(), 3);
|
||||
|
||||
Assert.assertEquals(resourcePermMap.get(PlainAccessResource.getRetryTopic("groupA")).byteValue(), Permission.DENY);
|
||||
Assert.assertEquals(resourcePermMap.get(PlainAccessResource.getRetryTopic("groupB")).byteValue(), Permission.PUB | Permission.SUB);
|
||||
Assert.assertEquals(resourcePermMap.get(PlainAccessResource.getRetryTopic("groupC")).byteValue(), Permission.PUB);
|
||||
|
||||
List<String> topics = new ArrayList<>();
|
||||
topics.add("topicA=DENY");
|
||||
topics.add("topicB=PUB|SUB");
|
||||
topics.add("topicC=PUB");
|
||||
plainAccess.setTopicPerms(topics);
|
||||
plainAccessResource = plainPermissionManager.buildPlainAccessResource(plainAccess);
|
||||
resourcePermMap = plainAccessResource.getResourcePermMap();
|
||||
Assert.assertEquals(resourcePermMap.size(), 6);
|
||||
|
||||
Assert.assertEquals(resourcePermMap.get("topicA").byteValue(), Permission.DENY);
|
||||
Assert.assertEquals(resourcePermMap.get("topicB").byteValue(), Permission.PUB | Permission.SUB);
|
||||
Assert.assertEquals(resourcePermMap.get("topicC").byteValue(), Permission.PUB);
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void checkPermAdmin() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setRequestCode(17);
|
||||
plainPermissionManager.checkPerm(plainAccessResource, pubPlainAccessResource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkPerm() {
|
||||
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.addResourceAndPerm("topicA", Permission.PUB);
|
||||
plainPermissionManager.checkPerm(plainAccessResource, pubPlainAccessResource);
|
||||
plainAccessResource.addResourceAndPerm("topicB", Permission.SUB);
|
||||
plainPermissionManager.checkPerm(plainAccessResource, anyPlainAccessResource);
|
||||
|
||||
plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.addResourceAndPerm("topicB", Permission.SUB);
|
||||
plainPermissionManager.checkPerm(plainAccessResource, subPlainAccessResource);
|
||||
plainAccessResource.addResourceAndPerm("topicA", Permission.PUB);
|
||||
plainPermissionManager.checkPerm(plainAccessResource, anyPlainAccessResource);
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void checkErrorPermDefaultValueNotMatch() {
|
||||
|
||||
plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.addResourceAndPerm("topicF", Permission.PUB);
|
||||
plainPermissionManager.checkPerm(plainAccessResource, subPlainAccessResource);
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void accountNullTest() {
|
||||
plainAccessConfig.setAccessKey(null);
|
||||
plainPermissionManager.buildPlainAccessResource(plainAccessConfig);
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void accountThanTest() {
|
||||
plainAccessConfig.setAccessKey("123");
|
||||
plainPermissionManager.buildPlainAccessResource(plainAccessConfig);
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void passWordtNullTest() {
|
||||
plainAccessConfig.setAccessKey(null);
|
||||
plainPermissionManager.buildPlainAccessResource(plainAccessConfig);
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void passWordThanTest() {
|
||||
plainAccessConfig.setSecretKey("123");
|
||||
plainPermissionManager.buildPlainAccessResource(plainAccessConfig);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void cleanAuthenticationInfoTest() throws IllegalAccessException {
|
||||
// PlainPermissionManager.addPlainAccessResource(plainAccessResource);
|
||||
Map<String, Map<String, PlainAccessResource>> plainAccessResourceMap = (Map<String, Map<String, PlainAccessResource>>) FieldUtils.readDeclaredField(plainPermissionManager, "aclPlainAccessResourceMap", true);
|
||||
Assert.assertFalse(plainAccessResourceMap.isEmpty());
|
||||
|
||||
plainPermissionManager.clearPermissionInfo();
|
||||
plainAccessResourceMap = (Map<String, Map<String, PlainAccessResource>>) FieldUtils.readDeclaredField(plainPermissionManager, "aclPlainAccessResourceMap", true);
|
||||
Assert.assertTrue(plainAccessResourceMap.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isWatchStartTest() {
|
||||
|
||||
PlainPermissionManager plainPermissionManager = new PlainPermissionManager();
|
||||
Assert.assertTrue(plainPermissionManager.isWatchStart());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWatch() throws IOException, IllegalAccessException, InterruptedException {
|
||||
String fileName = Joiner.on(File.separator).join(new String[]{System.getProperty("rocketmq.home.dir"), "conf", "acl", "plain_acl_test.yml"});
|
||||
File transport = new File(fileName);
|
||||
transport.delete();
|
||||
transport.createNewFile();
|
||||
FileWriter writer = new FileWriter(transport);
|
||||
writer.write("accounts:\r\n");
|
||||
writer.write("- accessKey: watchrocketmqx\r\n");
|
||||
writer.write(" secretKey: 12345678\r\n");
|
||||
writer.write(" whiteRemoteAddress: 127.0.0.1\r\n");
|
||||
writer.write(" admin: true\r\n");
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
PlainPermissionManager plainPermissionManager = new PlainPermissionManager();
|
||||
Assert.assertTrue(plainPermissionManager.isWatchStart());
|
||||
|
||||
Map<String, String> accessKeyTable = (Map<String, String>) FieldUtils.readDeclaredField(plainPermissionManager, "accessKeyTable", true);
|
||||
String aclFileName = accessKeyTable.get("watchrocketmqx");
|
||||
{
|
||||
Map<String, Map<String, PlainAccessResource>> plainAccessResourceMap = (Map<String, Map<String, PlainAccessResource>>) FieldUtils.readDeclaredField(plainPermissionManager, "aclPlainAccessResourceMap", true);
|
||||
PlainAccessResource accessResource = plainAccessResourceMap.get(aclFileName).get("watchrocketmqx");
|
||||
Assert.assertNotNull(accessResource);
|
||||
Assert.assertEquals(accessResource.getSecretKey(), "12345678");
|
||||
Assert.assertTrue(accessResource.isAdmin());
|
||||
|
||||
}
|
||||
|
||||
PlainAccessData updatedMap = AclUtils.getYamlDataObject(fileName, PlainAccessData.class);
|
||||
List<PlainAccessConfig> accounts = updatedMap.getAccounts();
|
||||
accounts.get(0).setAccessKey("watchrocketmq1y");
|
||||
accounts.get(0).setSecretKey("88888888");
|
||||
accounts.get(0).setAdmin(false);
|
||||
// Update file and flush to yaml file
|
||||
AclUtils.writeDataObject(fileName, updatedMap);
|
||||
|
||||
Thread.sleep(10000);
|
||||
{
|
||||
Map<String, Map<String, PlainAccessResource>> plainAccessResourceMap = (Map<String, Map<String, PlainAccessResource>>) FieldUtils.readDeclaredField(plainPermissionManager, "aclPlainAccessResourceMap", true);
|
||||
PlainAccessResource accessResource = plainAccessResourceMap.get(aclFileName).get("watchrocketmq1y");
|
||||
Assert.assertNotNull(accessResource);
|
||||
Assert.assertEquals(accessResource.getSecretKey(), "88888888");
|
||||
Assert.assertFalse(accessResource.isAdmin());
|
||||
|
||||
}
|
||||
transport.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateAccessConfigTest() {
|
||||
Assert.assertThrows(AclException.class, () -> plainPermissionManager.updateAccessConfig(null));
|
||||
|
||||
plainAccessConfig.setAccessKey("admin_test");
|
||||
// Invalid parameter
|
||||
plainAccessConfig.setSecretKey("123456");
|
||||
plainAccessConfig.setAdmin(true);
|
||||
Assert.assertThrows(AclException.class, () -> plainPermissionManager.updateAccessConfig(plainAccessConfig));
|
||||
|
||||
plainAccessConfig.setSecretKey("12345678");
|
||||
// Invalid parameter
|
||||
plainAccessConfig.setGroupPerms(Lists.newArrayList("groupA!SUB"));
|
||||
Assert.assertThrows(AclException.class, () -> plainPermissionManager.updateAccessConfig(plainAccessConfig));
|
||||
|
||||
// first update
|
||||
plainAccessConfig.setGroupPerms(Lists.newArrayList("groupA=SUB"));
|
||||
plainPermissionManager.updateAccessConfig(plainAccessConfig);
|
||||
|
||||
// second update
|
||||
plainAccessConfig.setTopicPerms(Lists.newArrayList("topicA=SUB"));
|
||||
plainPermissionManager.updateAccessConfig(plainAccessConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllAclFilesTest() {
|
||||
final List<String> notExistList = plainPermissionManager.getAllAclFiles("aa/bb");
|
||||
Assertions.assertThat(notExistList).isEmpty();
|
||||
final List<String> files = plainPermissionManager.getAllAclFiles(confHome.getAbsolutePath());
|
||||
Assertions.assertThat(files).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadTest() {
|
||||
plainPermissionManager.load();
|
||||
final Map<String, DataVersion> map = plainPermissionManager.getDataVersionMap();
|
||||
Assertions.assertThat(map).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateAclConfigFileVersionTest() {
|
||||
String aclFileName = "test_plain_acl";
|
||||
PlainAccessData updateAclConfigMap = new PlainAccessData();
|
||||
List<PlainAccessData.DataVersion> versionElement = new ArrayList<>();
|
||||
PlainAccessData.DataVersion accountsMap = new PlainAccessData.DataVersion();
|
||||
accountsMap.setCounter(1);
|
||||
accountsMap.setTimestamp(System.currentTimeMillis());
|
||||
versionElement.add(accountsMap);
|
||||
|
||||
updateAclConfigMap.setDataVersion(versionElement);
|
||||
final PlainAccessData map = plainPermissionManager.updateAclConfigFileVersion(aclFileName, updateAclConfigMap);
|
||||
final List<PlainAccessData.DataVersion> version = map.getDataVersion();
|
||||
Assert.assertEquals(2L, version.get(0).getCounter());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAclAccessConfigMapTest() {
|
||||
PlainAccessConfig existedAccountMap = new PlainAccessConfig();
|
||||
plainAccessConfig.setAccessKey("admin123");
|
||||
plainAccessConfig.setSecretKey("12345678");
|
||||
plainAccessConfig.setWhiteRemoteAddress("192.168.1.1");
|
||||
plainAccessConfig.setAdmin(false);
|
||||
plainAccessConfig.setDefaultGroupPerm(AclConstants.SUB_PUB);
|
||||
plainAccessConfig.setTopicPerms(Arrays.asList(DEFAULT_TOPIC + "=" + AclConstants.PUB));
|
||||
plainAccessConfig.setGroupPerms(Lists.newArrayList("groupA=SUB"));
|
||||
|
||||
final PlainAccessConfig map = plainPermissionManager.createAclAccessConfigMap(existedAccountMap, plainAccessConfig);
|
||||
Assert.assertEquals(AclConstants.SUB_PUB, map.getDefaultGroupPerm());
|
||||
Assert.assertEquals("groupA=SUB", map.getGroupPerms().get(0));
|
||||
Assert.assertEquals("12345678", map.getSecretKey());
|
||||
Assert.assertEquals("admin123", map.getAccessKey());
|
||||
Assert.assertEquals("192.168.1.1", map.getWhiteRemoteAddress());
|
||||
Assert.assertEquals("topic-acl=PUB", map.getTopicPerms().get(0));
|
||||
Assert.assertEquals(false, map.isAdmin());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteAccessConfigTest() throws InterruptedException {
|
||||
// delete not exist accessConfig
|
||||
final boolean flag1 = plainPermissionManager.deleteAccessConfig("test_delete");
|
||||
assert !flag1;
|
||||
|
||||
plainAccessConfig.setAccessKey("test_delete");
|
||||
plainAccessConfig.setSecretKey("12345678");
|
||||
plainAccessConfig.setWhiteRemoteAddress("192.168.1.1");
|
||||
plainAccessConfig.setAdmin(false);
|
||||
plainAccessConfig.setDefaultGroupPerm(AclConstants.SUB_PUB);
|
||||
plainAccessConfig.setTopicPerms(Arrays.asList(DEFAULT_TOPIC + "=" + AclConstants.PUB));
|
||||
plainAccessConfig.setGroupPerms(Lists.newArrayList("groupA=SUB"));
|
||||
plainPermissionManager.updateAccessConfig(plainAccessConfig);
|
||||
|
||||
//delete existed accessConfig
|
||||
final boolean flag2 = plainPermissionManager.deleteAccessConfig("test_delete");
|
||||
assert flag2;
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGlobalWhiteAddrsConfigTest() {
|
||||
final boolean flag = plainPermissionManager.updateGlobalWhiteAddrsConfig(Lists.newArrayList("192.168.1.2"));
|
||||
assert flag;
|
||||
final AclConfig config = plainPermissionManager.getAllAclConfig();
|
||||
Assert.assertEquals(true, config.getGlobalWhiteAddrs().contains("192.168.1.2"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.plain;
|
||||
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RemoteAddressStrategyTest {
|
||||
|
||||
RemoteAddressStrategyFactory remoteAddressStrategyFactory = new RemoteAddressStrategyFactory();
|
||||
|
||||
@Test
|
||||
public void netAddressStrategyFactoryExceptionTest() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource).getClass(),
|
||||
RemoteAddressStrategyFactory.BlankRemoteAddressStrategy.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void netAddressStrategyFactoryTest() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("*");
|
||||
RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("*.*.*.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.OneRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1,127.0.0.2,127.0.0.3");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.MultipleRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.{1,2,3}");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.MultipleRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1-200");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.1-20.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.BlankRemoteAddressStrategy.class);
|
||||
|
||||
// IPv6 test
|
||||
plainAccessResource.setWhiteRemoteAddress("*:*:*:*:*:*:*:*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy, RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:326b");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.OneRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261,1050::0005:0600:300c:3262,1050::0005:0600:300c:3263");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.MultipleRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261:{1,2,3}");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.MultipleRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261:1-200");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050:0005:0600:300c:3261:*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:3261:1-20:*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
Assert.assertEquals(remoteAddressStrategy.getClass(), RemoteAddressStrategyFactory.RangeRemoteAddressStrategy.class);
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void verifyTest() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("256.0.0.1");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("::1ggg");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullNetAddressStrategyTest() {
|
||||
boolean isMatch = RemoteAddressStrategyFactory.NULL_NET_ADDRESS_STRATEGY.match(new PlainAccessResource());
|
||||
Assert.assertTrue(isMatch);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blankNetAddressStrategyTest() {
|
||||
boolean isMatch = RemoteAddressStrategyFactory.BLANK_NET_ADDRESS_STRATEGY.match(new PlainAccessResource());
|
||||
Assert.assertFalse(isMatch);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneNetAddressStrategyTest() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1");
|
||||
RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("");
|
||||
boolean match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.2");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
// Ipv6 test
|
||||
plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("::1");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("::2");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("::1");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("0000:0000:0000:0000:0000:0000:0000:0001");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleNetAddressStrategyTest() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1,127.0.0.2,127.0.0.3");
|
||||
RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
multipleNetAddressStrategyTest(remoteAddressStrategy);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.{1,2,3}");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
multipleNetAddressStrategyTest(remoteAddressStrategy);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("192.100-150.*.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("192.130.0.2");
|
||||
boolean match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1,1050::0005:0600:300c:2,1050::0005:0600:300c:3");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
multipleIPv6NetAddressStrategyTest(remoteAddressStrategy);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:{1,2,3}");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
multipleIPv6NetAddressStrategyTest(remoteAddressStrategy);
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void multipleNetAddressStrategyExceptionTest() {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1,2,3}");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("::1,2,3}");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("192.168.1.{1}");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("192.168.1.{1,2}");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("192.168.{1}");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("{192.168.1}");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
plainAccessResource.setWhiteRemoteAddress("{192.168.1.1}");
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
}
|
||||
|
||||
private void multipleNetAddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy) {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1");
|
||||
boolean match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.2");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.3");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.4");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.0");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
}
|
||||
|
||||
private void multipleIPv6NetAddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy) {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:1");
|
||||
boolean match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:2");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:3");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertTrue(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:4");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050:0000:0000:0000:0005:0600:300c:0");
|
||||
match = remoteAddressStrategy.match(plainAccessResource);
|
||||
Assert.assertFalse(match);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rangeNetAddressStrategyTest() {
|
||||
String head = "127.0.0.";
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.1-200");
|
||||
RemoteAddressStrategy remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeNetAddressStrategyTest(remoteAddressStrategy, head, 1, 200, true);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.0.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeNetAddressStrategyTest(remoteAddressStrategy, head, 0, 255, true);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.0.1-200.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeNetAddressStrategyThirdlyTest(remoteAddressStrategy, head, 1, 200);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.*.*.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeNetAddressStrategyTest(remoteAddressStrategy, head, 0, 255, true);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("127.1-150.*.*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeNetAddressStrategyThirdlyTest(remoteAddressStrategy, head, 1, 200);
|
||||
|
||||
// IPv6 test
|
||||
head = "1050::0005:0600:300c:";
|
||||
plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1-200");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeIPv6NetAddressStrategyTest(remoteAddressStrategy, head, "1", "200", true);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeIPv6NetAddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", true);
|
||||
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:3001:*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeIPv6NetAddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", false);
|
||||
|
||||
head = "1050::0005:0600:300c:1:";
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1-200:*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeIPv6NetAddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", true);
|
||||
|
||||
head = "1050::0005:0600:300c:201:";
|
||||
plainAccessResource.setWhiteRemoteAddress("1050::0005:0600:300c:1-200:*");
|
||||
remoteAddressStrategy = remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
rangeIPv6NetAddressStrategyTest(remoteAddressStrategy, head, "0", "ffff", false);
|
||||
|
||||
}
|
||||
|
||||
private void rangeNetAddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy, String head, int start,
|
||||
int end,
|
||||
boolean isFalse) {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
for (int i = -10; i < 300; i++) {
|
||||
plainAccessResource.setWhiteRemoteAddress(head + i);
|
||||
boolean match = remoteAddressStrategy.match(plainAccessResource);
|
||||
if (isFalse && i >= start && i <= end) {
|
||||
Assert.assertTrue(match);
|
||||
continue;
|
||||
}
|
||||
Assert.assertFalse(match);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void rangeNetAddressStrategyThirdlyTest(RemoteAddressStrategy remoteAddressStrategy, String head, int start,
|
||||
int end) {
|
||||
String newHead;
|
||||
for (int i = -10; i < 300; i++) {
|
||||
newHead = head + i;
|
||||
if (i >= start && i <= end) {
|
||||
rangeNetAddressStrategyTest(remoteAddressStrategy, newHead, 0, 255, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void rangeIPv6NetAddressStrategyTest(RemoteAddressStrategy remoteAddressStrategy, String head, String start,
|
||||
String end,
|
||||
boolean isFalse) {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
for (int i = -10; i < 65536 + 100; i++) {
|
||||
String hex = Integer.toHexString(i);
|
||||
plainAccessResource.setWhiteRemoteAddress(head + hex);
|
||||
boolean match = remoteAddressStrategy.match(plainAccessResource);
|
||||
int startNum = Integer.parseInt(start, 16);
|
||||
int endNum = Integer.parseInt(end, 16);
|
||||
if (isFalse && i >= startNum && i <= endNum) {
|
||||
Assert.assertTrue(match);
|
||||
continue;
|
||||
}
|
||||
Assert.assertFalse(match);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void rangeNetAddressStrategyExceptionStartGreaterEndTest() {
|
||||
rangeNetAddressStrategyExceptionTest("127.0.0.2-1");
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void rangeNetAddressStrategyExceptionScopeTest() {
|
||||
rangeNetAddressStrategyExceptionTest("127.0.0.-1-200");
|
||||
}
|
||||
|
||||
@Test(expected = AclException.class)
|
||||
public void rangeNetAddressStrategyExceptionScopeTwoTest() {
|
||||
rangeNetAddressStrategyExceptionTest("127.0.0.0-256");
|
||||
}
|
||||
|
||||
private void rangeNetAddressStrategyExceptionTest(String netAddress) {
|
||||
PlainAccessResource plainAccessResource = new PlainAccessResource();
|
||||
plainAccessResource.setWhiteRemoteAddress(netAddress);
|
||||
remoteAddressStrategyFactory.getRemoteAddressStrategy(plainAccessResource);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
# 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.
|
||||
|
||||
accounts:
|
||||
- accessKey: rocketmq3
|
||||
secretKey: 12345678
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: DENY
|
||||
topicPerms:
|
||||
- topicA=PUB
|
||||
- topicB=SUB
|
||||
- topicC=PUB|SUB
|
||||
- topicD=DENY
|
||||
groupPerms:
|
||||
- groupB=SUB
|
||||
- groupC=PUB|SUB
|
||||
- groupD=DENY
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## no global white addresses in this file, define them in ../plain_acl.yml
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
# the group should convert to retry topic
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
# if it is admin, it could access all resources
|
||||
admin: true
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
# the group should convert to retry topic
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
# if it is admin, it could access all resources
|
||||
admin: true
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
@@ -1,20 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
@@ -1,25 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
accounts:
|
||||
- accessKey: watchrocketmq
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 127.0.0.1
|
||||
admin: true
|
||||
- accessKey: watchrocketmq1
|
||||
secretKey: 88888888
|
||||
whiteRemoteAddress: 127.0.0.1
|
||||
admin: false
|
||||
@@ -1,19 +0,0 @@
|
||||
# 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.
|
||||
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## no global white addresses in this file, define them in ../plain_acl.yml
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
# the group should convert to retry topic
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
# if it is admin, it could access all resources
|
||||
admin: true
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<configuration>
|
||||
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>
|
||||
%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
|
||||
</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.apache.rocketmq" level="error" additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -1,18 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
accounts: []
|
||||
@@ -1,39 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
@@ -1,36 +0,0 @@
|
||||
# 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.
|
||||
|
||||
## suggested format
|
||||
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.0.*
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
- groupA=DENY
|
||||
- groupB=SUB
|
||||
- groupC=SUB
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
admin: true
|
||||
+2
-2
@@ -21,10 +21,10 @@ java_library(
|
||||
srcs = glob(["src/main/java/**/*.java"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//acl",
|
||||
"//common",
|
||||
"//remoting",
|
||||
"//srvutil",
|
||||
"//client",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:org_apache_commons_commons_lang3",
|
||||
"@maven//:commons_collections_commons_collections",
|
||||
@@ -48,10 +48,10 @@ java_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":auth",
|
||||
"//acl",
|
||||
"//:test_deps",
|
||||
"//common",
|
||||
"//remoting",
|
||||
"//client",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:org_apache_commons_commons_lang3",
|
||||
"@maven//:commons_collections_commons_collections",
|
||||
|
||||
+9
-9
@@ -29,11 +29,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-remoting</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-common</artifactId>
|
||||
<artifactId>rocketmq-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
@@ -44,12 +40,12 @@
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-acl</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
@@ -61,6 +57,10 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -16,14 +16,9 @@
|
||||
*/
|
||||
package org.apache.rocketmq.auth.migration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.acl.common.AclConstants;
|
||||
import org.apache.rocketmq.acl.plain.PlainPermissionManager;
|
||||
import org.apache.rocketmq.auth.authentication.enums.UserType;
|
||||
import org.apache.rocketmq.auth.authentication.factory.AuthenticationFactory;
|
||||
import org.apache.rocketmq.auth.authentication.manager.AuthenticationMetadataManager;
|
||||
@@ -38,8 +33,9 @@ import org.apache.rocketmq.auth.authorization.model.Policy;
|
||||
import org.apache.rocketmq.auth.authorization.model.PolicyEntry;
|
||||
import org.apache.rocketmq.auth.authorization.model.Resource;
|
||||
import org.apache.rocketmq.auth.config.AuthConfig;
|
||||
import org.apache.rocketmq.common.AclConfig;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.auth.migration.v1.PlainPermissionManager;
|
||||
import org.apache.rocketmq.auth.migration.v1.AclConfig;
|
||||
import org.apache.rocketmq.auth.migration.v1.PlainAccessConfig;
|
||||
import org.apache.rocketmq.common.action.Action;
|
||||
import org.apache.rocketmq.common.constant.CommonConstants;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
@@ -48,6 +44,11 @@ import org.apache.rocketmq.common.resource.ResourceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class AuthMigrator {
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.rocketmq.acl;
|
||||
package org.apache.rocketmq.auth.migration.v1;
|
||||
|
||||
public interface AccessResource {
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.rocketmq.common;
|
||||
package org.apache.rocketmq.auth.migration.v1;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.rocketmq.common;
|
||||
package org.apache.rocketmq.auth.migration.v1;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
+1
-3
@@ -14,9 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.rocketmq.acl.plain;
|
||||
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
package org.apache.rocketmq.auth.migration.v1;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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.rocketmq.auth.migration.v1;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.rocketmq.common.KeyBuilder;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlainAccessResource implements AccessResource {
|
||||
|
||||
// Identify the user
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private String whiteRemoteAddress;
|
||||
|
||||
private boolean admin;
|
||||
|
||||
private byte defaultTopicPerm = 1;
|
||||
|
||||
private byte defaultGroupPerm = 1;
|
||||
|
||||
private Map<String, Byte> resourcePermMap;
|
||||
|
||||
private int requestCode;
|
||||
|
||||
// The content to calculate the content
|
||||
private byte[] content;
|
||||
|
||||
private String signature;
|
||||
|
||||
private String secretToken;
|
||||
|
||||
private String recognition;
|
||||
|
||||
public PlainAccessResource() {
|
||||
}
|
||||
|
||||
public static String getGroupFromRetryTopic(String retryTopic) {
|
||||
if (retryTopic == null) {
|
||||
return null;
|
||||
}
|
||||
return KeyBuilder.parseGroup(retryTopic);
|
||||
}
|
||||
|
||||
public static String getRetryTopic(String group) {
|
||||
if (group == null) {
|
||||
return null;
|
||||
}
|
||||
return MixAll.getRetryTopic(group);
|
||||
}
|
||||
|
||||
public void addResourceAndPerm(String resource, byte perm) {
|
||||
if (resource == null) {
|
||||
return;
|
||||
}
|
||||
if (resourcePermMap == null) {
|
||||
resourcePermMap = new HashMap<>();
|
||||
}
|
||||
resourcePermMap.put(resource, perm);
|
||||
}
|
||||
|
||||
public String getAccessKey() {
|
||||
return accessKey;
|
||||
}
|
||||
|
||||
public void setAccessKey(String accessKey) {
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public String getWhiteRemoteAddress() {
|
||||
return whiteRemoteAddress;
|
||||
}
|
||||
|
||||
public void setWhiteRemoteAddress(String whiteRemoteAddress) {
|
||||
this.whiteRemoteAddress = whiteRemoteAddress;
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return admin;
|
||||
}
|
||||
|
||||
public void setAdmin(boolean admin) {
|
||||
this.admin = admin;
|
||||
}
|
||||
|
||||
public byte getDefaultTopicPerm() {
|
||||
return defaultTopicPerm;
|
||||
}
|
||||
|
||||
public void setDefaultTopicPerm(byte defaultTopicPerm) {
|
||||
this.defaultTopicPerm = defaultTopicPerm;
|
||||
}
|
||||
|
||||
public byte getDefaultGroupPerm() {
|
||||
return defaultGroupPerm;
|
||||
}
|
||||
|
||||
public void setDefaultGroupPerm(byte defaultGroupPerm) {
|
||||
this.defaultGroupPerm = defaultGroupPerm;
|
||||
}
|
||||
|
||||
public Map<String, Byte> getResourcePermMap() {
|
||||
return resourcePermMap;
|
||||
}
|
||||
|
||||
public String getRecognition() {
|
||||
return recognition;
|
||||
}
|
||||
|
||||
public void setRecognition(String recognition) {
|
||||
this.recognition = recognition;
|
||||
}
|
||||
|
||||
public int getRequestCode() {
|
||||
return requestCode;
|
||||
}
|
||||
|
||||
public void setRequestCode(int requestCode) {
|
||||
this.requestCode = requestCode;
|
||||
}
|
||||
|
||||
public String getSecretToken() {
|
||||
return secretToken;
|
||||
}
|
||||
|
||||
public void setSecretToken(String secretToken) {
|
||||
this.secretToken = secretToken;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this);
|
||||
}
|
||||
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.rocketmq.auth.migration.v1;
|
||||
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.AclUtils;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PlainPermissionManager {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggerName.COMMON_LOGGER_NAME);
|
||||
|
||||
private String fileHome = System.getProperty(MixAll.ROCKETMQ_HOME_PROPERTY,
|
||||
System.getenv(MixAll.ROCKETMQ_HOME_ENV));
|
||||
|
||||
private String defaultAclDir;
|
||||
|
||||
private String defaultAclFile;
|
||||
|
||||
private List<String> fileList = new ArrayList<>();
|
||||
|
||||
|
||||
public PlainPermissionManager() {
|
||||
this.defaultAclDir = MixAll.dealFilePath(fileHome + File.separator + "conf" + File.separator + "acl");
|
||||
this.defaultAclFile = MixAll.dealFilePath(fileHome + File.separator + System.getProperty("rocketmq.acl.plain.file", "conf" + File.separator + "plain_acl.yml"));
|
||||
load();
|
||||
}
|
||||
|
||||
public List<String> getAllAclFiles(String path) {
|
||||
if (!new File(path).exists()) {
|
||||
log.info("The default acl dir {} is not exist", path);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> allAclFileFullPath = new ArrayList<>();
|
||||
File file = new File(path);
|
||||
File[] files = file.listFiles();
|
||||
for (int i = 0; files != null && i < files.length; i++) {
|
||||
String fileName = files[i].getAbsolutePath();
|
||||
File f = new File(fileName);
|
||||
if (fileName.equals(fileHome + MixAll.ACL_CONF_TOOLS_FILE)) {
|
||||
continue;
|
||||
} else if (fileName.endsWith(".yml") || fileName.endsWith(".yaml")) {
|
||||
allAclFileFullPath.add(fileName);
|
||||
} else if (f.isDirectory()) {
|
||||
allAclFileFullPath.addAll(getAllAclFiles(fileName));
|
||||
}
|
||||
}
|
||||
return allAclFileFullPath;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (fileHome == null || fileHome.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assureAclConfigFilesExist();
|
||||
|
||||
fileList = getAllAclFiles(defaultAclDir);
|
||||
if (new File(defaultAclFile).exists() && !fileList.contains(defaultAclFile)) {
|
||||
fileList.add(defaultAclFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently GlobalWhiteAddress is defined in {@link #defaultAclFile}, so make sure it exists.
|
||||
*/
|
||||
private void assureAclConfigFilesExist() {
|
||||
final Path defaultAclFilePath = Paths.get(this.defaultAclFile);
|
||||
if (!Files.exists(defaultAclFilePath)) {
|
||||
try {
|
||||
Files.createFile(defaultAclFilePath);
|
||||
} catch (FileAlreadyExistsException e) {
|
||||
// Maybe created by other threads
|
||||
} catch (IOException e) {
|
||||
log.error("Error in creating " + this.defaultAclFile, e);
|
||||
throw new AclException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AclConfig getAllAclConfig() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
List<PlainAccessConfig> configs = new ArrayList<>();
|
||||
List<String> whiteAddrs = new ArrayList<>();
|
||||
Set<String> accessKeySets = new HashSet<>();
|
||||
|
||||
for (String path : fileList) {
|
||||
PlainAccessData plainAclConfData = AclUtils.getYamlDataObject(path, PlainAccessData.class);
|
||||
if (plainAclConfData == null) {
|
||||
continue;
|
||||
}
|
||||
List<String> globalWhiteAddrs = plainAclConfData.getGlobalWhiteRemoteAddresses();
|
||||
if (globalWhiteAddrs != null && !globalWhiteAddrs.isEmpty()) {
|
||||
whiteAddrs.addAll(globalWhiteAddrs);
|
||||
}
|
||||
|
||||
List<PlainAccessConfig> plainAccessConfigs = plainAclConfData.getAccounts();
|
||||
if (plainAccessConfigs != null && !plainAccessConfigs.isEmpty()) {
|
||||
for (PlainAccessConfig accessConfig : plainAccessConfigs) {
|
||||
if (!accessKeySets.contains(accessConfig.getAccessKey())) {
|
||||
accessKeySets.add(accessConfig.getAccessKey());
|
||||
PlainAccessConfig plainAccessConfig = new PlainAccessConfig();
|
||||
plainAccessConfig.setGroupPerms(accessConfig.getGroupPerms());
|
||||
plainAccessConfig.setDefaultTopicPerm(accessConfig.getDefaultTopicPerm());
|
||||
plainAccessConfig.setDefaultGroupPerm(accessConfig.getDefaultGroupPerm());
|
||||
plainAccessConfig.setAccessKey(accessConfig.getAccessKey());
|
||||
plainAccessConfig.setSecretKey(accessConfig.getSecretKey());
|
||||
plainAccessConfig.setAdmin(accessConfig.isAdmin());
|
||||
plainAccessConfig.setTopicPerms(accessConfig.getTopicPerms());
|
||||
plainAccessConfig.setWhiteRemoteAddress(accessConfig.getWhiteRemoteAddress());
|
||||
configs.add(plainAccessConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aclConfig.setPlainAccessConfigs(configs);
|
||||
aclConfig.setGlobalWhiteAddrs(whiteAddrs);
|
||||
return aclConfig;
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,13 @@
|
||||
package org.apache.rocketmq.auth.migration;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.apache.rocketmq.acl.plain.PlainPermissionManager;
|
||||
import org.apache.rocketmq.auth.authentication.manager.AuthenticationMetadataManager;
|
||||
import org.apache.rocketmq.auth.authentication.model.User;
|
||||
import org.apache.rocketmq.auth.authorization.manager.AuthorizationMetadataManager;
|
||||
import org.apache.rocketmq.auth.config.AuthConfig;
|
||||
import org.apache.rocketmq.common.AclConfig;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.auth.migration.v1.PlainPermissionManager;
|
||||
import org.apache.rocketmq.auth.migration.v1.AclConfig;
|
||||
import org.apache.rocketmq.auth.migration.v1.PlainAccessConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
+5
-3
@@ -21,7 +21,6 @@ java_library(
|
||||
srcs = glob(["src/main/java/**/*.java"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//acl",
|
||||
"//auth",
|
||||
"//client",
|
||||
"//common",
|
||||
@@ -52,6 +51,7 @@ java_library(
|
||||
"@maven//:io_opentelemetry_opentelemetry_sdk_common",
|
||||
"@maven//:io_opentelemetry_opentelemetry_sdk_metrics",
|
||||
"@maven//:org_apache_commons_commons_lang3",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:org_lz4_lz4_java",
|
||||
"@maven//:io_github_aliyunmq_rocketmq_slf4j_api",
|
||||
"@maven//:io_github_aliyunmq_rocketmq_logback_classic",
|
||||
@@ -66,7 +66,6 @@ java_library(
|
||||
name = "tests",
|
||||
srcs = glob(["src/test/java/**/*.java"]),
|
||||
resources = [
|
||||
"src/test/resources/META-INF/service/org.apache.rocketmq.acl.AccessValidator",
|
||||
"src/test/resources/META-INF/service/org.apache.rocketmq.broker.transaction.AbstractTransactionalMessageCheckListener",
|
||||
"src/test/resources/META-INF/service/org.apache.rocketmq.broker.transaction.TransactionalMessageService",
|
||||
"src/test/resources/rmq.logback-test.xml",
|
||||
@@ -75,7 +74,6 @@ java_library(
|
||||
deps = [
|
||||
":broker",
|
||||
"//:test_deps",
|
||||
"//acl",
|
||||
"//auth",
|
||||
"//client",
|
||||
"//common",
|
||||
@@ -84,15 +82,19 @@ java_library(
|
||||
"//store",
|
||||
"//tieredstore",
|
||||
"@maven//:com_alibaba_fastjson2_fastjson2",
|
||||
"@maven//:org_slf4j_slf4j_api",
|
||||
"@maven//:com_google_guava_guava",
|
||||
"@maven//:io_netty_netty_all",
|
||||
"@maven//:org_apache_commons_commons_lang3",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:commons_io_commons_io",
|
||||
"@maven//:io_github_aliyunmq_rocketmq_slf4j_api",
|
||||
"@maven//:org_powermock_powermock_core",
|
||||
"@maven//:io_opentelemetry_opentelemetry_api",
|
||||
"@maven//:com_googlecode_concurrentlinkedhashmap_concurrentlinkedhashmap_lru",
|
||||
"@maven//:org_apache_rocketmq_rocketmq_rocksdb",
|
||||
"@maven//:commons_collections_commons_collections",
|
||||
"@maven//:org_junit_jupiter_junit_jupiter_api",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -58,10 +58,6 @@
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-filter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-acl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-auth</artifactId>
|
||||
|
||||
@@ -18,32 +18,6 @@ package org.apache.rocketmq.broker;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessValidator;
|
||||
import org.apache.rocketmq.auth.authentication.factory.AuthenticationFactory;
|
||||
import org.apache.rocketmq.auth.authentication.manager.AuthenticationMetadataManager;
|
||||
import org.apache.rocketmq.auth.authorization.factory.AuthorizationFactory;
|
||||
@@ -61,6 +35,15 @@ import org.apache.rocketmq.broker.client.net.Broker2Client;
|
||||
import org.apache.rocketmq.broker.client.rebalance.RebalanceLockManager;
|
||||
import org.apache.rocketmq.broker.coldctr.ColdDataCgCtrService;
|
||||
import org.apache.rocketmq.broker.coldctr.ColdDataPullRequestHoldService;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBConsumerOffsetManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBLmqSubscriptionGroupManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBLmqTopicConfigManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBSubscriptionGroupManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBTopicConfigManager;
|
||||
import org.apache.rocketmq.broker.config.v2.ConfigStorage;
|
||||
import org.apache.rocketmq.broker.config.v2.ConsumerOffsetManagerV2;
|
||||
import org.apache.rocketmq.broker.config.v2.SubscriptionGroupManagerV2;
|
||||
import org.apache.rocketmq.broker.config.v2.TopicConfigManagerV2;
|
||||
import org.apache.rocketmq.broker.controller.ReplicasManager;
|
||||
import org.apache.rocketmq.broker.dledger.DLedgerRoleChangeHandler;
|
||||
import org.apache.rocketmq.broker.failover.EscapeBridge;
|
||||
@@ -77,7 +60,6 @@ import org.apache.rocketmq.broker.offset.BroadcastOffsetManager;
|
||||
import org.apache.rocketmq.broker.offset.ConsumerOffsetManager;
|
||||
import org.apache.rocketmq.broker.offset.ConsumerOrderInfoManager;
|
||||
import org.apache.rocketmq.broker.offset.LmqConsumerOffsetManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBConsumerOffsetManager;
|
||||
import org.apache.rocketmq.broker.out.BrokerOuterAPI;
|
||||
import org.apache.rocketmq.broker.plugin.BrokerAttachedPlugin;
|
||||
import org.apache.rocketmq.broker.pop.PopConsumerService;
|
||||
@@ -101,16 +83,8 @@ import org.apache.rocketmq.broker.processor.SendMessageProcessor;
|
||||
import org.apache.rocketmq.broker.schedule.ScheduleMessageService;
|
||||
import org.apache.rocketmq.broker.slave.SlaveSynchronize;
|
||||
import org.apache.rocketmq.broker.subscription.LmqSubscriptionGroupManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBLmqSubscriptionGroupManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBSubscriptionGroupManager;
|
||||
import org.apache.rocketmq.broker.subscription.SubscriptionGroupManager;
|
||||
import org.apache.rocketmq.broker.config.v2.ConsumerOffsetManagerV2;
|
||||
import org.apache.rocketmq.broker.config.v2.SubscriptionGroupManagerV2;
|
||||
import org.apache.rocketmq.broker.config.v2.TopicConfigManagerV2;
|
||||
import org.apache.rocketmq.broker.config.v2.ConfigStorage;
|
||||
import org.apache.rocketmq.broker.topic.LmqTopicConfigManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBLmqTopicConfigManager;
|
||||
import org.apache.rocketmq.broker.config.v1.RocksDBTopicConfigManager;
|
||||
import org.apache.rocketmq.broker.topic.TopicConfigManager;
|
||||
import org.apache.rocketmq.broker.topic.TopicQueueMappingCleanService;
|
||||
import org.apache.rocketmq.broker.topic.TopicQueueMappingManager;
|
||||
@@ -154,7 +128,6 @@ import org.apache.rocketmq.remoting.pipeline.RequestPipeline;
|
||||
import org.apache.rocketmq.remoting.protocol.BrokerSyncInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.DataVersion;
|
||||
import org.apache.rocketmq.remoting.protocol.NamespaceUtil;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestHeaderRegistry;
|
||||
import org.apache.rocketmq.remoting.protocol.body.BrokerMemberGroup;
|
||||
@@ -183,6 +156,30 @@ import org.apache.rocketmq.store.timer.TimerCheckpoint;
|
||||
import org.apache.rocketmq.store.timer.TimerMessageStore;
|
||||
import org.apache.rocketmq.store.timer.TimerMetrics;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BrokerController {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
|
||||
private static final Logger LOG_PROTECTION = LoggerFactory.getLogger(LoggerName.PROTECTION_LOGGER_NAME);
|
||||
@@ -281,7 +278,6 @@ public class BrokerController {
|
||||
protected TransactionalMessageCheckService transactionalMessageCheckService;
|
||||
protected TransactionalMessageService transactionalMessageService;
|
||||
protected AbstractTransactionalMessageCheckListener transactionalMessageCheckListener;
|
||||
protected Map<Class, AccessValidator> accessValidatorMap = new HashMap<>();
|
||||
protected volatile boolean shutdown = false;
|
||||
protected ShutdownHook shutdownHook;
|
||||
private volatile boolean isScheduleServiceStart = false;
|
||||
@@ -917,8 +913,6 @@ public class BrokerController {
|
||||
|
||||
initialTransaction();
|
||||
|
||||
initialAcl();
|
||||
|
||||
initialRpcHooks();
|
||||
|
||||
initialRequestPipeline();
|
||||
@@ -1052,37 +1046,6 @@ public class BrokerController {
|
||||
|
||||
}
|
||||
|
||||
private void initialAcl() {
|
||||
if (!this.brokerConfig.isAclEnable()) {
|
||||
LOG.info("The broker does not enable acl");
|
||||
return;
|
||||
}
|
||||
|
||||
List<AccessValidator> accessValidators = ServiceProvider.load(AccessValidator.class);
|
||||
if (accessValidators.isEmpty()) {
|
||||
LOG.info("ServiceProvider loaded no AccessValidator, using default org.apache.rocketmq.acl.plain.PlainAccessValidator");
|
||||
accessValidators.add(new PlainAccessValidator());
|
||||
}
|
||||
|
||||
for (AccessValidator accessValidator : accessValidators) {
|
||||
final AccessValidator validator = accessValidator;
|
||||
accessValidatorMap.put(validator.getClass(), validator);
|
||||
this.registerServerRPCHook(new RPCHook() {
|
||||
|
||||
@Override
|
||||
public void doBeforeRequest(String remoteAddr, RemotingCommand request) {
|
||||
//Do not catch the exception
|
||||
validator.validate(validator.parse(request, remoteAddr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterResponse(String remoteAddr, RemotingCommand request, RemotingCommand response) {
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void initialRpcHooks() {
|
||||
|
||||
List<RPCHook> rpcHooks = ServiceProvider.load(RPCHook.class);
|
||||
@@ -2510,10 +2473,6 @@ public class BrokerController {
|
||||
|
||||
}
|
||||
|
||||
public Map<Class, AccessValidator> getAccessValidatorMap() {
|
||||
return accessValidatorMap;
|
||||
}
|
||||
|
||||
public ExecutorService getSendMessageExecutor() {
|
||||
return sendMessageExecutor;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,6 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessValidator;
|
||||
import org.apache.rocketmq.auth.authentication.enums.UserType;
|
||||
import org.apache.rocketmq.auth.authentication.exception.AuthenticationException;
|
||||
import org.apache.rocketmq.auth.authentication.model.Subject;
|
||||
@@ -59,7 +56,6 @@ import org.apache.rocketmq.common.LockCallback;
|
||||
import org.apache.rocketmq.common.MQVersion;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.Pair;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.common.TopicAttributes;
|
||||
import org.apache.rocketmq.common.TopicConfig;
|
||||
import org.apache.rocketmq.common.UnlockCallback;
|
||||
@@ -87,7 +83,6 @@ import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
import org.apache.rocketmq.remoting.common.RemotingHelper;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
|
||||
import org.apache.rocketmq.remoting.netty.NettyRemotingAbstract;
|
||||
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
|
||||
import org.apache.rocketmq.remoting.protocol.LanguageCode;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
@@ -131,11 +126,9 @@ import org.apache.rocketmq.remoting.protocol.body.UserInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CheckRocksdbCqWriteProgressRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CloneGroupOffsetRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.ConsumeMessageDirectlyResultRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateAccessConfigRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateTopicRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateUserRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteAccessConfigRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteSubscriptionGroupRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteTopicRequestHeader;
|
||||
@@ -146,7 +139,6 @@ import org.apache.rocketmq.remoting.protocol.header.ExportRocksDBConfigToJsonReq
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetAllProducerInfoRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetAllTopicConfigResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetBrokerAclConfigResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetBrokerConfigResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumeStatsInBrokerHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumeStatsRequestHeader;
|
||||
@@ -180,7 +172,6 @@ import org.apache.rocketmq.remoting.protocol.header.ResumeCheckHalfMessageReques
|
||||
import org.apache.rocketmq.remoting.protocol.header.SearchOffsetRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.SearchOffsetResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateGlobalWhiteAddrsConfigRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateGroupForbiddenRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateUserRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.ViewBrokerStatsDataRequestHeader;
|
||||
@@ -368,14 +359,6 @@ public class AdminBrokerProcessor implements NettyRequestProcessor {
|
||||
return this.updateAndGetGroupForbidden(ctx, request);
|
||||
case RequestCode.GET_SUBSCRIPTIONGROUP_CONFIG:
|
||||
return this.getSubscriptionGroup(ctx, request);
|
||||
case RequestCode.UPDATE_AND_CREATE_ACL_CONFIG:
|
||||
return updateAndCreateAccessConfig(ctx, request);
|
||||
case RequestCode.DELETE_ACL_CONFIG:
|
||||
return deleteAccessConfig(ctx, request);
|
||||
case RequestCode.GET_BROKER_CLUSTER_ACL_INFO:
|
||||
return getBrokerAclConfigVersion(ctx, request);
|
||||
case RequestCode.UPDATE_GLOBAL_WHITE_ADDRS_CONFIG:
|
||||
return updateGlobalWhiteAddrsConfig(ctx, request);
|
||||
case RequestCode.RESUME_CHECK_HALF_MESSAGE:
|
||||
return resumeCheckHalfMessage(ctx, request);
|
||||
case RequestCode.GET_TOPIC_CONFIG:
|
||||
@@ -828,148 +811,6 @@ public class AdminBrokerProcessor implements NettyRequestProcessor {
|
||||
this.brokerController.getMessageStore().getTimerMessageStore().getTimerMetrics().removeTimingCount(topic);
|
||||
}
|
||||
|
||||
private synchronized RemotingCommand updateAndCreateAccessConfig(ChannelHandlerContext ctx, RemotingCommand request) {
|
||||
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
|
||||
|
||||
try {
|
||||
ensureAclEnabled();
|
||||
|
||||
final CreateAccessConfigRequestHeader requestHeader = request.decodeCommandCustomHeader(CreateAccessConfigRequestHeader.class);
|
||||
AccessValidator accessValidator = this.brokerController.getAccessValidatorMap().get(PlainAccessValidator.class);
|
||||
if (accessValidator.updateAccessConfig(createAccessConfig(requestHeader))) {
|
||||
response.setCode(ResponseCode.SUCCESS);
|
||||
response.setOpaque(request.getOpaque());
|
||||
response.markResponseType();
|
||||
response.setRemark(null);
|
||||
NettyRemotingAbstract.writeResponse(ctx.channel(), request, response);
|
||||
} else {
|
||||
String errorMsg = "The accessKey[" + requestHeader.getAccessKey() + "] corresponding to accessConfig has been updated failed.";
|
||||
LOGGER.warn(errorMsg);
|
||||
response.setCode(ResponseCode.UPDATE_AND_CREATE_ACL_CONFIG_FAILED);
|
||||
response.setRemark(errorMsg);
|
||||
return response;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to generate a proper update accessValidator response", e);
|
||||
response.setCode(ResponseCode.UPDATE_AND_CREATE_ACL_CONFIG_FAILED);
|
||||
response.setRemark(e.getMessage());
|
||||
return response;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private PlainAccessConfig createAccessConfig(final CreateAccessConfigRequestHeader requestHeader) {
|
||||
PlainAccessConfig accessConfig = new PlainAccessConfig();
|
||||
accessConfig.setAccessKey(requestHeader.getAccessKey());
|
||||
accessConfig.setSecretKey(requestHeader.getSecretKey());
|
||||
accessConfig.setWhiteRemoteAddress(requestHeader.getWhiteRemoteAddress());
|
||||
accessConfig.setDefaultTopicPerm(requestHeader.getDefaultTopicPerm());
|
||||
accessConfig.setDefaultGroupPerm(requestHeader.getDefaultGroupPerm());
|
||||
accessConfig.setTopicPerms(UtilAll.split(requestHeader.getTopicPerms(), ","));
|
||||
accessConfig.setGroupPerms(UtilAll.split(requestHeader.getGroupPerms(), ","));
|
||||
accessConfig.setAdmin(requestHeader.isAdmin());
|
||||
return accessConfig;
|
||||
}
|
||||
|
||||
private synchronized RemotingCommand deleteAccessConfig(ChannelHandlerContext ctx, RemotingCommand request) {
|
||||
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
|
||||
|
||||
LOGGER.info("DeleteAccessConfig called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
|
||||
|
||||
try {
|
||||
ensureAclEnabled();
|
||||
|
||||
final DeleteAccessConfigRequestHeader requestHeader = request.decodeCommandCustomHeader(DeleteAccessConfigRequestHeader.class);
|
||||
String accessKey = requestHeader.getAccessKey();
|
||||
AccessValidator accessValidator = this.brokerController.getAccessValidatorMap().get(PlainAccessValidator.class);
|
||||
if (accessValidator.deleteAccessConfig(accessKey)) {
|
||||
response.setCode(ResponseCode.SUCCESS);
|
||||
response.setOpaque(request.getOpaque());
|
||||
response.markResponseType();
|
||||
response.setRemark(null);
|
||||
NettyRemotingAbstract.writeResponse(ctx.channel(), request, response);
|
||||
} else {
|
||||
String errorMsg = "The accessKey[" + requestHeader.getAccessKey() + "] corresponding to accessConfig has been deleted failed.";
|
||||
LOGGER.warn(errorMsg);
|
||||
response.setCode(ResponseCode.DELETE_ACL_CONFIG_FAILED);
|
||||
response.setRemark(errorMsg);
|
||||
return response;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to generate a proper delete accessValidator response", e);
|
||||
response.setCode(ResponseCode.DELETE_ACL_CONFIG_FAILED);
|
||||
response.setRemark(e.getMessage());
|
||||
return response;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private synchronized RemotingCommand updateGlobalWhiteAddrsConfig(ChannelHandlerContext ctx, RemotingCommand request) {
|
||||
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
|
||||
|
||||
try {
|
||||
ensureAclEnabled();
|
||||
|
||||
final UpdateGlobalWhiteAddrsConfigRequestHeader requestHeader = request.decodeCommandCustomHeader(UpdateGlobalWhiteAddrsConfigRequestHeader.class);
|
||||
AccessValidator accessValidator = this.brokerController.getAccessValidatorMap().get(PlainAccessValidator.class);
|
||||
if (accessValidator.updateGlobalWhiteAddrsConfig(UtilAll.split(requestHeader.getGlobalWhiteAddrs(), ","),
|
||||
requestHeader.getAclFileFullPath())) {
|
||||
response.setCode(ResponseCode.SUCCESS);
|
||||
response.setOpaque(request.getOpaque());
|
||||
response.markResponseType();
|
||||
response.setRemark(null);
|
||||
NettyRemotingAbstract.writeResponse(ctx.channel(), request, response);
|
||||
} else {
|
||||
String errorMsg = "The globalWhiteAddresses[" + requestHeader.getGlobalWhiteAddrs() + "] has been updated failed.";
|
||||
LOGGER.warn(errorMsg);
|
||||
response.setCode(ResponseCode.UPDATE_GLOBAL_WHITE_ADDRS_CONFIG_FAILED);
|
||||
response.setRemark(errorMsg);
|
||||
return response;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to generate a proper update globalWhiteAddresses response", e);
|
||||
response.setCode(ResponseCode.UPDATE_GLOBAL_WHITE_ADDRS_CONFIG_FAILED);
|
||||
response.setRemark(e.getMessage());
|
||||
return response;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private RemotingCommand getBrokerAclConfigVersion(ChannelHandlerContext ctx, RemotingCommand request) {
|
||||
final RemotingCommand response = RemotingCommand.createResponseCommand(GetBrokerAclConfigResponseHeader.class);
|
||||
|
||||
try {
|
||||
ensureAclEnabled();
|
||||
|
||||
final GetBrokerAclConfigResponseHeader responseHeader = (GetBrokerAclConfigResponseHeader) response.readCustomHeader();
|
||||
AccessValidator accessValidator = this.brokerController.getAccessValidatorMap().get(PlainAccessValidator.class);
|
||||
|
||||
responseHeader.setVersion(accessValidator.getAclConfigVersion());
|
||||
responseHeader.setBrokerAddr(this.brokerController.getBrokerAddr());
|
||||
responseHeader.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
|
||||
responseHeader.setClusterName(this.brokerController.getBrokerConfig().getBrokerClusterName());
|
||||
|
||||
response.setCode(ResponseCode.SUCCESS);
|
||||
response.setRemark(null);
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Failed to generate a proper getBrokerAclConfigVersion response", e);
|
||||
response.setCode(ResponseCode.SYSTEM_ERROR);
|
||||
response.setRemark(e.getMessage());
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureAclEnabled() {
|
||||
if (!brokerController.getBrokerConfig().isAclEnable()) {
|
||||
throw new AclException("The broker does not enable acl.");
|
||||
}
|
||||
}
|
||||
|
||||
private RemotingCommand getUnknownCmdResponse(ChannelHandlerContext ctx, RemotingCommand request) {
|
||||
String error = " request type " + request.getCode() + " not supported";
|
||||
final RemotingCommand response =
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.apache.rocketmq.broker.util;
|
||||
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.broker.transaction.AbstractTransactionalMessageCheckListener;
|
||||
import org.apache.rocketmq.broker.transaction.TransactionalMessageService;
|
||||
import org.apache.rocketmq.common.utils.ServiceProvider;
|
||||
@@ -25,8 +24,6 @@ import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ServiceProviderTest {
|
||||
|
||||
@Test
|
||||
@@ -41,10 +38,4 @@ public class ServiceProviderTest {
|
||||
AbstractTransactionalMessageCheckListener.class);
|
||||
assertThat(listener).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadAccessValidatorTest() {
|
||||
List<AccessValidator> accessValidators = ServiceProvider.load(AccessValidator.class);
|
||||
assertThat(accessValidators).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
org.apache.rocketmq.acl.plain.PlainAccessValidator
|
||||
+5
-1
@@ -28,12 +28,15 @@ java_library(
|
||||
"@maven//:com_github_luben_zstd_jni",
|
||||
"@maven//:org_lz4_lz4_java",
|
||||
"@maven//:com_alibaba_fastjson",
|
||||
"@maven//:com_alibaba_fastjson2_fastjson2",
|
||||
"@maven//:io_netty_netty_all",
|
||||
"@maven//:io_opentracing_opentracing_api",
|
||||
"@maven//:commons_collections_commons_collections",
|
||||
"@maven//:io_github_aliyunmq_rocketmq_slf4j_api",
|
||||
"@maven//:io_github_aliyunmq_rocketmq_logback_classic",
|
||||
"@maven//:com_google_guava_guava",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:org_yaml_snakeyaml",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -52,8 +55,9 @@ java_library(
|
||||
"@maven//:io_opentracing_opentracing_mock",
|
||||
"@maven//:org_awaitility_awaitility",
|
||||
"@maven//:org_mockito_mockito_junit_jupiter",
|
||||
"@maven//:com_alibaba_fastjson2_fastjson2",
|
||||
],
|
||||
resources = glob(["src/test/resources/certs/*.pem"]) + glob(["src/test/resources/certs/*.key"])
|
||||
resources = glob(["src/test/resources/certs/*.pem"]) + glob(["src/test/resources/certs/*.key"]) + glob(["src/test/resources/**/*.yml"])
|
||||
)
|
||||
|
||||
GenTestRules(
|
||||
|
||||
@@ -62,5 +62,9 @@
|
||||
<groupId>io.github.aliyunmq</groupId>
|
||||
<artifactId>rocketmq-logback-classic</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
+6
-9
@@ -16,15 +16,12 @@
|
||||
*/
|
||||
package org.apache.rocketmq.acl.common;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import org.apache.rocketmq.remoting.RPCHook;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
|
||||
import static org.apache.rocketmq.acl.common.SessionCredentials.ACCESS_KEY;
|
||||
import static org.apache.rocketmq.acl.common.SessionCredentials.SECURITY_TOKEN;
|
||||
import static org.apache.rocketmq.acl.common.SessionCredentials.SIGNATURE;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class AclClientRPCHook implements RPCHook {
|
||||
private final SessionCredentials sessionCredentials;
|
||||
@@ -36,14 +33,14 @@ public class AclClientRPCHook implements RPCHook {
|
||||
@Override
|
||||
public void doBeforeRequest(String remoteAddr, RemotingCommand request) {
|
||||
// Add AccessKey and SecurityToken into signature calculating.
|
||||
request.addExtField(ACCESS_KEY, sessionCredentials.getAccessKey());
|
||||
request.addExtField(SessionCredentials.ACCESS_KEY, sessionCredentials.getAccessKey());
|
||||
// The SecurityToken value is unnecessary,user can choose this one.
|
||||
if (sessionCredentials.getSecurityToken() != null) {
|
||||
request.addExtField(SECURITY_TOKEN, sessionCredentials.getSecurityToken());
|
||||
request.addExtField(SessionCredentials.SECURITY_TOKEN, sessionCredentials.getSecurityToken());
|
||||
}
|
||||
byte[] total = AclUtils.combineRequestContent(request, parseRequestContent(request));
|
||||
String signature = AclUtils.calSignature(total, sessionCredentials.getSecretKey());
|
||||
request.addExtField(SIGNATURE, signature);
|
||||
request.addExtField(SessionCredentials.SIGNATURE, signature);
|
||||
}
|
||||
|
||||
@Override
|
||||
+15
-3
@@ -14,9 +14,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.rocketmq.acl.plain;
|
||||
package org.apache.rocketmq.acl.common;
|
||||
|
||||
public interface RemoteAddressStrategy {
|
||||
public class AclConstants {
|
||||
|
||||
boolean match(PlainAccessResource plainAccessResource);
|
||||
public static final String CONFIG_ACCESS_KEY = "accessKey";
|
||||
|
||||
public static final String CONFIG_SECRET_KEY = "secretKey";
|
||||
|
||||
public static final String PUB = "PUB";
|
||||
|
||||
public static final String SUB = "SUB";
|
||||
|
||||
public static final String DENY = "DENY";
|
||||
|
||||
public static final String PUB_SUB = "PUB|SUB";
|
||||
|
||||
public static final String SUB_PUB = "SUB|PUB";
|
||||
}
|
||||
+5
-4
@@ -16,15 +16,16 @@
|
||||
*/
|
||||
package org.apache.rocketmq.acl.common;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class AclSigner {
|
||||
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
public static final SigningAlgorithm DEFAULT_ALGORITHM = SigningAlgorithm.HmacSHA1;
|
||||
+6
-19
@@ -16,13 +16,6 @@
|
||||
*/
|
||||
package org.apache.rocketmq.acl.common;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
@@ -32,6 +25,12 @@ import org.apache.rocketmq.remoting.RPCHook;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
|
||||
import static org.apache.rocketmq.acl.common.SessionCredentials.CHARSET;
|
||||
|
||||
public class AclUtils {
|
||||
@@ -248,18 +247,6 @@ public class AclUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean writeDataObject(String path, Object dataMap) {
|
||||
Yaml yaml = new Yaml();
|
||||
try (PrintWriter pw = new PrintWriter(path, "UTF-8")) {
|
||||
String dumpAsMap = yaml.dumpAsMap(dataMap);
|
||||
pw.print(dumpAsMap);
|
||||
pw.flush();
|
||||
} catch (Exception e) {
|
||||
throw new AclException(e.getMessage(), e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static RPCHook getAclRPCHook(String fileName) {
|
||||
JSONObject yamlDataObject;
|
||||
try {
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
public class Permission {
|
||||
|
||||
public static final byte DENY = 1;
|
||||
public static final byte ANY = 1 << 1;
|
||||
public static final byte PUB = 1 << 2;
|
||||
public static final byte SUB = 1 << 3;
|
||||
|
||||
public static byte parsePermFromString(String permString) {
|
||||
if (permString == null) {
|
||||
return Permission.DENY;
|
||||
}
|
||||
switch (permString.trim()) {
|
||||
case AclConstants.PUB:
|
||||
return Permission.PUB;
|
||||
case AclConstants.SUB:
|
||||
return Permission.SUB;
|
||||
case AclConstants.PUB_SUB:
|
||||
case AclConstants.SUB_PUB:
|
||||
return Permission.PUB | Permission.SUB;
|
||||
case AclConstants.DENY:
|
||||
return Permission.DENY;
|
||||
default:
|
||||
return Permission.DENY;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -16,12 +16,13 @@
|
||||
*/
|
||||
package org.apache.rocketmq.acl.common;
|
||||
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Properties;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
|
||||
public class SessionCredentials {
|
||||
public static final Charset CHARSET = StandardCharsets.UTF_8;
|
||||
@@ -17,19 +17,6 @@
|
||||
package org.apache.rocketmq.client.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.client.ClientConfig;
|
||||
@@ -61,7 +48,6 @@ import org.apache.rocketmq.common.MQVersion;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.ObjectCreator;
|
||||
import org.apache.rocketmq.common.Pair;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.common.TopicConfig;
|
||||
import org.apache.rocketmq.common.UtilAll;
|
||||
import org.apache.rocketmq.common.attribute.AttributeParser;
|
||||
@@ -99,7 +85,6 @@ import org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException;
|
||||
import org.apache.rocketmq.remoting.netty.NettyClientConfig;
|
||||
import org.apache.rocketmq.remoting.netty.NettyRemotingClient;
|
||||
import org.apache.rocketmq.remoting.netty.ResponseFuture;
|
||||
import org.apache.rocketmq.remoting.protocol.DataVersion;
|
||||
import org.apache.rocketmq.remoting.protocol.LanguageCode;
|
||||
import org.apache.rocketmq.remoting.protocol.NamespaceUtil;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
@@ -115,7 +100,6 @@ import org.apache.rocketmq.remoting.protocol.body.BrokerMemberGroup;
|
||||
import org.apache.rocketmq.remoting.protocol.body.BrokerReplicasInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.BrokerStatsData;
|
||||
import org.apache.rocketmq.remoting.protocol.body.CheckClientRequestBody;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ClusterAclVersionInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ConsumeStatsList;
|
||||
@@ -154,12 +138,10 @@ import org.apache.rocketmq.remoting.protocol.header.CheckRocksdbCqWriteProgressR
|
||||
import org.apache.rocketmq.remoting.protocol.header.CloneGroupOffsetRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.ConsumeMessageDirectlyResultRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.ConsumerSendMsgBackRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateAccessConfigRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateTopicListRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateTopicRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.CreateUserRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteAccessConfigRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteSubscriptionGroupRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.DeleteTopicRequestHeader;
|
||||
@@ -169,7 +151,6 @@ import org.apache.rocketmq.remoting.protocol.header.ExportRocksDBConfigToJsonReq
|
||||
import org.apache.rocketmq.remoting.protocol.header.ExtraInfoUtil;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetAllProducerInfoRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetBrokerAclConfigResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumeStatsInBrokerHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumeStatsRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumerConnectionListRequestHeader;
|
||||
@@ -221,7 +202,6 @@ import org.apache.rocketmq.remoting.protocol.header.UnlockBatchMqRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UnregisterClientRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateAclRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateConsumerOffsetRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateGlobalWhiteAddrsConfigRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateGroupForbiddenRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.UpdateUserRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.ViewBrokerStatsDataRequestHeader;
|
||||
@@ -252,6 +232,20 @@ import org.apache.rocketmq.remoting.protocol.subscription.SubscriptionGroupConfi
|
||||
import org.apache.rocketmq.remoting.rpchook.DynamicalExtFieldRPCHook;
|
||||
import org.apache.rocketmq.remoting.rpchook.StreamTypeRPCHook;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.apache.rocketmq.remoting.protocol.RemotingSysResponseCode.SUCCESS;
|
||||
|
||||
public class MQClientAPIImpl implements NameServerUpdateCallback, StartAndShutdown {
|
||||
@@ -498,112 +492,6 @@ public class MQClientAPIImpl implements NameServerUpdateCallback, StartAndShutdo
|
||||
throw new MQClientException(response.getCode(), response.getRemark());
|
||||
}
|
||||
|
||||
public void createPlainAccessConfig(final String addr, final PlainAccessConfig plainAccessConfig,
|
||||
final long timeoutMillis)
|
||||
throws RemotingException, InterruptedException, MQClientException {
|
||||
CreateAccessConfigRequestHeader requestHeader = new CreateAccessConfigRequestHeader();
|
||||
requestHeader.setAccessKey(plainAccessConfig.getAccessKey());
|
||||
requestHeader.setSecretKey(plainAccessConfig.getSecretKey());
|
||||
requestHeader.setAdmin(plainAccessConfig.isAdmin());
|
||||
requestHeader.setDefaultGroupPerm(plainAccessConfig.getDefaultGroupPerm());
|
||||
requestHeader.setDefaultTopicPerm(plainAccessConfig.getDefaultTopicPerm());
|
||||
requestHeader.setWhiteRemoteAddress(plainAccessConfig.getWhiteRemoteAddress());
|
||||
requestHeader.setTopicPerms(UtilAll.join(plainAccessConfig.getTopicPerms(), ","));
|
||||
requestHeader.setGroupPerms(UtilAll.join(plainAccessConfig.getGroupPerms(), ","));
|
||||
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.UPDATE_AND_CREATE_ACL_CONFIG, requestHeader);
|
||||
|
||||
RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr),
|
||||
request, timeoutMillis);
|
||||
assert response != null;
|
||||
switch (response.getCode()) {
|
||||
case ResponseCode.SUCCESS: {
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new MQClientException(response.getCode(), response.getRemark());
|
||||
}
|
||||
|
||||
public void deleteAccessConfig(final String addr, final String accessKey, final long timeoutMillis)
|
||||
throws RemotingException, InterruptedException, MQClientException {
|
||||
DeleteAccessConfigRequestHeader requestHeader = new DeleteAccessConfigRequestHeader();
|
||||
requestHeader.setAccessKey(accessKey);
|
||||
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.DELETE_ACL_CONFIG, requestHeader);
|
||||
|
||||
RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr),
|
||||
request, timeoutMillis);
|
||||
assert response != null;
|
||||
switch (response.getCode()) {
|
||||
case ResponseCode.SUCCESS: {
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new MQClientException(response.getCode(), response.getRemark());
|
||||
}
|
||||
|
||||
public void updateGlobalWhiteAddrsConfig(final String addr, final String globalWhiteAddrs, String aclFileFullPath,
|
||||
final long timeoutMillis)
|
||||
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
|
||||
UpdateGlobalWhiteAddrsConfigRequestHeader requestHeader = new UpdateGlobalWhiteAddrsConfigRequestHeader();
|
||||
requestHeader.setGlobalWhiteAddrs(globalWhiteAddrs);
|
||||
requestHeader.setAclFileFullPath(aclFileFullPath);
|
||||
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.UPDATE_GLOBAL_WHITE_ADDRS_CONFIG, requestHeader);
|
||||
|
||||
RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr),
|
||||
request, timeoutMillis);
|
||||
assert response != null;
|
||||
switch (response.getCode()) {
|
||||
case ResponseCode.SUCCESS: {
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new MQClientException(response.getCode(), response.getRemark());
|
||||
}
|
||||
|
||||
public ClusterAclVersionInfo getBrokerClusterAclInfo(final String addr,
|
||||
final long timeoutMillis) throws RemotingCommandException, InterruptedException, RemotingTimeoutException,
|
||||
RemotingSendRequestException, RemotingConnectException, MQBrokerException {
|
||||
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_BROKER_CLUSTER_ACL_INFO, null);
|
||||
|
||||
RemotingCommand response = this.remotingClient.invokeSync(MixAll.brokerVIPChannel(this.clientConfig.isVipChannelEnabled(), addr), request, timeoutMillis);
|
||||
assert response != null;
|
||||
switch (response.getCode()) {
|
||||
case ResponseCode.SUCCESS: {
|
||||
GetBrokerAclConfigResponseHeader responseHeader =
|
||||
(GetBrokerAclConfigResponseHeader) response.decodeCommandCustomHeader(GetBrokerAclConfigResponseHeader.class);
|
||||
|
||||
ClusterAclVersionInfo clusterAclVersionInfo = new ClusterAclVersionInfo();
|
||||
clusterAclVersionInfo.setClusterName(responseHeader.getClusterName());
|
||||
clusterAclVersionInfo.setBrokerName(responseHeader.getBrokerName());
|
||||
clusterAclVersionInfo.setBrokerAddr(responseHeader.getBrokerAddr());
|
||||
clusterAclVersionInfo.setAclConfigDataVersion(DataVersion.fromJson(responseHeader.getVersion(), DataVersion.class));
|
||||
HashMap<String, Object> dataVersionMap = JSON.parseObject(responseHeader.getAllAclFileVersion(), HashMap.class);
|
||||
Map<String, DataVersion> allAclConfigDataVersion = new HashMap<>(dataVersionMap.size(), 1);
|
||||
for (Map.Entry<String, Object> entry : dataVersionMap.entrySet()) {
|
||||
allAclConfigDataVersion.put(entry.getKey(), DataVersion.fromJson(JSON.toJSONString(entry.getValue()), DataVersion.class));
|
||||
}
|
||||
clusterAclVersionInfo.setAllAclConfigDataVersion(allAclConfigDataVersion);
|
||||
return clusterAclVersionInfo;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
|
||||
|
||||
}
|
||||
|
||||
public SendResult sendMessage(
|
||||
final String addr,
|
||||
final String brokerName,
|
||||
|
||||
+5
-4
@@ -17,10 +17,6 @@
|
||||
|
||||
package org.apache.rocketmq.acl.common;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.remoting.CommandCustomHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
@@ -29,6 +25,11 @@ import org.apache.rocketmq.remoting.protocol.RequestType;
|
||||
import org.apache.rocketmq.remoting.protocol.header.PullMessageRequestHeader;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static org.apache.rocketmq.acl.common.SessionCredentials.ACCESS_KEY;
|
||||
import static org.apache.rocketmq.acl.common.SessionCredentials.SECURITY_TOKEN;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
-74
@@ -18,8 +18,6 @@ package org.apache.rocketmq.acl.common;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessData;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.remoting.RPCHook;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -31,7 +29,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -206,16 +203,6 @@ public class AclUtilsTest {
|
||||
Assert.assertEquals(AclUtils.expandIP("5::7:6", 6), "0005:0000:0000:0000:0007:0006");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testGetYamlDataObject() throws IOException {
|
||||
try (InputStream is = AclUtilsTest.class.getClassLoader().getResourceAsStream("conf/plain_acl_correct.yml")) {
|
||||
Map<String, Object> map = AclUtils.getYamlDataObject(is, Map.class);
|
||||
Assert.assertNotNull(map);
|
||||
Assert.assertFalse(map.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
private static String randomTmpFile() {
|
||||
String tmpFileName = System.getProperty("java.io.tmpdir");
|
||||
// https://rationalpi.wordpress.com/2007/01/26/javaiotmpdir-inconsitency/
|
||||
@@ -226,67 +213,6 @@ public class AclUtilsTest {
|
||||
return tmpFileName;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeDataObject2YamlFileTest() throws IOException {
|
||||
String targetFileName = randomTmpFile();
|
||||
File transport = new File(targetFileName);
|
||||
Assert.assertTrue(transport.createNewFile());
|
||||
transport.deleteOnExit();
|
||||
|
||||
PlainAccessData aclYamlMap = new PlainAccessData();
|
||||
|
||||
// For globalWhiteRemoteAddrs element in acl yaml config file
|
||||
List<String> globalWhiteRemoteAddrs = new ArrayList<>();
|
||||
globalWhiteRemoteAddrs.add("10.10.103.*");
|
||||
globalWhiteRemoteAddrs.add("192.168.0.*");
|
||||
aclYamlMap.setGlobalWhiteRemoteAddresses(globalWhiteRemoteAddrs);
|
||||
|
||||
// For accounts element in acl yaml config file
|
||||
List<PlainAccessConfig> accounts = new ArrayList<>();
|
||||
PlainAccessConfig accountsMap = new PlainAccessConfig() {
|
||||
{
|
||||
setAccessKey("RocketMQ");
|
||||
setSecretKey("12345678");
|
||||
setWhiteRemoteAddress("whiteRemoteAddress");
|
||||
setAdmin(true);
|
||||
}
|
||||
};
|
||||
accounts.add(accountsMap);
|
||||
aclYamlMap.setAccounts(accounts);
|
||||
Assert.assertTrue(AclUtils.writeDataObject(targetFileName, aclYamlMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateExistedYamlFileTest() throws IOException {
|
||||
String targetFileName = randomTmpFile();
|
||||
File transport = new File(targetFileName);
|
||||
Assert.assertTrue(transport.createNewFile());
|
||||
transport.deleteOnExit();
|
||||
|
||||
PlainAccessData aclYamlMap = new PlainAccessData();
|
||||
|
||||
// For globalWhiteRemoteAddrs element in acl yaml config file
|
||||
List<String> globalWhiteRemoteAddrs = new ArrayList<>();
|
||||
globalWhiteRemoteAddrs.add("10.10.103.*");
|
||||
globalWhiteRemoteAddrs.add("192.168.0.*");
|
||||
aclYamlMap.setGlobalWhiteRemoteAddresses(globalWhiteRemoteAddrs);
|
||||
|
||||
// Write file to yaml file
|
||||
AclUtils.writeDataObject(targetFileName, aclYamlMap);
|
||||
|
||||
PlainAccessData updatedMap = AclUtils.getYamlDataObject(targetFileName, PlainAccessData.class);
|
||||
List<String> globalWhiteRemoteAddrList = updatedMap.getGlobalWhiteRemoteAddresses();
|
||||
globalWhiteRemoteAddrList.clear();
|
||||
globalWhiteRemoteAddrList.add("192.168.1.2");
|
||||
|
||||
// Update file and flush to yaml file
|
||||
AclUtils.writeDataObject(targetFileName, updatedMap);
|
||||
|
||||
PlainAccessData readableMap = AclUtils.getYamlDataObject(targetFileName, PlainAccessData.class);
|
||||
List<String> updatedGlobalWhiteRemoteAddrs = readableMap.getGlobalWhiteRemoteAddresses();
|
||||
Assert.assertEquals("192.168.1.2", updatedGlobalWhiteRemoteAddrs.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getYamlDataIgnoreFileNotFoundExceptionTest() {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.rocketmq.acl.common;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PermissionTest {
|
||||
|
||||
@Test
|
||||
public void fromStringGetPermissionTest() {
|
||||
byte perm = Permission.parsePermFromString("PUB");
|
||||
Assert.assertEquals(perm, Permission.PUB);
|
||||
|
||||
perm = Permission.parsePermFromString("SUB");
|
||||
Assert.assertEquals(perm, Permission.SUB);
|
||||
|
||||
perm = Permission.parsePermFromString("PUB|SUB");
|
||||
Assert.assertEquals(perm, Permission.PUB | Permission.SUB);
|
||||
|
||||
perm = Permission.parsePermFromString("SUB|PUB");
|
||||
Assert.assertEquals(perm, Permission.PUB | Permission.SUB);
|
||||
|
||||
perm = Permission.parsePermFromString("DENY");
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
perm = Permission.parsePermFromString("1");
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
perm = Permission.parsePermFromString(null);
|
||||
Assert.assertEquals(perm, Permission.DENY);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AclExceptionTest() {
|
||||
AclException aclException = new AclException("CAL_SIGNATURE_FAILED",10015);
|
||||
AclException aclExceptionWithMessage = new AclException("CAL_SIGNATURE_FAILED",10015,"CAL_SIGNATURE_FAILED Exception");
|
||||
Assert.assertEquals(aclException.getCode(),10015);
|
||||
Assert.assertEquals(aclExceptionWithMessage.getStatus(),"CAL_SIGNATURE_FAILED");
|
||||
aclException.setCode(10016);
|
||||
Assert.assertEquals(aclException.getCode(),10016);
|
||||
aclException.setStatus("netAddress examine scope Exception netAddress");
|
||||
Assert.assertEquals(aclException.getStatus(),"netAddress examine scope Exception netAddress");
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import org.apache.rocketmq.client.producer.SendStatus;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.ObjectCreator;
|
||||
import org.apache.rocketmq.common.Pair;
|
||||
import org.apache.rocketmq.common.PlainAccessConfig;
|
||||
import org.apache.rocketmq.common.TopicConfig;
|
||||
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
|
||||
import org.apache.rocketmq.common.message.Message;
|
||||
@@ -74,7 +73,6 @@ import org.apache.rocketmq.remoting.protocol.body.BrokerMemberGroup;
|
||||
import org.apache.rocketmq.remoting.protocol.body.BrokerReplicasInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.BrokerStatsData;
|
||||
import org.apache.rocketmq.remoting.protocol.body.BrokerStatsItem;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ClusterAclVersionInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
|
||||
import org.apache.rocketmq.remoting.protocol.body.Connection;
|
||||
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
|
||||
@@ -108,7 +106,6 @@ import org.apache.rocketmq.remoting.protocol.header.ChangeInvisibleTimeRequestHe
|
||||
import org.apache.rocketmq.remoting.protocol.header.ChangeInvisibleTimeResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.EndTransactionRequestHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.ExtraInfoUtil;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetBrokerAclConfigResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumerListByGroupResponseBody;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetConsumerListByGroupResponseHeader;
|
||||
import org.apache.rocketmq.remoting.protocol.header.GetEarliestMsgStoretimeResponseHeader;
|
||||
@@ -364,68 +361,6 @@ public class MQClientAPIImplTest {
|
||||
}, null, null, 0, sendMessageContext, defaultMQProducerImpl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePlainAccessConfig_Success() throws InterruptedException, RemotingException {
|
||||
doAnswer(mock -> {
|
||||
RemotingCommand request = mock.getArgument(1);
|
||||
return createSuccessResponse4UpdateAclConfig(request);
|
||||
}).when(remotingClient).invokeSync(anyString(), any(RemotingCommand.class), anyLong());
|
||||
|
||||
PlainAccessConfig config = createUpdateAclConfig();
|
||||
|
||||
try {
|
||||
mqClientAPI.createPlainAccessConfig(brokerAddr, config, 3 * 1000);
|
||||
} catch (MQClientException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePlainAccessConfig_Exception() throws InterruptedException, RemotingException {
|
||||
doAnswer(mock -> {
|
||||
RemotingCommand request = mock.getArgument(1);
|
||||
return createErrorResponse4UpdateAclConfig(request);
|
||||
}).when(remotingClient).invokeSync(anyString(), any(RemotingCommand.class), anyLong());
|
||||
|
||||
PlainAccessConfig config = createUpdateAclConfig();
|
||||
try {
|
||||
mqClientAPI.createPlainAccessConfig(brokerAddr, config, 3 * 1000);
|
||||
} catch (MQClientException ex) {
|
||||
assertThat(ex.getResponseCode()).isEqualTo(209);
|
||||
assertThat(ex.getErrorMessage()).isEqualTo("corresponding to accessConfig has been updated failed");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAccessConfig_Success() throws InterruptedException, RemotingException {
|
||||
doAnswer(mock -> {
|
||||
RemotingCommand request = mock.getArgument(1);
|
||||
return createSuccessResponse4DeleteAclConfig(request);
|
||||
}).when(remotingClient).invokeSync(anyString(), any(RemotingCommand.class), anyLong());
|
||||
|
||||
String accessKey = "1234567";
|
||||
try {
|
||||
mqClientAPI.deleteAccessConfig(brokerAddr, accessKey, 3 * 1000);
|
||||
} catch (MQClientException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAccessConfig_Exception() throws InterruptedException, RemotingException {
|
||||
doAnswer(mock -> {
|
||||
RemotingCommand request = mock.getArgument(1);
|
||||
return createErrorResponse4DeleteAclConfig(request);
|
||||
}).when(remotingClient).invokeSync(anyString(), any(RemotingCommand.class), anyLong());
|
||||
|
||||
try {
|
||||
mqClientAPI.deleteAccessConfig(brokerAddr, "11111", 3 * 1000);
|
||||
} catch (MQClientException ex) {
|
||||
assertThat(ex.getResponseCode()).isEqualTo(210);
|
||||
assertThat(ex.getErrorMessage()).isEqualTo("corresponding to accessConfig has been deleted failed");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResumeCheckHalfMessage_WithException() throws RemotingException, InterruptedException {
|
||||
doAnswer(mock -> {
|
||||
@@ -1026,35 +961,6 @@ public class MQClientAPIImplTest {
|
||||
return response;
|
||||
}
|
||||
|
||||
private RemotingCommand createErrorResponse4UpdateAclConfig(RemotingCommand request) {
|
||||
RemotingCommand response = RemotingCommand.createResponseCommand(null);
|
||||
response.setCode(ResponseCode.UPDATE_AND_CREATE_ACL_CONFIG_FAILED);
|
||||
response.setOpaque(request.getOpaque());
|
||||
response.markResponseType();
|
||||
response.setRemark("corresponding to accessConfig has been updated failed");
|
||||
return response;
|
||||
}
|
||||
|
||||
private RemotingCommand createErrorResponse4DeleteAclConfig(RemotingCommand request) {
|
||||
RemotingCommand response = RemotingCommand.createResponseCommand(null);
|
||||
response.setCode(ResponseCode.DELETE_ACL_CONFIG_FAILED);
|
||||
response.setOpaque(request.getOpaque());
|
||||
response.markResponseType();
|
||||
response.setRemark("corresponding to accessConfig has been deleted failed");
|
||||
return response;
|
||||
}
|
||||
|
||||
private PlainAccessConfig createUpdateAclConfig() {
|
||||
PlainAccessConfig config = new PlainAccessConfig();
|
||||
config.setAccessKey("Rocketmq111");
|
||||
config.setSecretKey("123456789");
|
||||
config.setAdmin(true);
|
||||
config.setWhiteRemoteAddress("127.0.0.1");
|
||||
config.setDefaultTopicPerm("DENY");
|
||||
config.setDefaultGroupPerm("SUB");
|
||||
return config;
|
||||
}
|
||||
|
||||
private SendMessageRequestHeader createSendMessageRequestHeader() {
|
||||
SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
|
||||
requestHeader.setBornTimestamp(System.currentTimeMillis());
|
||||
@@ -1117,29 +1023,6 @@ public class MQClientAPIImplTest {
|
||||
assertEquals(defaultNsAddr, mqClientAPI.onNameServerAddressChange(defaultNsAddr));
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void testUpdateGlobalWhiteAddrsConfig() throws MQBrokerException, RemotingException, InterruptedException, MQClientException {
|
||||
mqClientAPI.updateGlobalWhiteAddrsConfig(defaultNsAddr, "", "", defaultTimeout);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertGetBrokerClusterAclInfo() throws MQBrokerException, RemotingException, InterruptedException {
|
||||
mockInvokeSync();
|
||||
GetBrokerAclConfigResponseHeader responseHeader = mock(GetBrokerAclConfigResponseHeader.class);
|
||||
when(responseHeader.getBrokerName()).thenReturn(brokerName);
|
||||
when(responseHeader.getBrokerAddr()).thenReturn(defaultBrokerAddr);
|
||||
when(responseHeader.getClusterName()).thenReturn(clusterName);
|
||||
when(responseHeader.getAllAclFileVersion()).thenReturn("{\"key\":{\"stateVersion\":1}}");
|
||||
setResponseHeader(responseHeader);
|
||||
ClusterAclVersionInfo actual = mqClientAPI.getBrokerClusterAclInfo(defaultNsAddr, defaultTimeout);
|
||||
assertNotNull(actual);
|
||||
assertEquals(brokerName, actual.getBrokerName());
|
||||
assertEquals(defaultBrokerAddr, actual.getBrokerAddr());
|
||||
assertEquals(clusterName, actual.getClusterName());
|
||||
assertEquals(1, actual.getAllAclConfigDataVersion().size());
|
||||
assertNull(actual.getAclConfigDataVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertPullMessage() throws MQBrokerException, RemotingException, InterruptedException {
|
||||
PullMessageRequestHeader requestHeader = mock(PullMessageRequestHeader.class);
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
## suggested format
|
||||
|
||||
- accessKey: rocketmq2
|
||||
secretKey:
|
||||
secretKey:
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
# if it is admin, it could access all resources
|
||||
admin: true
|
||||
@@ -57,6 +57,7 @@ java_library(
|
||||
"@maven//:com_google_guava_guava",
|
||||
"@maven//:com_alibaba_fastjson",
|
||||
"@maven//:com_alibaba_fastjson2_fastjson2",
|
||||
"@maven//:commons_codec_commons_codec",
|
||||
"@maven//:io_netty_netty_all",
|
||||
"@maven//:io_opentelemetry_opentelemetry_api",
|
||||
"@maven//:io_opentelemetry_opentelemetry_context",
|
||||
|
||||
@@ -1289,10 +1289,6 @@ public class BrokerConfig extends BrokerIdentity {
|
||||
this.traceTopicEnable = traceTopicEnable;
|
||||
}
|
||||
|
||||
public boolean isAclEnable() {
|
||||
return aclEnable;
|
||||
}
|
||||
|
||||
public void setAclEnable(boolean aclEnable) {
|
||||
this.aclEnable = aclEnable;
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class AclConfigTest {
|
||||
|
||||
@Test
|
||||
public void testGetGlobalWhiteAddrsWhenNull() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
Assert.assertNull("The globalWhiteAddrs should return null", aclConfig.getGlobalWhiteAddrs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGlobalWhiteAddrsWhenEmpty() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
List<String> globalWhiteAddrs = new ArrayList<>();
|
||||
aclConfig.setGlobalWhiteAddrs(globalWhiteAddrs);
|
||||
assertNotNull("The globalWhiteAddrs should never return null", aclConfig.getGlobalWhiteAddrs());
|
||||
assertEquals("The globalWhiteAddrs list should be empty", 0, aclConfig.getGlobalWhiteAddrs().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGlobalWhiteAddrs() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
List<String> expected = Arrays.asList("192.168.1.1", "192.168.1.2");
|
||||
aclConfig.setGlobalWhiteAddrs(expected);
|
||||
assertEquals("Global white addresses should match", expected, aclConfig.getGlobalWhiteAddrs());
|
||||
assertEquals("The globalWhiteAddrs list should be equal to 2", 2, aclConfig.getGlobalWhiteAddrs().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPlainAccessConfigsWhenNull() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
Assert.assertNull("The plainAccessConfigs should return null", aclConfig.getPlainAccessConfigs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPlainAccessConfigsWhenEmpty() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
List<PlainAccessConfig> plainAccessConfigs = new ArrayList<>();
|
||||
aclConfig.setPlainAccessConfigs(plainAccessConfigs);
|
||||
assertNotNull("The plainAccessConfigs should never return null", aclConfig.getPlainAccessConfigs());
|
||||
assertEquals("The plainAccessConfigs list should be empty", 0, aclConfig.getPlainAccessConfigs().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPlainAccessConfigs() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
List<PlainAccessConfig> expected = Arrays.asList(new PlainAccessConfig(), new PlainAccessConfig());
|
||||
aclConfig.setPlainAccessConfigs(expected);
|
||||
assertEquals("Plain access configs should match", expected, aclConfig.getPlainAccessConfigs());
|
||||
assertEquals("The plainAccessConfigs list should be equal to 2", 2, aclConfig.getPlainAccessConfigs().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithNullValues() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
String result = aclConfig.toString();
|
||||
assertNotNull("toString should not be null", result);
|
||||
assertEquals("toString should match", "AclConfig{globalWhiteAddrs=null, plainAccessConfigs=null}", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithEmptyGlobalWhiteAddrsAndPlainAccessConfigs() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
aclConfig.setGlobalWhiteAddrs(Collections.emptyList());
|
||||
aclConfig.setPlainAccessConfigs(Collections.emptyList());
|
||||
String expected = "AclConfig{globalWhiteAddrs=[], plainAccessConfigs=[]}";
|
||||
assertEquals(expected, aclConfig.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithNonEmptyGlobalWhiteAddrsAndPlainAccessConfigs() {
|
||||
AclConfig aclConfig = new AclConfig();
|
||||
List<String> globalWhiteAddrs = Collections.singletonList("192.168.1.1");
|
||||
aclConfig.setGlobalWhiteAddrs(globalWhiteAddrs);
|
||||
PlainAccessConfig plainAccessConfig = new PlainAccessConfig();
|
||||
List<PlainAccessConfig> plainAccessConfigs = Collections.singletonList(plainAccessConfig);
|
||||
aclConfig.setPlainAccessConfigs(plainAccessConfigs);
|
||||
String expected = "AclConfig{globalWhiteAddrs=[192.168.1.1], plainAccessConfigs=[" + plainAccessConfig + "]}";
|
||||
assertEquals("toString should match", expected, aclConfig.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
# 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.
|
||||
|
||||
globalWhiteRemoteAddresses:
|
||||
- 10.10.103.*
|
||||
- 192.168.0.*
|
||||
|
||||
accounts:
|
||||
- accessKey: RocketMQ
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress:
|
||||
admin: false
|
||||
defaultTopicPerm: DENY
|
||||
defaultGroupPerm: SUB
|
||||
topicPerms:
|
||||
- topicA=DENY
|
||||
- topicB=PUB|SUB
|
||||
- topicC=SUB
|
||||
groupPerms:
|
||||
# the group should convert to retry topic
|
||||
- groupA=DENY
|
||||
- groupB=PUB|SUB
|
||||
- groupC=SUB
|
||||
|
||||
- accessKey: rocketmq2
|
||||
secretKey: 12345678
|
||||
whiteRemoteAddress: 192.168.1.*
|
||||
# if it is admin, it could access all resources
|
||||
admin: true
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>rocketmq-acl</artifactId>
|
||||
<artifactId>rocketmq-auth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
|
||||
@@ -193,7 +193,6 @@
|
||||
<module>test</module>
|
||||
<module>distribution</module>
|
||||
<module>openmessaging</module>
|
||||
<module>acl</module>
|
||||
<module>auth</module>
|
||||
<module>example</module>
|
||||
<module>container</module>
|
||||
@@ -545,11 +544,6 @@
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-acl</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-auth</artifactId>
|
||||
|
||||
@@ -21,7 +21,6 @@ java_library(
|
||||
srcs = glob(["src/main/java/**/*.java"]),
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//acl",
|
||||
"//auth",
|
||||
"//broker",
|
||||
"//client",
|
||||
@@ -80,7 +79,6 @@ java_library(
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//acl",
|
||||
"//auth",
|
||||
":proxy",
|
||||
"//:test_deps",
|
||||
|
||||
@@ -51,10 +51,6 @@
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-acl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-auth</artifactId>
|
||||
|
||||
@@ -20,27 +20,20 @@ package org.apache.rocketmq.proxy;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.grpc.protobuf.services.ChannelzService;
|
||||
import io.grpc.protobuf.services.ProtoReflectionService;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessValidator;
|
||||
import org.apache.rocketmq.broker.BrokerController;
|
||||
import org.apache.rocketmq.broker.BrokerStartup;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.common.thread.ThreadPoolMonitor;
|
||||
import org.apache.rocketmq.common.utils.ServiceProvider;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
import org.apache.rocketmq.common.utils.AbstractStartAndShutdown;
|
||||
import org.apache.rocketmq.common.utils.StartAndShutdown;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
import org.apache.rocketmq.proxy.config.Configuration;
|
||||
import org.apache.rocketmq.proxy.config.ConfigurationManager;
|
||||
import org.apache.rocketmq.proxy.config.ProxyConfig;
|
||||
@@ -54,6 +47,11 @@ import org.apache.rocketmq.proxy.remoting.RemotingProtocolServer;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.apache.rocketmq.srvutil.ServerUtil;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ProxyStartup {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggerName.PROXY_LOGGER_NAME);
|
||||
private static final ProxyStartAndShutdown PROXY_START_AND_SHUTDOWN = new ProxyStartAndShutdown();
|
||||
@@ -78,18 +76,17 @@ public class ProxyStartup {
|
||||
|
||||
MessagingProcessor messagingProcessor = createMessagingProcessor();
|
||||
|
||||
List<AccessValidator> accessValidators = loadAccessValidators();
|
||||
// create grpcServer
|
||||
GrpcServer grpcServer = GrpcServerBuilder.newBuilder(executor, ConfigurationManager.getProxyConfig().getGrpcServerPort())
|
||||
.addService(createServiceProcessor(messagingProcessor))
|
||||
.addService(ChannelzService.newInstance(100))
|
||||
.addService(ProtoReflectionService.newInstance())
|
||||
.configInterceptor(accessValidators)
|
||||
.configInterceptor()
|
||||
.shutdownTime(ConfigurationManager.getProxyConfig().getGrpcShutdownTimeSeconds(), TimeUnit.SECONDS)
|
||||
.build();
|
||||
PROXY_START_AND_SHUTDOWN.appendStartAndShutdown(grpcServer);
|
||||
|
||||
RemotingProtocolServer remotingServer = new RemotingProtocolServer(messagingProcessor, accessValidators);
|
||||
RemotingProtocolServer remotingServer = new RemotingProtocolServer(messagingProcessor);
|
||||
PROXY_START_AND_SHUTDOWN.appendStartAndShutdown(remotingServer);
|
||||
|
||||
// start servers one by one.
|
||||
@@ -114,15 +111,6 @@ public class ProxyStartup {
|
||||
log.info(new Date() + " rocketmq-proxy startup successfully");
|
||||
}
|
||||
|
||||
protected static List<AccessValidator> loadAccessValidators() {
|
||||
List<AccessValidator> accessValidators = ServiceProvider.load(AccessValidator.class);
|
||||
if (accessValidators.isEmpty()) {
|
||||
log.info("ServiceProvider loaded no AccessValidator, using default org.apache.rocketmq.acl.plain.PlainAccessValidator");
|
||||
accessValidators.add(new PlainAccessValidator());
|
||||
}
|
||||
return accessValidators;
|
||||
}
|
||||
|
||||
protected static void initConfiguration(CommandLineArgument commandLineArgument) throws Exception {
|
||||
if (StringUtils.isNotBlank(commandLineArgument.getProxyConfigPath())) {
|
||||
System.setProperty(Configuration.CONFIG_PATH_PROPERTY, commandLineArgument.getProxyConfigPath());
|
||||
|
||||
@@ -17,16 +17,6 @@
|
||||
|
||||
package org.apache.rocketmq.proxy.config;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.common.MixAll;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
@@ -38,6 +28,17 @@ import org.apache.rocketmq.proxy.ProxyMode;
|
||||
import org.apache.rocketmq.proxy.common.ProxyException;
|
||||
import org.apache.rocketmq.proxy.common.ProxyExceptionCode;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ProxyConfig implements ConfigFile {
|
||||
private final static Logger log = LoggerFactory.getLogger(LoggerName.PROXY_LOGGER_NAME);
|
||||
public final static String DEFAULT_CONFIG_FILE_NAME = "rmq-proxy.json";
|
||||
@@ -203,8 +204,6 @@ public class ProxyConfig implements ConfigFile {
|
||||
private long renewMaxTimeMillis = TimeUnit.HOURS.toMillis(3);
|
||||
private long renewSchedulePeriodMillis = TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
private boolean enableACL = false;
|
||||
|
||||
private boolean enableAclRpcHookForClusterMode = false;
|
||||
|
||||
private boolean useDelayLevel = false;
|
||||
@@ -1046,14 +1045,6 @@ public class ProxyConfig implements ConfigFile {
|
||||
this.longPollingReserveTimeInMillis = longPollingReserveTimeInMillis;
|
||||
}
|
||||
|
||||
public boolean isEnableACL() {
|
||||
return enableACL;
|
||||
}
|
||||
|
||||
public void setEnableACL(boolean enableACL) {
|
||||
this.enableACL = enableACL;
|
||||
}
|
||||
|
||||
public boolean isEnableAclRpcHookForClusterMode() {
|
||||
return enableAclRpcHookForClusterMode;
|
||||
}
|
||||
|
||||
@@ -24,19 +24,17 @@ import io.grpc.netty.shaded.io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.grpc.netty.shaded.io.netty.channel.epoll.EpollServerSocketChannel;
|
||||
import io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.grpc.netty.shaded.io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
import org.apache.rocketmq.proxy.config.ConfigurationManager;
|
||||
import org.apache.rocketmq.proxy.grpc.interceptor.AuthenticationInterceptor;
|
||||
import org.apache.rocketmq.proxy.grpc.interceptor.ContextInterceptor;
|
||||
import org.apache.rocketmq.proxy.grpc.interceptor.GlobalExceptionInterceptor;
|
||||
import org.apache.rocketmq.proxy.grpc.interceptor.HeaderInterceptor;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GrpcServerBuilder {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggerName.PROXY_LOGGER_NAME);
|
||||
protected NettyServerBuilder serverBuilder;
|
||||
@@ -104,16 +102,11 @@ public class GrpcServerBuilder {
|
||||
return new GrpcServer(this.serverBuilder.build(), time, unit);
|
||||
}
|
||||
|
||||
public GrpcServerBuilder configInterceptor(List<AccessValidator> accessValidators) {
|
||||
// grpc interceptors, including acl, logging etc.
|
||||
this.serverBuilder
|
||||
.intercept(new AuthenticationInterceptor(accessValidators));
|
||||
|
||||
public GrpcServerBuilder configInterceptor() {
|
||||
this.serverBuilder
|
||||
.intercept(new GlobalExceptionInterceptor())
|
||||
.intercept(new ContextInterceptor())
|
||||
.intercept(new HeaderInterceptor());
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.proxy.grpc.interceptor;
|
||||
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import io.grpc.Context;
|
||||
import io.grpc.ForwardingServerCallListener;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.ServerCall;
|
||||
import io.grpc.ServerCallHandler;
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import java.util.List;
|
||||
import org.apache.rocketmq.acl.AccessResource;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.acl.common.AclException;
|
||||
import org.apache.rocketmq.acl.common.AuthenticationHeader;
|
||||
import org.apache.rocketmq.acl.plain.PlainAccessResource;
|
||||
import org.apache.rocketmq.common.constant.GrpcConstants;
|
||||
import org.apache.rocketmq.proxy.common.utils.GrpcUtils;
|
||||
import org.apache.rocketmq.proxy.config.ConfigurationManager;
|
||||
|
||||
public class AuthenticationInterceptor implements ServerInterceptor {
|
||||
protected final List<AccessValidator> accessValidatorList;
|
||||
|
||||
public AuthenticationInterceptor(List<AccessValidator> accessValidatorList) {
|
||||
this.accessValidatorList = accessValidatorList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, W> ServerCall.Listener<R> interceptCall(ServerCall<R, W> call, Metadata headers,
|
||||
ServerCallHandler<R, W> next) {
|
||||
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<R>(next.startCall(call, headers)) {
|
||||
@Override
|
||||
public void onMessage(R message) {
|
||||
GeneratedMessageV3 messageV3 = (GeneratedMessageV3) message;
|
||||
GrpcUtils.putHeaderIfNotExist(headers, GrpcConstants.RPC_NAME, messageV3.getDescriptorForType().getFullName());
|
||||
GrpcUtils.putHeaderIfNotExist(headers, GrpcConstants.SIMPLE_RPC_NAME, messageV3.getDescriptorForType().getName());
|
||||
if (ConfigurationManager.getProxyConfig().isEnableACL()) {
|
||||
try {
|
||||
AuthenticationHeader authenticationHeader = AuthenticationHeader.builder()
|
||||
.remoteAddress(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.REMOTE_ADDRESS))
|
||||
.namespace(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.NAMESPACE_ID))
|
||||
.authorization(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.AUTHORIZATION))
|
||||
.datetime(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.DATE_TIME))
|
||||
.sessionToken(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.SESSION_TOKEN))
|
||||
.requestId(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.REQUEST_ID))
|
||||
.language(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.LANGUAGE))
|
||||
.clientVersion(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.CLIENT_VERSION))
|
||||
.protocol(GrpcConstants.METADATA.get(Context.current()).get(GrpcConstants.PROTOCOL_VERSION))
|
||||
.requestCode(RequestMapping.map(messageV3.getDescriptorForType().getFullName()))
|
||||
.build();
|
||||
|
||||
validate(authenticationHeader, headers, messageV3);
|
||||
super.onMessage(message);
|
||||
} catch (AclException aclException) {
|
||||
throw new StatusRuntimeException(Status.PERMISSION_DENIED, headers);
|
||||
}
|
||||
} else {
|
||||
super.onMessage(message);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void validate(AuthenticationHeader authenticationHeader, Metadata headers, GeneratedMessageV3 messageV3) {
|
||||
for (AccessValidator accessValidator : accessValidatorList) {
|
||||
AccessResource accessResource = accessValidator.parse(messageV3, authenticationHeader);
|
||||
accessValidator.validate(accessResource);
|
||||
|
||||
if (accessResource instanceof PlainAccessResource) {
|
||||
PlainAccessResource plainAccessResource = (PlainAccessResource) accessResource;
|
||||
GrpcUtils.putHeaderIfNotExist(headers, GrpcConstants.AUTHORIZATION_AK, plainAccessResource.getAccessKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-12
@@ -19,13 +19,6 @@ package org.apache.rocketmq.proxy.remoting;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.auth.config.AuthConfig;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.common.future.FutureTaskExt;
|
||||
@@ -65,6 +58,12 @@ import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
import org.apache.rocketmq.remoting.protocol.ResponseCode;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RemotingProtocolServer implements StartAndShutdown, RemotingProxyOutClient {
|
||||
private final static Logger log = LoggerFactory.getLogger(LoggerName.PROXY_LOGGER_NAME);
|
||||
|
||||
@@ -90,11 +89,11 @@ public class RemotingProtocolServer implements StartAndShutdown, RemotingProxyOu
|
||||
protected final ThreadPoolExecutor defaultExecutor;
|
||||
protected final ScheduledExecutorService timerExecutor;
|
||||
|
||||
public RemotingProtocolServer(MessagingProcessor messagingProcessor, List<AccessValidator> accessValidators) {
|
||||
public RemotingProtocolServer(MessagingProcessor messagingProcessor) {
|
||||
this.messagingProcessor = messagingProcessor;
|
||||
this.remotingChannelManager = new RemotingChannelManager(this, messagingProcessor.getProxyRelayService());
|
||||
|
||||
RequestPipeline pipeline = createRequestPipeline(accessValidators, messagingProcessor);
|
||||
RequestPipeline pipeline = createRequestPipeline(messagingProcessor);
|
||||
this.getTopicRouteActivity = new GetTopicRouteActivity(pipeline, messagingProcessor);
|
||||
this.clientManagerActivity = new ClientManagerActivity(pipeline, messagingProcessor, remotingChannelManager);
|
||||
this.consumerManagerActivity = new ConsumerManagerActivity(pipeline, messagingProcessor);
|
||||
@@ -269,8 +268,7 @@ public class RemotingProtocolServer implements StartAndShutdown, RemotingProxyOu
|
||||
return future;
|
||||
}
|
||||
|
||||
protected RequestPipeline createRequestPipeline(List<AccessValidator> accessValidators,
|
||||
MessagingProcessor messagingProcessor) {
|
||||
protected RequestPipeline createRequestPipeline(MessagingProcessor messagingProcessor) {
|
||||
RequestPipeline pipeline = (ctx, request, context) -> {
|
||||
};
|
||||
// add pipeline
|
||||
@@ -278,7 +276,7 @@ public class RemotingProtocolServer implements StartAndShutdown, RemotingProxyOu
|
||||
AuthConfig authConfig = ConfigurationManager.getAuthConfig();
|
||||
if (authConfig != null) {
|
||||
pipeline = pipeline.pipe(new AuthorizationPipeline(authConfig, messagingProcessor))
|
||||
.pipe(new AuthenticationPipeline(accessValidators, authConfig, messagingProcessor));
|
||||
.pipe(new AuthenticationPipeline(authConfig, messagingProcessor));
|
||||
}
|
||||
return pipeline.pipe(new ContextInitPipeline());
|
||||
}
|
||||
|
||||
+1
-16
@@ -18,9 +18,6 @@
|
||||
package org.apache.rocketmq.proxy.remoting.pipeline;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import java.util.List;
|
||||
import org.apache.rocketmq.acl.AccessResource;
|
||||
import org.apache.rocketmq.acl.AccessValidator;
|
||||
import org.apache.rocketmq.auth.authentication.AuthenticationEvaluator;
|
||||
import org.apache.rocketmq.auth.authentication.context.AuthenticationContext;
|
||||
import org.apache.rocketmq.auth.authentication.exception.AuthenticationException;
|
||||
@@ -30,33 +27,21 @@ import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
import org.apache.rocketmq.proxy.common.ProxyContext;
|
||||
import org.apache.rocketmq.proxy.config.ConfigurationManager;
|
||||
import org.apache.rocketmq.proxy.config.ProxyConfig;
|
||||
import org.apache.rocketmq.proxy.processor.MessagingProcessor;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
|
||||
|
||||
public class AuthenticationPipeline implements RequestPipeline {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoggerName.PROXY_LOGGER_NAME);
|
||||
private final List<AccessValidator> accessValidatorList;
|
||||
private final AuthConfig authConfig;
|
||||
private final AuthenticationEvaluator authenticationEvaluator;
|
||||
|
||||
public AuthenticationPipeline(List<AccessValidator> accessValidatorList, AuthConfig authConfig, MessagingProcessor messagingProcessor) {
|
||||
this.accessValidatorList = accessValidatorList;
|
||||
public AuthenticationPipeline(AuthConfig authConfig, MessagingProcessor messagingProcessor) {
|
||||
this.authConfig = authConfig;
|
||||
this.authenticationEvaluator = AuthenticationFactory.getEvaluator(authConfig, messagingProcessor::getMetadataService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, RemotingCommand request, ProxyContext context) throws Exception {
|
||||
ProxyConfig config = ConfigurationManager.getProxyConfig();
|
||||
if (config.isEnableACL()) {
|
||||
for (AccessValidator accessValidator : accessValidatorList) {
|
||||
AccessResource accessResource = accessValidator.parse(request, context.getRemoteAddress());
|
||||
accessValidator.validate(accessResource);
|
||||
}
|
||||
}
|
||||
|
||||
if (!authConfig.isAuthenticationEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -73,17 +73,6 @@ public class RequestCode {
|
||||
|
||||
public static final int GET_CLIENT_CONFIG = 47;
|
||||
|
||||
public static final int UPDATE_AND_CREATE_ACL_CONFIG = 50;
|
||||
|
||||
public static final int DELETE_ACL_CONFIG = 51;
|
||||
|
||||
public static final int GET_BROKER_CLUSTER_ACL_INFO = 52;
|
||||
|
||||
public static final int UPDATE_GLOBAL_WHITE_ADDRS_CONFIG = 53;
|
||||
|
||||
@Deprecated
|
||||
public static final int GET_BROKER_CLUSTER_ACL_CONFIG = 54;
|
||||
|
||||
public static final int GET_TIMER_CHECK_POINT = 60;
|
||||
|
||||
public static final int GET_TIMER_METRICS = 61;
|
||||
|
||||
@@ -74,12 +74,6 @@ public class ResponseCode extends RemotingSysResponseCode {
|
||||
|
||||
public static final int NO_MESSAGE = 208;
|
||||
|
||||
public static final int UPDATE_AND_CREATE_ACL_CONFIG_FAILED = 209;
|
||||
|
||||
public static final int DELETE_ACL_CONFIG_FAILED = 210;
|
||||
|
||||
public static final int UPDATE_GLOBAL_WHITE_ADDRS_CONFIG_FAILED = 211;
|
||||
|
||||
public static final int POLLING_FULL = 209;
|
||||
|
||||
public static final int POLLING_TIMEOUT = 210;
|
||||
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.remoting.protocol.body;
|
||||
|
||||
import java.util.Map;
|
||||
import org.apache.rocketmq.remoting.protocol.DataVersion;
|
||||
import org.apache.rocketmq.remoting.protocol.RemotingSerializable;
|
||||
|
||||
public class ClusterAclVersionInfo extends RemotingSerializable {
|
||||
|
||||
private String brokerName;
|
||||
|
||||
private String brokerAddr;
|
||||
|
||||
@Deprecated
|
||||
private DataVersion aclConfigDataVersion;
|
||||
|
||||
private Map<String, DataVersion> allAclConfigDataVersion;
|
||||
|
||||
private String clusterName;
|
||||
|
||||
public String getBrokerName() {
|
||||
return brokerName;
|
||||
}
|
||||
|
||||
public void setBrokerName(String brokerName) {
|
||||
this.brokerName = brokerName;
|
||||
}
|
||||
|
||||
public String getBrokerAddr() {
|
||||
return brokerAddr;
|
||||
}
|
||||
|
||||
public void setBrokerAddr(String brokerAddr) {
|
||||
this.brokerAddr = brokerAddr;
|
||||
}
|
||||
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
public void setClusterName(String clusterName) {
|
||||
this.clusterName = clusterName;
|
||||
}
|
||||
|
||||
public DataVersion getAclConfigDataVersion() {
|
||||
return aclConfigDataVersion;
|
||||
}
|
||||
|
||||
public void setAclConfigDataVersion(DataVersion aclConfigDataVersion) {
|
||||
this.aclConfigDataVersion = aclConfigDataVersion;
|
||||
}
|
||||
|
||||
public Map<String, DataVersion> getAllAclConfigDataVersion() {
|
||||
return allAclConfigDataVersion;
|
||||
}
|
||||
|
||||
public void setAllAclConfigDataVersion(
|
||||
Map<String, DataVersion> allAclConfigDataVersion) {
|
||||
this.allAclConfigDataVersion = allAclConfigDataVersion;
|
||||
}
|
||||
}
|
||||
-134
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.remoting.protocol.header;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.apache.rocketmq.common.action.Action;
|
||||
import org.apache.rocketmq.common.action.RocketMQAction;
|
||||
import org.apache.rocketmq.common.resource.ResourceType;
|
||||
import org.apache.rocketmq.remoting.CommandCustomHeader;
|
||||
import org.apache.rocketmq.remoting.annotation.CFNotNull;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
|
||||
@RocketMQAction(value = RequestCode.UPDATE_AND_CREATE_ACL_CONFIG, resource = ResourceType.CLUSTER, action = Action.UPDATE)
|
||||
public class CreateAccessConfigRequestHeader implements CommandCustomHeader {
|
||||
|
||||
@CFNotNull
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private String whiteRemoteAddress;
|
||||
|
||||
private boolean admin;
|
||||
|
||||
private String defaultTopicPerm;
|
||||
|
||||
private String defaultGroupPerm;
|
||||
|
||||
// list string,eg: topicA=DENY,topicD=SUB
|
||||
private String topicPerms;
|
||||
|
||||
// list string,eg: groupD=DENY,groupD=SUB
|
||||
private String groupPerms;
|
||||
|
||||
|
||||
@Override
|
||||
public void checkFields() throws RemotingCommandException {
|
||||
|
||||
}
|
||||
|
||||
public String getAccessKey() {
|
||||
return accessKey;
|
||||
}
|
||||
|
||||
public void setAccessKey(String accessKey) {
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
public String getWhiteRemoteAddress() {
|
||||
return whiteRemoteAddress;
|
||||
}
|
||||
|
||||
public void setWhiteRemoteAddress(String whiteRemoteAddress) {
|
||||
this.whiteRemoteAddress = whiteRemoteAddress;
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return admin;
|
||||
}
|
||||
|
||||
public void setAdmin(boolean admin) {
|
||||
this.admin = admin;
|
||||
}
|
||||
|
||||
public String getDefaultTopicPerm() {
|
||||
return defaultTopicPerm;
|
||||
}
|
||||
|
||||
public void setDefaultTopicPerm(String defaultTopicPerm) {
|
||||
this.defaultTopicPerm = defaultTopicPerm;
|
||||
}
|
||||
|
||||
public String getDefaultGroupPerm() {
|
||||
return defaultGroupPerm;
|
||||
}
|
||||
|
||||
public void setDefaultGroupPerm(String defaultGroupPerm) {
|
||||
this.defaultGroupPerm = defaultGroupPerm;
|
||||
}
|
||||
|
||||
public String getTopicPerms() {
|
||||
return topicPerms;
|
||||
}
|
||||
|
||||
public void setTopicPerms(String topicPerms) {
|
||||
this.topicPerms = topicPerms;
|
||||
}
|
||||
|
||||
public String getGroupPerms() {
|
||||
return groupPerms;
|
||||
}
|
||||
|
||||
public void setGroupPerms(String groupPerms) {
|
||||
this.groupPerms = groupPerms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("accessKey", accessKey)
|
||||
.add("secretKey", secretKey)
|
||||
.add("whiteRemoteAddress", whiteRemoteAddress)
|
||||
.add("admin", admin)
|
||||
.add("defaultTopicPerm", defaultTopicPerm)
|
||||
.add("defaultGroupPerm", defaultGroupPerm)
|
||||
.add("topicPerms", topicPerms)
|
||||
.add("groupPerms", groupPerms)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.remoting.protocol.header;
|
||||
|
||||
import org.apache.rocketmq.common.action.Action;
|
||||
import org.apache.rocketmq.common.action.RocketMQAction;
|
||||
import org.apache.rocketmq.common.resource.ResourceType;
|
||||
import org.apache.rocketmq.remoting.CommandCustomHeader;
|
||||
import org.apache.rocketmq.remoting.annotation.CFNotNull;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
|
||||
@RocketMQAction(value = RequestCode.DELETE_ACL_CONFIG, resource = ResourceType.CLUSTER, action = Action.UPDATE)
|
||||
public class DeleteAccessConfigRequestHeader implements CommandCustomHeader {
|
||||
|
||||
@CFNotNull
|
||||
private String accessKey;
|
||||
|
||||
@Override
|
||||
public void checkFields() throws RemotingCommandException {
|
||||
|
||||
}
|
||||
|
||||
public String getAccessKey() {
|
||||
return accessKey;
|
||||
}
|
||||
|
||||
public void setAccessKey(String accessKey) {
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.remoting.protocol.header;
|
||||
|
||||
import org.apache.rocketmq.common.action.Action;
|
||||
import org.apache.rocketmq.common.action.RocketMQAction;
|
||||
import org.apache.rocketmq.common.resource.ResourceType;
|
||||
import org.apache.rocketmq.common.resource.RocketMQResource;
|
||||
import org.apache.rocketmq.remoting.CommandCustomHeader;
|
||||
import org.apache.rocketmq.remoting.annotation.CFNotNull;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
|
||||
@RocketMQAction(value = RequestCode.GET_BROKER_CLUSTER_ACL_INFO, resource = ResourceType.CLUSTER, action = Action.GET)
|
||||
public class GetBrokerAclConfigResponseHeader implements CommandCustomHeader {
|
||||
|
||||
@CFNotNull
|
||||
private String version;
|
||||
|
||||
private String allAclFileVersion;
|
||||
|
||||
@CFNotNull
|
||||
private String brokerName;
|
||||
|
||||
@CFNotNull
|
||||
private String brokerAddr;
|
||||
|
||||
@CFNotNull
|
||||
@RocketMQResource(ResourceType.CLUSTER)
|
||||
private String clusterName;
|
||||
|
||||
@Override
|
||||
public void checkFields() throws RemotingCommandException {
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getBrokerName() {
|
||||
return brokerName;
|
||||
}
|
||||
|
||||
public void setBrokerName(String brokerName) {
|
||||
this.brokerName = brokerName;
|
||||
}
|
||||
|
||||
public String getBrokerAddr() {
|
||||
return brokerAddr;
|
||||
}
|
||||
|
||||
public void setBrokerAddr(String brokerAddr) {
|
||||
this.brokerAddr = brokerAddr;
|
||||
}
|
||||
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
public void setClusterName(String clusterName) {
|
||||
this.clusterName = clusterName;
|
||||
}
|
||||
|
||||
public String getAllAclFileVersion() {
|
||||
return allAclFileVersion;
|
||||
}
|
||||
|
||||
public void setAllAclFileVersion(String allAclFileVersion) {
|
||||
this.allAclFileVersion = allAclFileVersion;
|
||||
}
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.remoting.protocol.header;
|
||||
|
||||
import org.apache.rocketmq.common.action.Action;
|
||||
import org.apache.rocketmq.common.action.RocketMQAction;
|
||||
import org.apache.rocketmq.common.resource.ResourceType;
|
||||
import org.apache.rocketmq.remoting.CommandCustomHeader;
|
||||
import org.apache.rocketmq.remoting.annotation.CFNotNull;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
|
||||
import org.apache.rocketmq.remoting.protocol.RequestCode;
|
||||
|
||||
@RocketMQAction(value = RequestCode.UPDATE_GLOBAL_WHITE_ADDRS_CONFIG, resource = ResourceType.CLUSTER, action = Action.UPDATE)
|
||||
public class UpdateGlobalWhiteAddrsConfigRequestHeader implements CommandCustomHeader {
|
||||
|
||||
@CFNotNull
|
||||
private String globalWhiteAddrs;
|
||||
@CFNotNull
|
||||
private String aclFileFullPath;
|
||||
|
||||
@Override
|
||||
public void checkFields() throws RemotingCommandException {
|
||||
|
||||
}
|
||||
|
||||
public String getGlobalWhiteAddrs() {
|
||||
return globalWhiteAddrs;
|
||||
}
|
||||
|
||||
public void setGlobalWhiteAddrs(String globalWhiteAddrs) {
|
||||
this.globalWhiteAddrs = globalWhiteAddrs;
|
||||
}
|
||||
|
||||
public String getAclFileFullPath() {
|
||||
return aclFileFullPath;
|
||||
}
|
||||
|
||||
public void setAclFileFullPath(String aclFileFullPath) {
|
||||
this.aclFileFullPath = aclFileFullPath;
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* 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.rocketmq.srvutil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.rocketmq.common.ServiceThread;
|
||||
import org.apache.rocketmq.common.UtilAll;
|
||||
import org.apache.rocketmq.common.constant.LoggerName;
|
||||
import org.apache.rocketmq.logging.org.slf4j.Logger;
|
||||
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AclFileWatchService extends ServiceThread {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggerName.COMMON_LOGGER_NAME);
|
||||
|
||||
private final String aclPath;
|
||||
private int aclFilesNum;
|
||||
@Deprecated
|
||||
private final Map<String, String> fileCurrentHash;
|
||||
private Map<String, Long> fileLastModifiedTime;
|
||||
private List<String/**absolute pathname **/> fileList = new ArrayList<>();
|
||||
private final AclFileWatchService.Listener listener;
|
||||
private static final int WATCH_INTERVAL = 5000;
|
||||
private MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
private String defaultAclFile;
|
||||
|
||||
public AclFileWatchService(String path, String defaultAclFile, final AclFileWatchService.Listener listener) throws Exception {
|
||||
this.aclPath = path;
|
||||
this.defaultAclFile = defaultAclFile;
|
||||
this.fileCurrentHash = new HashMap<>();
|
||||
this.fileLastModifiedTime = new HashMap<>();
|
||||
this.listener = listener;
|
||||
|
||||
getAllAclFiles(path);
|
||||
if (new File(this.defaultAclFile).exists() && !fileList.contains(this.defaultAclFile)) {
|
||||
fileList.add(this.defaultAclFile);
|
||||
}
|
||||
this.aclFilesNum = fileList.size();
|
||||
for (int i = 0; i < aclFilesNum; i++) {
|
||||
String fileAbsolutePath = fileList.get(i);
|
||||
this.fileLastModifiedTime.put(fileAbsolutePath, new File(fileAbsolutePath).lastModified());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void getAllAclFiles(String path) {
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
log.info("The default acl dir {} is not exist", path);
|
||||
return;
|
||||
}
|
||||
File[] files = file.listFiles();
|
||||
for (int i = 0; files != null && i < files.length; i++) {
|
||||
String fileName = files[i].getAbsolutePath();
|
||||
File f = new File(fileName);
|
||||
if (fileName.equals(aclPath + File.separator + "tools.yml")) {
|
||||
continue;
|
||||
} else if (fileName.endsWith(".yml") || fileName.endsWith(".yaml")) {
|
||||
fileList.add(fileName);
|
||||
} else if (f.isDirectory()) {
|
||||
getAllAclFiles(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceName() {
|
||||
return "AclFileWatchService";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.info(this.getServiceName() + " service started");
|
||||
|
||||
while (!this.isStopped()) {
|
||||
try {
|
||||
this.waitForRunning(WATCH_INTERVAL);
|
||||
|
||||
if (fileList.size() > 0) {
|
||||
fileList.clear();
|
||||
}
|
||||
getAllAclFiles(aclPath);
|
||||
if (new File(defaultAclFile).exists() && !fileList.contains(defaultAclFile)) {
|
||||
fileList.add(defaultAclFile);
|
||||
}
|
||||
int realAclFilesNum = fileList.size();
|
||||
|
||||
if (aclFilesNum != realAclFilesNum) {
|
||||
log.info("aclFilesNum: " + aclFilesNum + " realAclFilesNum: " + realAclFilesNum);
|
||||
aclFilesNum = realAclFilesNum;
|
||||
log.info("aclFilesNum: " + aclFilesNum + " realAclFilesNum: " + realAclFilesNum);
|
||||
Map<String, Long> fileLastModifiedTime = new HashMap<>(realAclFilesNum);
|
||||
for (int i = 0; i < realAclFilesNum; i++) {
|
||||
String fileAbsolutePath = fileList.get(i);
|
||||
fileLastModifiedTime.put(fileAbsolutePath, new File(fileAbsolutePath).lastModified());
|
||||
}
|
||||
this.fileLastModifiedTime = fileLastModifiedTime;
|
||||
listener.onFileNumChanged(aclPath);
|
||||
} else {
|
||||
for (int i = 0; i < aclFilesNum; i++) {
|
||||
String fileName = fileList.get(i);
|
||||
Long newLastModifiedTime = new File(fileName).lastModified();
|
||||
if (!newLastModifiedTime.equals(fileLastModifiedTime.get(fileName))) {
|
||||
fileLastModifiedTime.put(fileName, newLastModifiedTime);
|
||||
listener.onFileChanged(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn(this.getServiceName() + " service has exception. ", e);
|
||||
}
|
||||
}
|
||||
log.info(this.getServiceName() + " service end");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private String hash(String filePath) throws IOException {
|
||||
Path path = Paths.get(filePath);
|
||||
md.update(Files.readAllBytes(path));
|
||||
byte[] hash = md.digest();
|
||||
return UtilAll.bytes2string(hash);
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
/**
|
||||
* Will be called when the target file is changed
|
||||
*
|
||||
* @param aclFileName the changed file absolute path
|
||||
*/
|
||||
void onFileChanged(String aclFileName);
|
||||
|
||||
/**
|
||||
* Will be called when the number of the acl file is changed
|
||||
*
|
||||
* @param path the path of the acl dir
|
||||
*/
|
||||
void onFileNumChanged(String path);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ java_library(
|
||||
"//common",
|
||||
"//remoting",
|
||||
"@maven//:com_alibaba_fastjson",
|
||||
"@maven//:com_alibaba_fastjson2_fastjson2",
|
||||
"@maven//:com_conversantmedia_disruptor",
|
||||
"@maven//:com_google_guava_guava",
|
||||
"@maven//:commons_collections_commons_collections",
|
||||
|
||||
@@ -51,7 +51,7 @@ Method cloneGroupOffset(boolean,java.lang.String,java.lang.String,java.lang.Stri
|
||||
Method consumeMessageDirectly(java.lang.String,java.lang.String,java.lang.String) : public throws (org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult)
|
||||
Method consumeMessageDirectly(java.lang.String,java.lang.String,java.lang.String,java.lang.String) : public throws (org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult)
|
||||
Method createAndUpdateKvConfig(java.lang.String,java.lang.String,java.lang.String) : public throws (void)
|
||||
Method createAndUpdatePlainAccessConfig(java.lang.String,org.apache.rocketmq.common.PlainAccessConfig) : public throws (void)
|
||||
Method createAndUpdatePlainAccessConfig(java.lang.String,org.apache.rocketmq.auth.migration.plain.PlainAccessConfig) : public throws (void)
|
||||
Method createAndUpdateSubscriptionGroupConfig(java.lang.String,org.apache.rocketmq.remoting.protocol.subscription.SubscriptionGroupConfig) : public throws (void)
|
||||
Method createAndUpdateTopicConfig(java.lang.String,org.apache.rocketmq.common.TopicConfig) : public throws (void)
|
||||
Method createOrUpdateOrderConf(boolean,java.lang.String,java.lang.String) : public throws (void)
|
||||
@@ -66,7 +66,7 @@ Method deleteSubscriptionGroup(java.lang.String,java.lang.String) : public throw
|
||||
Method deleteTopicInBroker(java.lang.String,java.util.Set) : public throws (void)
|
||||
Method deleteTopicInNameServer(java.lang.String,java.lang.String,java.util.Set) : public throws (void)
|
||||
Method earliestMsgStoreTime(org.apache.rocketmq.common.message.MessageQueue) : public throws (long)
|
||||
Method examineBrokerClusterAclConfig(java.lang.String) : public throws (org.apache.rocketmq.common.AclConfig)
|
||||
Method examineBrokerClusterAclConfig(java.lang.String) : public throws (org.apache.rocketmq.auth.migration.plain.AclConfig)
|
||||
Method examineBrokerClusterAclVersionInfo(java.lang.String) : public throws (org.apache.rocketmq.remoting.protocol.body.ClusterAclVersionInfo)
|
||||
Method examineBrokerClusterInfo() : public throws (org.apache.rocketmq.remoting.protocol.body.ClusterInfo)
|
||||
Method examineConsumeStats(java.lang.String) : public throws (org.apache.rocketmq.remoting.protocol.admin.ConsumeStats)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user