1. 程式人生 > >Spring Cloud Config 伺服器(下)

Spring Cloud Config 伺服器(下)

健康指標

配置伺服器附帶執行狀況指示器,檢查配置的EnvironmentRepository是否正常工作。預設情況下,它要求EnvironmentRepository應用程式名稱為appdefault配置檔案和EnvironmentRepository實現提供的預設標籤。

您可以配置執行狀況指示器以檢查更多應用程式以及自定義配置檔案和自定義標籤,例如

spring:
  cloud:
    config:
      server:
        health:
          repositories:
            myservice:
              label:
mylabel myservice-dev: name: myservice profiles: development

您可以通過設定spring.cloud.config.server.health.enabled=false來禁用執行狀況指示器。

安全

您可以以任何對您有意義的方式(從物理網路安全性到OAuth2承載令牌)保護您的Config Server,並且Spring Security和Spring Boot可以輕鬆做任何事情。

要使用預設的Spring Boot配置的HTTP Basic安全性,只需在類路徑中包含Spring Security(例如通過spring-boot-starter-security

)。預設值為“user”的使用者名稱和隨機生成的密碼,這在實踐中不會非常有用,因此建議您配置密碼(通過security.user.password)並對其進行加密(請參閱下文的說明怎麼做)。

加密和解密

重要 先決條件:要使用加密和解密功能,您需要在JVM中安裝全面的JCE(預設情況下不存在)。您可以從Oracle下載“Java加密擴充套件(JCE)無限強度管理策略檔案”,並按照安裝說明(實際上將JRE lib / security目錄中的2個策略檔案替換為您下載的檔案)。

如果遠端屬性源包含加密內容(以{cipher}開頭的值),則在通過HTTP傳送到客戶端之前,它們將被解密。這種設定的主要優點是,當它們“靜止”時,屬性值不必是純文字(例如在git倉庫中)。如果值無法解密,則從屬性源中刪除該值,並新增具有相同鍵的附加屬性,但以“無效”作為字首。和“不適用”的值(通常為“<n / a>”)。這主要是為了防止密碼被用作密碼並意外洩漏。

如果要為config客戶端應用程式設定遠端配置儲存庫,可能會包含一個application.yml,例如:

application.yml

spring:
  datasource:
    username: dbuser
    password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'

.properties檔案中的加密值不能用引號括起來,否則不會解密該值:

application.properties

spring.datasource.username: dbuser
spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ

您可以安全地將此純文字推送到共享git儲存庫,並且保密密碼。

伺服器還暴露了/encrypt/decrypt端點(假設這些端點將被保護,並且只能由授權代理訪問)。如果您正在編輯遠端配置檔案,可以使用Config Server通過POST到/encrypt端點來加密值,例如

$ curl localhost:8888/encrypt -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
注意 如果要加密的值具有需要進行URL編碼的字元,則應使用–data-urlencode選項curl來確保它們已正確編碼。

逆向操作也可通過/decrypt獲得(如果伺服器配置了對稱金鑰或全金鑰對):

