1、為什麼要開啟ACL
透過之前的文章我們已經知道怎麼安裝RocketMq了。如果你還不會安裝RocketMq可以檢視我的這篇文章:快速入門一篇搞定RocketMq-實現微服務實戰落地 進行軟體安裝,附文章地址:https://www.cnblogs.com/sowler/p/18173752
。雖說已經安裝成功了,但是它現在在伺服器上面還處於"裸奔"狀態。如果是公司內網伺服器還好,有一層安全保障。但是如果是公網伺服器駭客可以根據RocketMq埠號入侵伺服器系統植入木馬病毒,給伺服器帶來安全漏洞。所以如果部署在公網環境下,強烈建議開啟RocketMq的ACL機制以加強系統的安全性。
2、ACL的作用
ACL主要是為了增強系統的安全性和保護訊息佇列資料的機密性。透過ACL,可以限制使用者或應用程式對訊息佇列的訪問許可權,只有經過授權的使用者才能進行相關操作,如傳送訊息、消費訊息等。防止未經授權的使用者或惡意應用程式對訊息佇列進行操作,減少潛在的安全風險和資料洩露的可能性。同時,ACL還可以幫助管理者更好地控制系統的訪問許可權,提高系統的可控性和安全性。總體來說,開啟ACL是一種有效的安全措施,可以保護RocketMq系統免受未經授權的訪問和潛在的安全威脅。
3、ACL是什麼
RocketMQ的ACL(Access Control List)是一種安全機制,用於對訊息中介軟體的訪問進行授權和限制。ACL機制可以確保只有具備相應許可權的使用者才能執行特定的操作,從而保護訊息系統的安全性。而ACL管理員可以對以下操作進行細粒度的控制和許可權管理:
- Topic級別許可權控制: 管理員可以對每個Topic設定讀寫許可權,決定哪些使用者或角色有權傳送和訂閱該主題的訊息。
- Consumer組許可權控制: 管理員可以為每個消費者組分配訂閱許可權,控制哪些使用者或角色有權使用該消費者組並接收訊息。
- IP地址訪問控制: 管理員可以基於客戶端的IP地址進行訪問控制,只允許特定的IP地址範圍訪問訊息中介軟體。
4、伺服器開啟ACL
首先我們檢視RocketMq官網選擇4.X版本的文件進行檢視,找到控制許可權選單。連結:https://rocketmq.apache.org/zh/docs/4.x/bestPractice/04access
透過說明,我們可以看到許可權控制配置檔案位置在 /conf/plain_acl.yml
,知道配置檔案後進入 conf
目錄,首先先備份一份檔案防止後面改錯了無法恢復,然後在編輯該檔案。
#備份檔案
cp plain_acl.yml plain_acl.yml.init.bak
#編輯檔案
vim plain_acl.yml
配置資訊如下
#白名單中,不會走acl鑑權
globalWhiteRemoteAddresses:
#- 192.168.0.102
accounts: #使用者資訊,預設配置了兩個使用者資訊。一個管理員使用者,一個普通使用者
- accessKey: rocket0001Mq #使用者名稱
secretKey: 1234asdf #密碼
whiteRemoteAddress: #192.168.0.102
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: rocketAdminMq #使用者名稱
secretKey: admin1234asdf #密碼
whiteRemoteAddress: #192.168.1.*
# if it is admin, it could access all resources
admin: true
透過官網文件我們可以看到配置說明
許可權說明:
plain_acl.yml
配置檔案中按照上述說明定義好許可權屬性後,接下來我們需要修改 broker.conf
配置檔案開啟ACL開關。官網文件上面也給了相關說明,參照官網配置即可。
編輯 vim broker.conf
檔案,在檔案末尾加入配置 aclEnable=true
#所屬叢集名字
brokerClusterName=DefaultCluster
#broker名字,叢集的時候不同的配置檔案填寫的不一樣,如果在這裡使用:broker-a,在另外一個使用:broker-b
brokerName=broker-a
#0表示Master,>0表示Slave
brokerId=0
#刪除檔案時間點,預設凌晨4點
deleteWhen=04
#檔案保留時間,預設48小時
fileReservedTime=48
#Broker角色 ASYNC_MASTER 非同步複製/SYNC_MASTER 同步雙寫
brokerRole=ASYNC_MASTER
##刷盤方式 ASYNC_FLUSH 非同步刷盤 SYNC_FLUSH 同步刷盤
flushDiskType=ASYNC_FLUSH
#nameServer地址,多個,分號分割
namesrvAddr=192.168.42.130:9876
#設定IP 公網Ip
brokerIP1=192.168.42.130
#允許Broker自動建立Topic
autoCreateTopicEnable=true
#Broker 對外服務的監聽埠
listenPort=10911
#開啟ACL安全認證
aclEnable=true
開啟後重新啟動 Broker
程式。重啟成功後,如果中間需要修改 plain_acl.yml
配置檔案,修改成功後,不需要重新啟動 BrokerStartup
重新了。ACL有自動過載機制,會自動載入已經修改的 plain_acl.yml
配置檔案。
5、rocketmq-dashboard 開啟認證
透過伺服器端開啟ACL後,在開啟MQ監控中心 rocketmq-dashboard
發現報錯了,已經連線不上mq伺服器了,這就說明ACL開啟成功了。報錯資訊 No accessKey is configured
[2024-05-17 11:53:30.956] INFO create MQAdmin instance ClientConfig [namesrvAddr=192.168.42.130:9876, clientIP=192.168.1.4, instanceName=1715918010272, clientCallbackExecutorThreads=8, pollNameServerInterval=30000, heartbeatBrokerInterval=30000, persistConsumerOffsetInterval=5000, pullTimeDelayMillsWhenException=1000, unitMode=false, unitName=null, vipChannelEnabled=false, useTLS=false, language=JAVA, namespace=null] success.
[2024-05-17 11:53:31.149] ERROR Unexpected error occurred in scheduled task
java.lang.RuntimeException: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 1 DESC: org.apache.rocketmq.acl.common.AclException: No accessKey is configured, org.apache.rocketmq.acl.plain.PlainPermissionLoader.validate(PlainPermissionLoader.java:189) BROKER: 192.168.42.130:10911
For more information, please visit the url, http://rocketmq.apache.org/docs/faq/
at com.google.common.base.Throwables.propagate(Throwables.java:241)
at org.apache.rocketmq.dashboard.task.DashboardCollectTask.collectTopic(DashboardCollectTask.java:161)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
at java.util.concurrent.FutureTask.run(FutureTask.java)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 1 DESC: org.apache.rocketmq.acl.common.AclException: No accessKey is configured, org.apache.rocketmq.acl.plain.PlainPermissionLoader.validate(PlainPermissionLoader.java:189) BROKER: 192.168.42.130:10911
所以我們需要透過賬號密碼來連線mq伺服器,在rocketmq-dashboard
的配置檔案 application.properties
中新增賬號密碼資訊。
rocketmq.config.accessKey=rocketAdminMq
rocketmq.config.secretKey=admin1234asdf
新增配置成功後重新打包部署到伺服器。啟動成功再次訪問 rocketmq-dashboard
沒有報錯,啟動成功。
6、Java透過認證方式連線
RocketMq開啟ACL後,在不配置賬號密碼情況下,啟動專案傳送MQ訊息的時候也會報錯。報錯資訊如下:
2024-05-18 16:37:54.260 ERROR -[TaskUtils.java:95]- Unexpected error occurred in scheduled task
org.springframework.messaging.MessagingException: Send [3] times, still failed, cost [90]ms, Topic: blog_operation_sow, BrokersSent: [broker-a, broker-a, broker-a]
Caused by: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 1 DESC: org.apache.rocketmq.acl.common.AclException: No accessKey is configured, org.apache.rocketmq.acl.plain.PlainPermissionManager.validate(PlainPermissionManager.java:403) BROKER: 192.168.42.130:9876
No accessKey is configured
透過報錯資訊顯示,需要配置賬號和密碼,所以需要配置ACL的連線資訊連線Mq伺服器傳送訊息。配置檔案新增資訊:
rocketmq: # rocketMQ配置
# name server地址
name-server: 192.168.42.130:9876
producer:
group: message_group
# 傳送訊息超時時間,預設3000
sendMessageTimeout: 10000
# 傳送訊息失敗重試次數,預設2
retryTimesWhenSendFailed: 2
# 非同步訊息重試此處,預設2
retryTimesWhenSendAsyncFailed: 2
# 訊息最大長度,預設1024 * 1024 * 4(預設4M)
maxMessageSize: 4096
# 壓縮訊息閾值,預設4k(1024 * 4)
compressMessageBodyThreshold: 4096
# 是否在內部傳送失敗時重試另一個broker,預設false
retryNextServer: false
access-key: rocketAdminMq # 擁有改 ‘message_group’組傳送許可權的使用者資訊
secret-key: admin1234asdf # 密碼
consumer:
pull-batch-size: 10
group: message_group
access-key: rocketAdminMq # 擁有改‘message_group’組消費許可權的使用者資訊
secret-key: admin1234asdf # 密碼
配置成功後,測試訊息傳送資訊:
// 定時向Mq傳送資料
@Component
public class RocketStorage {
@Autowired
private RocketMQTemplate rocketMQTemplate;
@Scheduled(fixedDelay = 1000L * 60,initialDelay = 1000L * 20)
public void store() {
//String message = String.format("%s,%s,%s",value,type,timestamp);
System.out.println("aaaaaa");
rocketMQTemplate.convertAndSend("blog_operation_sow","aaaaaaaaa");
}
}
消費者監聽接收資料:
@RocketMQMessageListener(consumerGroup = "message_group",topic = "blog_operation_sow")
public class RocketDataConsumer implements RocketMQListener {
@Autowired
@Qualifier("dataPersist")
private IDataPersist dataPersist;
@Override
public void onMessage(Object o) {
log.info("Operation RocketMq 接收到的資訊 . . . . . .:{}",o);
dataPersist.put(o.toString(),1,System.currentTimeMillis());
}
}
啟動專案檢視控制檯資訊,可以看到資料傳送和接收成功。
7、Java開啟認證踩坑說明
7.1 問題記錄
在配置檔案加入 access-key
和 secret-key
後,剛開始一直報 AclException: No accessKey is configured
錯誤,但是配置檔案中已經配置賬號密碼資訊了。不知道為什麼沒有生效。後來看了一下引入的Maven依賴版本為:
<!--RocketMQ-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
透過IDEA檢視依賴jar包發現引入的RocketMq依賴版本高了。
透過上圖可以看到,我們引入的客戶端版本是4.9.1版本,但是伺服器目前部署的版本是4.4.0。然後以為是maven依賴引入的版本太高了,就把rocketMq依賴降到了4.4.0版本。maven依賴如下:
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
再次透過IDEA檢視客戶端依賴,發現版本已經改為4.4.0了
修改maven依賴成功後,再次啟動專案。以為這次會啟動成功,但是還是啟動失敗了。版本問題已經解決了,就不是版本問題了。後來看了下相關問題說明。發現RocketMq是在4.4.0版本才開始有ACl認證的,可能是這個版本客戶端不支援透過yaml
配置檔案配置ACl的賬號密碼資訊。需要手動進行編寫Java配置檔案進行傳送訊息。然後我就直接放棄了這種方法,直接升級伺服器RocketMq版本從4.4.0升級為4.9.1。
7.2 升級版本
既然決定升級伺服器RocketMq版本資訊了,那就開幹。有了之前的安裝經驗,這次也很好安裝。首先在官網下載RocketMq的4.9.1版本。地址:https://rocketmq.apache.org/download
下載成功後上傳伺服器到rocketMq目錄下。
進入rocktmq-4.9.1
目錄,按照之前的步驟進行操作即可。先修改啟動指令碼,先備份在修改。進入 bin
目錄下開始備份。
cp runserver.sh runserver.sh.init.bak
cp runbroker.sh runbroker.sh.init.bak
修改JVM引數即可。備份成功後,然後在進入 conf
目錄,修改配置檔案資訊並開啟ACL配置,如何開啟ACL和上面操作一致。我們也可以備份一下 broker.conf
和 plain_acl.yml
檔案,把在rocketmq-4.4.0
目錄裡面的配置資訊直接複製到 rocketmq-4.9.1
目錄下面。複製成功後,給需要給配置檔案授可執行許可權。
chmod +x broker.conf plain_acl.yml
接下來就可以啟動rocketmq了,按照之前方式啟動即可。先啟動 namesrv
在啟動 broker
。
nohup sh bin/mqnamesrv -n 192.168.42.130:9876 > /dev/null 2>&1 &
nohup sh bin/mqbroker -n 192.168.42.130:9876 -c conf/broker.conf autoCreateTopicEnable=true >/dev/null 2>&1 &
啟動成功後,版本就升級成功了。由於rocketmq預設採用持久化儲存,當使用持久化儲存模式時,訊息會被寫入磁碟,並儲存在指定的儲存路徑下。預設情況下,儲存路徑為$HOME/store
也可以透過配置檔案進行修改。在儲存路徑下,RocketMQ會根據一些規則和目錄結構來組織訊息儲存檔案。其中,訊息資料檔案commitlog
儲存在$HOME/store/commitlog
目錄下,而消費進度檔案 consumequeue
儲存在$HOME/store/consumequeue
目錄下。由於有持久化儲存,所以原來的資料也不會丟失。
7.3 檢視監控
由於RocketMq的配置檔案還是採用之前的,所以不需要改動 rocketmq-dashboard
可以直接訪問地址。檢視叢集資訊:
從上圖version
版本可以看出當前版本為 4.9.1
說明已經連線升級成功了。可以檢視監控資料:
至此,RockeMq伺服器版本升級完畢。
8、總結
透過以上方式,RocketMq安全措施就配置成功了。這是我自己在使用RocketMq的搭建過程,分享出來讓大家少走彎路,中間也許會有一些地方考慮不周,歡迎各位指點。感謝大家閱讀。
公眾號文章連結:https://mp.weixin.qq.com/s/XTB9rrtpAh5q9QI6LkqSEw 如果文章對你有所幫助,歡迎大家點個推薦和關注。