在微服務架構中,我們通常都會採用DevOps的組織方式來降低因團隊間溝通造成的巨大成本,以加速微服務應用的交付能力。這就使得原本由運維團隊控制的線上資訊將交由微服務所屬組織的成員自行維護,其中將會包括大量的敏感資訊,比如:資料庫的賬戶與密碼等。很顯然,如果我們直接將敏感資訊以明文的方式儲存於微服務應用的配置檔案中是非常危險的。針對這個問題,Spring Cloud Config提供了對屬性進行加密解密的功能,以保護配置檔案中的資訊保安。比如下面的例子:
spring.datasource.username=didi
spring.datasource.password={cipher}dba6505baa81d78bd08799d8d4429de499bd4c2053c05f029e7cfbf143695f5b
複製程式碼
在Spring Cloud Config中通過在屬性值前使用{cipher}
字首來標註該內容是一個加密值,當微服務客戶端來載入配置時,配置中心會自動的為帶有{cipher}
字首的值進行解密。通過該機制的實現,運維團隊就可以放心的將線上資訊的加密資源給到微服務團隊,而不用擔心這些敏感資訊遭到洩露了。下面我們來具體介紹如何在配置中心使用該項功能。
使用前提
在使用Spring Cloud Config的加密解密功能時,有一個必要的前提需要我們注意。為了啟用該功能,我們需要在配置中心的執行環境中安裝不限長度的JCE版本(Unlimited Strength Java Cryptography Extension)。雖然,JCE功能在JRE中自帶,但是預設使用的是有長度限制的版本。我們可以從Oracle的官方網站中下載到它,它是一個壓縮包,解壓後可以看到下面三個檔案:
README.txt
local_policy.jar
US_export_policy.jar
複製程式碼
我們需要將local_policy.jar
和US_export_policy.jar
兩個檔案複製到$JAVA_HOME/jre/lib/security
目錄下,覆蓋原來的預設內容。到這裡,加密解密的準備工作就完成了。
相關端點
在完成了JCE的安裝後,可以嘗試啟動配置中心。在控制檯中,將會輸出了一些配置中心特有的端點,主要包括:
/encrypt/status
:檢視加密功能狀態的端點/key
:檢視金鑰的端點/encrypt
:對請求的body內容進行加密的端點/decrypt
:對請求的body內容進行解密的端點
可以嘗試通過GET請求訪問/encrypt/status
端點,我們將得到如下內容:
{
"description": "No key was installed for encryption service",
"status": "NO_KEY"
}
複製程式碼
該返回說明當前配置中心的加密功能還不能使用,因為沒有為加密服務配置對應的金鑰。
配置金鑰
我們可以通過encrypt.key
屬性在配置檔案中直接指定金鑰資訊(對稱性金鑰),比如:
encrypt.key=didispace
複製程式碼
加入上述配置資訊後,重啟配置中心,再訪問/encrypt/status
端點,我們將得到如下內容:
{
"status": "OK"
}
複製程式碼
此時,我們配置中心的加密解密功能就已經可以使用了,不妨嘗試訪問一下/encrypt
和/decrypt
端點來進行加密和解密的功能。注意,這兩個端點都是POST請求,加密和解密資訊需要通過請求體來傳送。比如,以curl
命令為例,我們可以通過下面的方式呼叫加密與解密端點:
$ curl localhost:7001/encrypt -d didispace
3c70a809bfa24ab88bcb5e1df51cb9e4dd4b8fec88301eb7a18177f1769c849ae9c9f29400c920480be2c99406ae28c7
$ curl localhost:7001/decrypt -d 3c70a809bfa24ab88bcb5e1df51cb9e4dd4b8fec88301eb7a18177f1769c849ae9c9f29400c920480be2c99406ae28c7
didispace
複製程式碼
這裡,我們通過配置encrypt.key
引數來指定金鑰的實現方式採用了對稱性加密。這種方式實現比較簡單,只需要配置一個引數即可。另外,我們也可以使用環境變數ENCRYPT_KEY
來進行配置,讓金鑰資訊外部化儲存。
非對稱加密
Spring Cloud Config的配置中心不僅可以使用對稱性加密,也可以使用非對稱性加密(比如:RSA金鑰對)。雖然非對稱性加密的金鑰生成與配置相對複雜一些,但是它具有更高的安全性。下面,我們來具體介紹一下如何使用非對稱加密。
首先,我們需要通過keytool
工具來生成金鑰對。keytool
是JDK中的一個金鑰和證照管理工具。它使使用者能夠管理自己的公鑰/私鑰對及相關證照,用於(通過數字簽名)自我認證(使用者向別的使用者/服務認證自己)或資料完整性以及認證服務。在JDK 1.4以後的版本中都包含了這一工具,它的位置在:%JAVA_HOME%\bin\keytool.exe
。
生成金鑰的具體命令如下:
$ keytool -genkeypair -alias config-server -keyalg RSA -keystore config-server.keystore
輸入金鑰庫口令:
再次輸入新口令:
您的名字與姓氏是什麼?
[Unknown]: zhaiyongchao
您的組織單位名稱是什麼?
[Unknown]: company
您的組織名稱是什麼?
[Unknown]: organization
您所在的城市或區域名稱是什麼?
[Unknown]: city
您所在的省/市/自治區名稱是什麼?
[Unknown]: province
該單位的雙字母國家/地區程式碼是什麼?
[Unknown]: china
CN=zhaiyongchao, OU=company, O=organization, L=city, ST=province, C=china是否正確?
[否]: y
輸入 <config-server> 的金鑰口令
(如果和金鑰庫口令相同, 按回車):
再次輸入新口令:
複製程式碼
另外,如果我們不想逐步的輸入那些提示資訊,可以使用-dname
來直接指定,而金鑰庫口令與金鑰口令可使用-storepass
和-keypass
來直接指定。所以,我們可以通過下面的命令直接建立出與上述命令一樣的金鑰庫:
$ keytool -genkeypair -alias config-server -keyalg RSA \
-dname "CN=zhaiyongchao, OU=company, O=organization, L=city, ST=province, C=china" \
-keypass 222222 \
-keystore config-server.keystore \
-storepass 111111 \
複製程式碼
預設情況下,上述命令建立的金鑰只有90天有效期。如果我們想要調整它的有效期,可以通過增加-validity
引數來實現,比如我們可以通過下面的命令,讓金鑰的有效期延長到一年:
$ keytool -genkeypair -alias config-server -keyalg RSA \
-dname "CN=zhaiyongchao, OU=company, O=organization, L=city, ST=province, C=china" \
-keypass 222222 \
-keystore config-server.keystore \
-storepass 111111 \
-validity 365 \
複製程式碼
上述的三種命令生成方式,最終都會在命令的當前執行目錄下生成一個config-server.keystore
檔案。下面,我們需要將它儲存在配置中心的檔案系統中的某個位置,比如放在當前的使用者目錄下,然後在配置中心中加入相關的配置資訊:
encrypt.key-store.location=file://${user.home}/config-server.keystore
encrypt.key-store.alias=config-server
encrypt.key-store.password=111111
encrypt.key-store.secret=222222
複製程式碼
如果我們將config-server.keystore
放在配置中心的src/main/resource
目錄下,也可以直接這樣配置:encrypt.key-store.location=config-server.keystore
。另外,非對稱加密的配置資訊也可以通過環境變數的方式進行配置,它們對應的具體變數名如下:
ENCRYPT_KEY_STORE_LOCATION
ENCRYPT_KEY_STORE_ALIAS
ENCRYPT_KEY_STORE_PASSWORD
ENCRYPT_KEY_STORE_SECRET
複製程式碼
通過環境變數來配置金鑰庫相關資訊可以獲得更好的安全性,所以我們可以將敏感的口令資訊儲存在配置中心的環境變數中是一種不錯的選擇。
以下專題教程也許您會有興趣
本文內容部分節選自我的《Spring Cloud微服務實戰》,稍作改變和內容升級