Nacos配置安全最佳實踐

前言



配置管理作爲軟件開發中重要的一環,肩負着連接代碼和環境的職責,能很好的分離開發人員和維護人員的關注點。

Nacos 的配置管理功能就很好地滿足了雲原生應用對於配置管理的需求:既能做到配置和代碼分離,也能做到配置的動態修改。

在 1月份,Nacos 出了一個安全漏洞,外部用戶能夠僞裝爲 Nacos-server 來獲取/修改配置( https://github.com/alibaba/nacos/issues/4593 )。確認問題後,Nacos 火速修復了漏洞,而阿里雲的微服務引擎(MSE)也已在 1月末將修復方案反向移植到 MSE 上的 Nacos 實例上。

在本文中,我們將會從全局視角入手,討論如何才能保證 Nacos 配置的安全性(security),即如何保證配置信息不被惡意用戶獲取或者泄漏。


Nacos 配置架構



Nacos 配置部分的整體架構如下:


對於上圖中的每一條鏈路,都需要考慮有沒有兩個基本的安全動作:認證(Identification)和鑑權(Authentication)。

從上圖可以看到,配置信息可能的泄漏方式有:

  • 通過 Nacos-client 獲取配置。
  • 通過控制檯獲取配置。
  • 通過服務器之間的通信協議獲取配置。
  • 直接訪問持久化層(比如 DB)獲取配置。

可能的泄漏點如下:


認證
鑑權
Nacos 客戶端
未登錄用戶通過客戶端獲取/修改配置
用戶通過客戶端獲取/修改了未授權的配置
配置控制檯
未登錄用戶通過控制檯獲取/修改配置
用戶通過控制檯獲取/修改了未授權的配置
Nacos 集羣內
用戶僞裝爲 Nacos 集羣獲取/修改配置
不需要
持久化層
用戶直接查 DB,獲取/修改配置
不需要


Nacos 客戶端場景的認證和鑑權



在 Nacos 客戶端嘗試從服務端獲取配置時,服務端需要確認客戶端的身份,並確認該身份有權限獲取配置。

開源版本的 Nacos


在默認的 Nacos server 配置中,不會對客戶端鑑權,即任何能訪問 Nacos server 的用戶,都可以直接獲取 Nacos 中存儲的配置。比如一個黑客攻進了企業內網,就能獲取所有的業務配置,這樣肯定會有安全隱患。

所以需要先開啓 Nacos server 的鑑權。在 Nacos server 上修改 application.properties 中的 nacos.core.auth.enabled 值爲 true 即可:

  
  
  
nacos.core.auth.enabled=true

如上設置後,Nacos 客戶端獲取配置時,需要設置上對應的用戶名和密碼,才能獲取配置

  
  
  
String serverAddr = "{serverAddr}";Properties properties = new Properties();properties.put("serverAddr", serverAddr);properties.put("username","nacos-readonly");properties.put("password","nacos");ConfigService configService = NacosFactory.createConfigService(properties);

上面講了如何認證用戶,即如何確定現在是哪一個用戶在訪問,但還需要識別用戶的權限,當用戶訪問沒有權限獲取對應配置的時候,比如庫存服務嘗試獲取支付服務的配置時,就會失敗

我們可以在開源的 Nacos 控制檯上創建用戶、設置權限。步驟如下:

首先,訪問 localhost:8848/nacos 並登錄,在 權限控制->用戶列表 頁面,添加用戶:


權限控制->角色管理,綁定用戶和角色:


給對應角色添加權限,在 權限控制->權限管理 頁面,添加權限:


經過如上配置後,readonly-user 就只能訪問 public 命名空間下的配置了。


阿里雲 MSE-AK/SK


對於小團隊,用用戶名和密碼來做認證鑑權是足夠的。但對於中大型團隊,密碼的定期更換、人員的頻繁變動等,都會導致用戶名和密碼頻繁變動。

這時,使用用戶名和密碼認證鑑權就需要頻繁修改併發布應用。爲了解決這個問題,Nacos 也提供了基於 AK/SK 的認證方案 、ECS關聯RAM角色的方案,可以避免用戶名和密碼修改導致的頻繁發佈問題。

以阿里雲 MSE 爲例,阿里雲用戶已經普遍使用了阿里雲訪問控制服務(RAM)作爲權限系統,如果 MSE 和開源一樣,使用用戶名和密碼實現認證和鑑權的話,那麼用戶就需要在 RAM 和 MSE Nacos 兩個地方配置權限。這樣既不方便用戶權限的統一管理、審查,也給用戶帶來了不一致的體驗。

所以 MSE(微服務引擎)提供了基於 AK/SK 的認證方式,操作示例如下:

首先,在 MSE 上申請一個 Nacos 實例(並記下實例 id),然後在 實例詳情->參數設置 界面,將 ConfigAuthEnabled(配置鑑權)參數設置爲 true,這樣匿名用戶就無法獲取配置:


然後就可以在阿里雲RAM系統上配置相關權限。RAM子賬號的權限系統可以簡單表示如下:


  • 第一步:創建 RAM 權限策略如下:



圖中,mse:Get*、mse:List*、mse:Query* 表示能讀取配置,mse:* 表示所有權限,包括修改權限。

acs:mse:*:*:instance/${instanceId} 表示授權到實例級別,acs:mse:*:*:instance/${instanceId}/${namespaceId} 表示授權到命名空間級別。

  • 第二步:創建用戶並賦予權限:


填寫用戶名稱:


然後獲取到用戶的 AK/SK


給這個用戶對應的權限:


  • 最後,只需要在代碼中添加 AK/SK 就可以了:


  
  
  
String serverAddr = "{serverAddr}";Properties properties = new Properties();properties.put("serverAddr", serverAddr);properties.put(PropertyKeyConst.ACCESS_KEY, "${accessKey}");properties.put(PropertyKeyConst.SECRET_KEY, "${secret}");ConfigService configService = NacosFactory.createConfigService(properties);

經過如上配置,客戶端在訪問 MSE 上購買的 Nacos 實例的時候,MSE 會校驗 AK 和簽名,確認該用戶是合法的用戶,並校驗權限,否則拒絕提供服務。

阿里雲 MSE- 基於 ECS 的 Ram 角色認證


當然,在上面的使用方式中,還是要在初始配置(比如 srping-cloud-alibaba-nacos-config 中的 bootstrap.yml 文件)中配置 AK/SK。黑客入侵內網、或者源碼泄漏時,也會存在 AK/SK 泄漏,導致配置信息泄漏的風險

在這種情況下,推薦使用 ECS 關聯的 RAM 角色來做認證。

ECS 關聯 RAM 角色對應的授權模型如下:


上述的關鍵步驟在角色扮演。只有關聯了 RAM 角色的雲服務器,才能成功扮演角色,從而獲取操作 MSE Nacos 實例的權限。

如果黑客只獲取了代碼,也無法成功扮演 RAM 角色,無法操作 MSE Nacos 實例。 如果機器被攻破,那也能在阿里雲控制檯上取消雲服務器關聯的角色,及時止損。

具體的操作步驟如下:

  • 第一步,創建 MSE Nacos 實例,並創建對應的權限策略(上文有說明,此處不贅述)。

  • 第二步,創建 RAM 角色並授權。


創建 RAM 角色:



創建角色後,爲該角色添加對應的權限策略:


  • 第三步,將該角色和 ECS 關聯:


在對應的 ECS 詳情頁面,點擊 授予/收回 RAM 角色


選擇對應的角色並授予


  • 最後一步,在代碼中 指定 RAM 角色 即可:


String serverAddr = "{serverAddr}";Properties properties = new Properties();properties.put("serverAddr", serverAddr);properties.put(PropertyKeyConst.RAM_ROLE_NAME, "StoreServiceRole");ConfigService configService = NacosFactory.createConfigService(properties);


經過如上配置,Nacos 客戶端在獲取配置時,雲服務器會扮演指定的 RAM 角色,阿里雲臨時安全令牌(Security Token Service,STS)來訪問 MSE Nacos 實例。


如果攻擊者獲取代碼,也無法在其他機器上運行,因爲攻擊者的機器沒有扮演 RAM 角色的權限。


如果攻擊者獲取扮演之後的認證信息,由於 STS 失效較短(默認是1小時),攻擊者拿到後很快就失效,有效減少了攻擊面。


如果需要撤銷授權,只需要在阿里雲控制檯上就可以操作,不需要重新發布應用。


相比於 AK/SK 方式的認證鑑權,ECS 關聯角色的認證鑑權更可控、更安全,所以推薦使用這種認證鑑權方式。


   
   
   


配置控制檯場景的認證和鑑權



開源版本的 Nacos


開源版本的 Nacos 控制檯,在登錄的時候,會通過控制檯的 login 接口,獲取臨時的 accessToken,然後後續的操作,都是以 accessToken 來做認證鑑權。


比如前文提到的 readonly-user 用戶,登錄後,就只能看到 public 命名空間下的配置信息,無法修改、無法查看其他命名空間下的配置信息。


另外,如果需要創建命名空間、刪除命名空間,則只能管理員登錄纔可以。


開源版本 Nacos 的認證鑑權,可以參考該文檔:https://nacos.io/zh-cn/docs/auth.html。


阿里雲 MSE


阿里雲 MSE 由於是對企業提供服務,所以在權限的劃分上會更加精細。

資源分爲實例級別(acs:mse:*:*:instance/${instanceId})和命名空間級別(acs:mse:*:*:instance/${instanceId}/${namespaceId})。

對資源的操作也更加精細,比如:

Action
說明
CreateEngineNamespace
創建命名空間
DeleteEngineNamespace
刪除命名空間
mse:Get*,mse:List*,mse:Query*
讀取配置(Nacos 客戶端和控制檯)
mse:*
所有權限,包括修改、刪除配置
mse:QueryNacosConfig
客戶端讀取配置
mse:UpdateNacosConfig
客戶端修改配置

比如,只允許讀取一個命名空間下的配置,不允許修改。那權限策略就可以寫:


  
  
  
{  "Action": [    "mse:Get*",    "mse:List*",    "mse:Query*"  ],  "Resource": [    "acs:mse:*:*:instance/${instanceId}/${namespaceId}"  ],  "Effect": "Allow"}


服務器之間的認證



Nacos 服務器之間需要同步一些信息,這時也需要認證對方身份,以確認對方真的是 Nacos-server,而不是僞裝的。


在 1.4.1 之前,是通過 User-Agent 這個 header 來認證的,這種原始的認證方式,很容易被僞造。本文開頭提到的,1月份 Nacos 爆出的漏洞就是這個原因。

所以 1.4.1 及之後的版本,認證的 header 以及對應的值可以自己配置。 在 application.properties 中,修改如下值即可:

  
  
  
# 不使用User-Agent來認證nacos.core.auth.enable.userAgentAuthWhite=false# 認證header的keynacos.core.auth.server.identity=Authorization# 認證header的valuenacos.core.auth.server.identity.value=secret

這樣,只有發送了 header Authorization: secret 的請求, 才能確認對方是服務端,才能同步集羣信息;否則就拒絕同步。

由於 Nacos-server 需要全部權限才能同步配置數據,所以對於 Nacos-server 之間,則不需要做鑑權。

這樣,就能讓服務器之間的通信也能做到安全可信了。

阿里雲 MSE 上購買的 Nacos 實例,也已經將上述方案反向移植到了 1.2 版本上,也不會有對應的安全問題。


持久化層的安全



Nacos 的配置信息,都是存儲在持久化層的。比如 Nacos 默認的持久化層是 MySQL。

爲了防止通過 git 或者其他方式將 MySQL 的用戶名和密碼泄漏出去,我們需要定時修改 MySQL 的用戶名和密碼。

通常的做法是使用兩個數據庫用戶,比如 UserA 和 UserB。如果要更新密碼,則按照如下方式操作:

  • 將 Nacos server 訪問數據庫的用戶從 UserA 切換到 UserB。
  • 更新 UserA 的密碼。
  • 將 Nacos server 訪問數據庫的用戶從 UserB 切換回UserA。
  • 更新 UserB 的密碼。

作爲阿里雲產品,MSE 都有定時修改數據庫用戶名密碼的策略,所以如果您購買了 MSE 實例,則不需要擔心此問題。


配置安全最佳實踐



捋了一遍 Nacos 配置安全的關鍵點,那麼怎麼才能保證配置安全呢。只需要做到如下最佳實踐就可以了:


1、定期修改密碼和 ak/sk

在使用 Nacos 用戶名密碼(或者 AK/SK)認證的情況下(比如使用開源 Nacos 認證方式),如果惡意用戶拿到了 Nacos 的用戶名和密碼(或者 AK/SK),那麼他就有可能拿到應用的配置。但如果定期修改了密碼或者 AK/SK 的話,就能有效限制配置泄漏的時間段,減少攻擊面。

2、使用 ECS 角色(推薦用法)

當然,在上面的解決方案中,還是會有 Nacos 用戶名密碼或者 AK/SK 在配置中的,而且這些信息的也有可能泄漏,泄漏後的修改也需要重新發布纔可以。 所以推薦使用阿里雲的 ECS 角色,所有的權限管理都是在阿里雲控制檯上完成

3、輪轉 Nacos 內部認證的 key

前文有提到 Nacos 服務器之間的認證是通過 nacos.core.auth.server.identity 來完成的,但如果惡意用戶入侵,也會導致泄漏,從而導致配置泄漏。

所以對於自建 Nacos,需要定期更換 nacos.core.auth.server.identity.value,確保惡意用戶無法僞裝爲 Nacos Server 來獲取、修改配置。

當然,如果您使用的是 MSE 託管的 Nacos 實例的話,MSE 會自動輪轉,您可以不用擔心這一點。

4、輪轉持久化層的用戶名和密碼

爲了防止配置從持久化層泄漏出去,所以需要定時修改持久化層的認證信息。通常 Nacos 的持久化層都是 DB,所以需要定時修改數據庫的用戶名和密碼。

對於 MSE 用戶,則不需要做任何操作,MSE 內部會定時修改數據庫的用戶名和密碼。

5、設計安全預案並定時執行

有了如上重重保險,理論上萬無一失,但是因爲人的操作總有失誤,所以還是需要指定安全預案:

  • 定時檢查配置的監聽列表,確認沒有未授權的機器。
  • AK/SK 泄漏時,該如何更新 AK/SK,如何撤銷泄漏的 AK/SK
  • 對於自建 Nacos,服務器被攻破後,如何修改 nacos.core.auth.server.identity.value 的方案。


總結



開源的 Nacos 在配置管理、權限管理上,能基本滿足中小企業需求。

而對於中大型企業,阿里雲產品 MSE 支持更加精細、更加靈活的權限配置、安全管理,也能利用和其他阿里雲產品一起做到更加安全的配置能力。


當然,不論是自建 Nacos 還是使用阿里雲 MSE,都需要關注上述提到的安全點,防止配置信息泄漏,造成業務損失。最後提到的配置安全最佳實踐,也能能保證配置泄漏後,有能力及時修復,做到防患未然。


招賢納士



我們 Dubbo /  Spring Cloud 商業化團隊正在招人。除了 EDAS,我們還有 ARMS  (應用實時監控服務)、MSE(微服務引擎)、SAE(Serverless  應用引擎)等獨立產品。我們在忙什麼?用心打磨這些產品,就是我們的工作。團隊的目標是將阿里巴巴在服務治理上的最佳實踐通過產品化的形式輸出給阿里雲上的企業客戶,幫助客戶實現業務永遠在線。


簡歷投遞方式: https://job.alibaba.com/zhaopin/position_detail.htm?positionId=98290


點個在看,讓更多人看見


本文分享自微信公衆號 - Kirito的技術分享(cnkirito)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章