$ curl localhost:8888/decrypt -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret
提示 如果您使用curl進行測試,則使用–data-urlencode(而不是-d)或設定顯式Content-Type:text/plain,以確保在有特殊字元時正確地對資料進行編碼(’+'特別是棘手)。

將加密的值新增到{cipher}字首,然後再將其放入YAML或屬性檔案中,然後再提交併將其推送到遠端可能不安全的儲存區。

/encrypt/decrypt端點也都接受/*/{name}/{profiles}形式的路徑,當客戶端呼叫到主環境資源時,可以用於每個應用程式(名稱)和配置檔案控制密碼。

注意 為了以這種細微的方式控制密碼,您還必須提供一種TextEncryptorLocator型別的@Bean,可以為每個名稱和配置檔案建立不同的加密器。預設提供的不會這樣做(所有加密使用相同的金鑰)。

spring命令列客戶端(安裝了Spring Cloud CLI擴充套件)也可以用於加密和解密,例如

$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

要在檔案中使用金鑰(例如用於加密的RSA公鑰),使用“@”鍵入鍵值,並提供檔案路徑,例如

$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...

關鍵引數是強制性的(儘管有一個字首)。

金鑰管理

Config Server可以使用對稱(共享)金鑰或非對稱金鑰(RSA金鑰對)。非對稱選擇在安全性方面是優越的,但是使用對稱金鑰往往更方便,因為它只是配置的一個屬性值。

要配置對稱金鑰,您只需要將encrypt.key設定為一個祕密字串(或使用環境變數ENCRYPT_KEY將其從純文字配置檔案中刪除)。

要配置非對稱金鑰,您可以將金鑰設定為PEM編碼的文字值(encrypt.key),也可以通過金鑰庫設定金鑰(例如由JDK附帶的keytool實用程式建立)。金鑰庫屬性為encrypt.keyStore.,等於

  • location(a Resource位置),

  • password(解鎖金鑰庫)和

  • alias(以識別商店中使用的金鑰)。

使用公鑰進行加密,需要私鑰進行解密。因此,原則上您只能在伺服器中配置公鑰,如果您只想進行加密(並準備使用私鑰本地解密值)。實際上,您可能不想這樣做,因為它圍繞所有客戶端傳播金鑰管理流程,而不是將其集中在伺服器中。另一方面,如果您的配置伺服器真的相對不安全,並且只有少數客戶端需要加密的屬性,這是一個有用的選項。

建立用於測試的金鑰庫

要建立一個金鑰庫進行測試,您可以執行以下操作:

$ keytool -genkeypair -alias mytestkey -keyalg RSA \
  -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
  -keypass changeme -keystore server.jks -storepass letmein

server.jks檔案放在類路徑(例如)中,然後在您的application.yml中配置伺服器:

encrypt:
  keyStore:
    location: classpath:/server.jks
    password: letmein
    alias: mytestkey
    secret: changeme

使用多個鍵和鍵旋轉

除了加密屬性值中的{cipher}字首之外,配置伺服器在(Base64編碼)密文開始前查詢{name:value}字首(零或多個)。金鑰被傳遞給TextEncryptorLocator,它可以執行找到密碼的TextEncryptor所需的任何邏輯。如果配置了金鑰庫(encrypt.keystore.location),預設定位器將使用“key”字首提供的別名,即使用如下密碼查詢儲存中的金鑰:

foo:
  bar: `{cipher}{key:testkey}...`

定位器將尋找一個名為“testkey”的鍵。也可以通過字首中的{secret:…?}值提供一個祕密,但是如果不是預設值,則使用金鑰庫密碼(這是您在構建金鑰庫時獲得的,並且不指定密碼)。如果你這樣做 提供一個祕密建議你也加密使用自定義SecretLocator的祕密。

如果金鑰只用於加密幾個位元組的配置資料(即它們沒有在其他地方使用),則密碼轉換幾乎不是必需的,但是如果存在安全漏洞,有時您可能需要更改金鑰例項。在這種情況下,所有客戶端都需要更改其源配置檔案(例如,以git格式),並在所有密碼中使用新的{key:…?}字首,當然事先檢查金鑰別名在配置伺服器金鑰庫中是否可用。

提示 如果要讓Config Server處理所有加密以及解密,也可以將{name:value}字首新增到釋出到/encrypt端點的明文中。

服務加密Properties

有時您希望客戶端在本地解密配置,而不是在伺服器中進行配置。在這種情況下,您仍然可以擁有/加密和解密端點(如果您提供encrypt.*配置來定位金鑰),但是您需要使用spring.cloud.config.server.encrypt.enabled=false明確地關閉傳出屬性的解密。如果您不關心端點,那麼如果您既不配置金鑰也不配置使能的標誌,則應該起作用。

歡迎關注作者的公眾號《Java程式設計生活》,每日記載Java程式猿工作中遇到的問題 在這裡插入圖片描述