1. 程式人生 > >《Spring Cloud Config官方文件》之Spring Cloud Config Server

《Spring Cloud Config官方文件》之Spring Cloud Config Server

原文連結

5. Spring Cloud Config Server

伺服器為外部配置(名稱 – 值對或同等的YAML內容)提供了一個HTTP、基於資源的API。伺服器很容易使用@EnableConfigServer註釋嵌入到Spring Boot應用程式中 。所以這個應用是一個配置伺服器:

ConfigServer.java

@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
  public static void main(String[] args) {
    SpringApplication.run(ConfigServer.class, args);
  }
}

像所有Spring Boot應用程式一樣,預設情況下,它將在埠8080上執行,但您可以通過各種方式將其切換到常規埠8888。最簡單的方式是設定一個預設的配置庫,通過spring.config.name=configserver來啟動(在Config Server jar中有一個configserver.yml)。另一個是使用你自己的application.properties,例如

application.properties中。

server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo

${user.home}/config-repo是包含YAML和屬性檔案的git倉庫。

在Windows中,如果驅動器字首是絕對路徑,那麼在檔案URL中需要額外的“/”,例如`file:///${user.home}/config-repo`。

下面是在上面的例子中建立git倉庫的步驟:

$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar > application.properties
$ git add -A .
$ git commit -m "Add application.properties"

使用本地檔案系統為您的git倉庫這個做法僅用於測試。在生產中使用伺服器來託管配置倉庫。

如果只保留文字檔案,配置庫的初始克隆將會快速有效。如果您開始儲存二進位制檔案(尤其是大型檔案),則可能會在第一次請求配置或伺服器記憶體不足錯誤時遇到延遲。

5.1環境庫

你想在哪裡儲存配置伺服器的配置資料?管理這種行為的策略是 EnvironmentRepository,服務Environment物件。這個 Environment是來自 Spring的域名Environment(包括propertySources主要特性)的淺層副本 。該 Environment 資源由三個變數引數化:

  • {application} 對映到客戶端的“spring.application.name”;
  • {profile}對映到客戶端的“spring.profiles.active”(逗號分隔列表); 和
  • {label} 這是一個標記“版本化”的配置檔案集的伺服器端功能。

版本庫的實現通常就像一個 Spring Boot 應用程式一樣從{application}引數“spring.config.name”載入配置檔案,而“spring.profiles.active”等於{profiles}引數。配置檔案的優先順序規則也與常規引導應用程式中的相同:活動配置檔案優先於預設值,如果有多個配置檔案,則最後一個配置檔案將勝出(如向a Map中新增實體)。

示例:客戶端應用程式具有此載入程式配置:

bootstrap.yml。

spring:
  application:
    name: foo
  profiles:
    active: dev,mysql

(像通常的Spring Boot應用程式一樣,這些屬性也可以設定為環境變數或命令列引數)。

如果倉庫是基於檔案的,伺服器將通過 application.yml(在所有客戶端之間共享)和 foo.yml(foo.yml優先)建立一個 Environment 。如果YAML檔案內部有指向Spring配置檔案的文件,那麼這些檔案將以更高的優先順序(按列出的配置檔案的順序)應用,如果存在特定於配置檔案的YAML(或屬性)檔案,則這些檔案的優先順序應高於預設值。更高的優先順序轉換為PropertySource正如前面所列出的 Environment。(這些規則與獨立的Spring Boot應用程式中的規則相同。)

5.1.1 Git後端

EnvironmentRepository的預設實現使用Git後端,這對於管理升級和物理環境非常方便,並且也可以用於審計更改。若要更改倉庫的位置,可以在配置伺服器(例如,在 application.yml)中設定“spring.cloud.config.server.git.uri”配置屬性 。如果你用一個file:字首設定它,那麼它應該從一個本地儲存庫工作,所以在沒有伺服器情形中你可以快速,輕鬆地開始,但在這種情況下,伺服器直接在本地儲存庫上執行,而不克隆它(沒關係,因為配置伺服器從不對“遠端”儲存庫進行更改)。要擴充套件配置伺服器並使其高度可用,您需要將伺服器的所有例項指向同一個儲存庫,因此只有共享檔案系統才能工作。即使在這種情況下,最好將ssh:協議用於共享檔案系統儲存庫,以便伺服器可以將其克隆並使用本地工作副本作為快取。

這個儲存庫實現將{label}HTTP資源的引數對映到一個git標籤(commit id,分支名稱或標籤)。如果git分支或標籤名稱包含斜槓(“/”),則應該使用特殊字串“(_)”來指定HTTP URL中的標籤(以避免與其他URL路徑混淆)。例如,如果標籤是 foo/bar,替換斜槓將導致看起來像一個標籤 foo(__)bar。包含特殊字串“(\ _)”也可以應用於{application}引數。如果使用像curl這樣的命令列客戶端,請小心URL中的括號(例如,用引號”將它們從shell中轉義出來)。

Git URI中的佔位符

Spring Cloud Config Server 支援帶有佔位符{application}{profile}(和{label}如果你需要它,但請記住,標籤作為一個git標籤適用任何情況)的一個Git倉庫URL 。因此,您可以輕鬆地使用(例如)支援“每個應用程式一個倉庫”政策:

spring:
   cloud:
     config:
       server:
         git:
           uri:https://github.com/myorg/ { application }

或通過 {profile}來採用的使用類似模式的“每個配置檔案一個倉庫”政策,

另外,在{application}引數中使用特殊字串“(\ _)” 可以支援多個組織(例如):

spring:
   cloud:
     config:
       server:
         git:
           uri:https://github.com/ { application }

其中{application}在格式“組織(\ _)應用”請求時被提供。

模式匹配和多個儲存庫

還有對應用程式和配置檔名稱進行模式匹配的更復雜要求的支援。模式格式是{application}/{profile}用萬用字元(以萬用字元開頭的模式可能需要引用)的逗號分隔的名稱列表。例:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            simple: https://github.com/simple/config-repo
            special:
              pattern: special*/dev*,*special*/dev*
              uri: https://github.com/special/config-repo
            local:
              pattern: local*
              uri: file:/home/configsvc/config-repo

如果{application}/{profile}不匹配任何模式,將使用“spring.cloud.config.server.git.uri”下定義的預設URI。在上面的示例中,對於“簡單”儲存庫,模式是simple/*(即它只匹配所有配置檔案中名為“簡單”的一個應用程式)。“本地”儲存庫匹配所有配置檔案中以“local”開頭的所有應用程式名稱(/*字尾會自動新增到任何沒有配置檔案匹配器的模式)。

上述“簡單”示例中使用的“單行”快捷方式只能在要設定的唯一屬性是URI的情況下使用。如果你需要設定其他任何東西(憑據,模式等),你需要使用完整的形式。

pattern在回購屬性中實際上是一個數組,所以可以使用一個YAML陣列(或[0][1]等在屬性檔案字尾)繫結到多個模式。如果要使用多個配置檔案執行應用程式,則可能需要執行此操作。例:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            development:
              pattern:
                - '*/development'
                - '*/staging'
              uri: https://github.com/development/config-repo
            staging:
              pattern:
                - '*/qa'
                - '*/production'
              uri: https://github.com/staging/config-repo

Spring Cloud會猜測包含沒有結束的配置檔案的模式*意味著你實際上想要匹配以這個模式開始的配置檔案列表(這*/staging也是一個快捷方式 ["*/staging", "*/staging,*"])。例如,您需要在本地“development”配置檔案中執行應用程式,而在遠端執行“cloud”配置檔案時,這也很常見。

每個儲存庫也可以選擇性地將配置檔案儲存在子目錄中,並且可以將指定為這些目錄的模式指定為searchPaths。例如在頂層:

spring:
   cloud:
     config:
       server:
         git:
           uri:https://github.com/spring-cloud-samples/config-repo
           searchPaths:foo,bar *

在這個例子中,伺服器在頂層搜尋配置檔案,在“foo /”子目錄中搜索名稱以“bar”開頭的子目錄。

預設情況下,伺服器在首次請求配置時將會克隆遠端儲存庫。可以將伺服器配置為在啟動時克隆儲存庫。例如在頂層:

spring:
   cloud:
     config:
       server:
         git:
           uri:https://git/common/config-repo.git
           repos:
             team-a:
                 pattern:team-a- *
                 cloneOnStart:true 
                uri:http:// git / team -a / config-repo.git
             team-b:
                 pattern:team-b- *
                 cloneOnStart:false 
                uri:http://git/team-b/config-repo.git
             team-c:
                 pattern:team-c- *
                 uri:http://git/team-a/config-repo.git

在這個例子中,伺服器在接受任何請求之前,在啟動時將會克隆team-a的config-repo。所有其他儲存庫將不會被克隆,直到請求儲存庫的配置。

在配置伺服器啟動時設定要克隆的儲存庫可以幫助在配置伺服器啟動時快速識別配置錯誤的配置源(例如,無效的儲存庫URI)。在 cloneOnStart未啟用配置源的情況下,配置伺服器可能會以錯誤配置或無效的配置源成功啟動,並且在應用程式從該配置源請求配置之前不會檢測到錯誤。

認證

要在遠端儲存庫上使用HTTP基本認證,單獨新增“username”和“password”屬性(不在URL中),例如

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          username: trolley
          password: strongpassword

如果您不使用HTTPS和使用者憑據,那麼當您將金鑰儲存在預設目錄(~/.ssh)和uri指向SSH位置(例如“ [email protected]:configuration / cloud-組態”。Git伺服器的條目存在於~/.ssh/known_hosts檔案中,並且ssh-rsa格式是很重要的。其他格式(如ecdsa-sha2-nistp256)不支援。為避免出現意外,您應該確保在Git伺服器的known_hosts檔案中只有一個條目存在,並且與您提供給配置伺服器的URL匹配。如果您在URL中使用了一個主機名,那麼您希望在known_hosts檔案中的URL使用主機名,而不是IP。使用JGit可以訪問儲存庫,因此您找到的任何文件都應該適用。HTTPS代理設定可以在~/.git/config中設定,或者是通過系統屬性(-Dhttps.proxyHost-Dhttps.proxyPort)以任何其他JVM程序的方式進行設定 。

如果你不知道是否你的~/.git目錄是使用git config --global來操作設定的(例如git config --global http.sslVerify false)。

使用AWS CodeCommit進行身份驗證

AWS CodeCommit認證也可以完成。從命令列使用Git時,AWS CodeCommit使用身份驗證助手。此幫助程式未與JGit庫一起使用,因此,如果Git URI與AWS CodeCommit模式匹配,則將建立用於AWS CodeCommit的JGit CredentialProvider。AWS CodeCommit URI總是看起來像 https://git-codecommit.$ {AWS_REGION} .amazonaws.com / $ {repopath}

如果您的Git URI與上面的CodeCommit URI模式相匹配,那麼您必須在使用者名稱和密碼中或預設憑證提供程式鏈支援的其中一個位置提供有效的AWS憑證。AWS EC2例項可以使用 ECAM Instance的IAM角色

注意:aws-java-sdk-core jar是一個可選的依賴項。如果aws-java-sdk-core jar不在您的類路徑中,那麼無論git伺服器的URI如何,都不會建立AWS Code Commit憑據提供程式。

使用屬性Git SSH配置

預設情況下,Spring Cloud Config Server使用JGit庫使用SSH配置檔案,比如可以通過~/.ssh/known_hosts/etc/ssh/ssh_config使用SSH URI連線到Git倉庫。在Cloud Foundry等雲環境中,本地檔案系統可能是短暫的或不易訪問的。對於這些情況,可以使用Java屬性來設定SSH配置。為了啟用基於屬性的SSH配置,屬性spring.cloud.config.server.git.ignoreLocalSshSettings必須設定為true。例:

spring:
    cloud:
      config:
        server:
          git:
            uri: [email protected]:team/repo1.git
            ignoreLocalSshSettings: true
            hostKey: someHostKey
            hostKeyAlgorithm: ssh-rsa
            privateKey: |
                         -----BEGIN RSA PRIVATE KEY-----
                         MIIEpgIBAAKCAQEAx4UbaDzY5xjW6hc9jwN0mX33XpTDVW9WqHp5AKaRbtAC3DqX
                         IXFMPgw3K45jxRb93f8tv9vL3rD9CUG1Gv4FM+o7ds7FRES5RTjv2RT/JVNJCoqF
                         ol8+ngLqRZCyBtQN7zYByWMRirPGoDUqdPYrj2yq+ObBBNhg5N+hOwKjjpzdj2Ud
                         1l7R+wxIqmJo1IYyy16xS8WsjyQuyC0lL456qkd5BDZ0Ag8j2X9H9D5220Ln7s9i
                         oezTipXipS7p7Jekf3Ywx6abJwOmB0rX79dV4qiNcGgzATnG1PkXxqt76VhcGa0W
                         DDVHEEYGbSQ6hIGSh0I7BQun0aLRZojfE3gqHQIDAQABAoIBAQCZmGrk8BK6tXCd
                         fY6yTiKxFzwb38IQP0ojIUWNrq0+9Xt+NsypviLHkXfXXCKKU4zUHeIGVRq5MN9b
                         BO56/RrcQHHOoJdUWuOV2qMqJvPUtC0CpGkD+valhfD75MxoXU7s3FK7yjxy3rsG
                         EmfA6tHV8/4a5umo5TqSd2YTm5B19AhRqiuUVI1wTB41DjULUGiMYrnYrhzQlVvj
                         5MjnKTlYu3V8PoYDfv1GmxPPh6vlpafXEeEYN8VB97e5x3DGHjZ5UrurAmTLTdO8
                         +AahyoKsIY612TkkQthJlt7FJAwnCGMgY6podzzvzICLFmmTXYiZ/28I4BX/mOSe
                         pZVnfRixAoGBAO6Uiwt40/PKs53mCEWngslSCsh9oGAaLTf/XdvMns5VmuyyAyKG
                         ti8Ol5wqBMi4GIUzjbgUvSUt+IowIrG3f5tN85wpjQ1UGVcpTnl5Qo9xaS1PFScQ
                         xrtWZ9eNj2TsIAMp/svJsyGG3OibxfnuAIpSXNQiJPwRlW3irzpGgVx/AoGBANYW
                         dnhshUcEHMJi3aXwR12OTDnaLoanVGLwLnkqLSYUZA7ZegpKq90UAuBdcEfgdpyi
                         PhKpeaeIiAaNnFo8m9aoTKr+7I6/uMTlwrVnfrsVTZv3orxjwQV20YIBCVRKD1uX
                         VhE0ozPZxwwKSPAFocpyWpGHGreGF1AIYBE9UBtjAoGBAI8bfPgJpyFyMiGBjO6z
                         FwlJc/xlFqDusrcHL7abW5qq0L4v3R+FrJw3ZYufzLTVcKfdj6GelwJJO+8wBm+R
                         gTKYJItEhT48duLIfTDyIpHGVm9+I1MGhh5zKuCqIhxIYr9jHloBB7kRm0rPvYY4
                         VAykcNgyDvtAVODP+4m6JvhjAoGBALbtTqErKN47V0+JJpapLnF0KxGrqeGIjIRV
                         cYA6V4WYGr7NeIfesecfOC356PyhgPfpcVyEztwlvwTKb3RzIT1TZN8fH4YBr6Ee
                         KTbTjefRFhVUjQqnucAvfGi29f+9oE3Ei9f7wA+H35ocF6JvTYUsHNMIO/3gZ38N
                         CPjyCMa9AoGBAMhsITNe3QcbsXAbdUR00dDsIFVROzyFJ2m40i4KCRM35bC/BIBs
                         q0TY3we+ERB40U8Z2BvU61QuwaunJ2+uGadHo58VSVdggqAo0BSkH58innKKt96J
                         69pcVH/4rmLbXdcmNYGm6iu+MlPQk4BUZknHSmVHIFdJ0EPupVaQ8RHT
                         -----END RSA PRIVATE KEY-----                 

表5.1。SSH配置屬性

屬性名稱 備註
ignoreLocalSshSettings 如果為true,則使用基於屬性的SSH配置,而不是基於檔案。必須設定為spring.cloud.config.server.git.ignoreLocalSshSettings,而不是在儲存庫定義中。
privateKey 有效的SSH私鑰。當ignoreLocalSshSettings為true,並且Git URI是SSH格式時,該屬性必須被設定。
hostKey 有效的SSH主機金鑰。如果hostKeyAlgorithm被設定,則該屬性也必須要被設定。
hostKeyAlgorithm ssh-dss, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384 ,ecdsa-sha2-nistp521其中之一。則必須被設定,如果hostKey也設定
strictHostKeyChecking true或者false。如果為false,則忽略主機金鑰的錯誤
knownHostsFile 自定義.known_hosts檔案的位置
preferredAuthentications 覆蓋伺服器認證方法的順序。如果伺服器在publickey方法之前有鍵盤互動式驗證,這應該允許規避登入提示。

Git搜尋路徑中的佔位符

Spring Cloud Config Server 也支援佔位符的搜尋路徑{application}{profile}(和{label}如果需要的話)。例:

spring:
   cloud:
     config:
       server:
         git:
           uri:https://github.com/spring-cloud-samples/config-repo
           searchPaths:'{application}'

在儲存庫中搜索與目錄同名的檔案(以及頂層)。在帶佔位符的搜尋路徑中萬用字元也是有效的(搜尋中包含任何匹配的目錄)。

強制拉入Git倉庫

如前所述,Spring Cloud Config Server對遠端git儲存庫進行了克隆,並且如果本地拷貝變得髒(例如資料夾內容被OS程序更改),Spring Cloud Config Server將無法從遠端儲存庫更新本地拷貝。

為了解決這個問題,如果本地副本是髒的,會有一個屬性 force-pull 使Spring Cloud Config Server強制從遠端儲存庫中提取。例:

spring:
   cloud:
     config:
       server:
         git:
           uri:https://github.com/spring-cloud-samples/config-repo
           force-pull:true               

如果您有多個儲存庫配置,則可以在每個儲存庫中配置force-pull屬性。例:

spring:
   cloud:
     config:
       server:
         git:
           uri:https://git/common/config-repo.git
           force-pull:true 
          repos:
             team-a:
                 pattern:team-a- *
                 uri:http:// git /team-a/config-repo.git
                 force-pull:true 
            team-b:
                 pattern:team-b- *
                 uri:http://git/team-b/config-repo.git
                 force-pull:true 
            team-c:
                 pattern:team-c- *
                 uri:http://git/team-a/config-repo.git                 

force-pull屬性的預設值是false

5.1.2 版本控制後端檔案系統使用

使用基於VCS的後端(git,svn)檔案檢出或克隆到本地的檔案系統。預設情況下,它們被放在系統臨時目錄中,字首為config-repo-。在Linux上,例如它可能是/tmp/config-repo-<randomid>。一些作業系統 經常清理 臨時目錄。這可能會導致意外的行為,如缺少屬性。為避免此問題,請通過設定spring.cloud.config.server.git.basedirspring.cloud.config.server.svn.basedir更改不在系統臨時結構中的目錄來更改“配置伺服器使用的目錄”。

5.1.3 檔案系統後端

配置伺服器中還有一個“本機”配置檔案,它不使用Git,只是從本地類路徑或檔案系統中載入配置檔案(任何你想用“spring.cloud.config.server.native.searchLocations”指向的靜態URL)。要使用本機配置檔案,只需使用“spring.profiles.active = native”啟動配置伺服器即可。

請記住為檔案資源使用字首file:(沒有字首的預設通常是類路徑)。就像所有的Spring Boot配置一樣,你可以嵌入${}環境佔位符,但是要記住,Windows中的絕對路徑需要額外的“/”,例如file:///${user.home}/config-repo

這個預設值和searchLocations本地的Spring Boot應用程式是一樣的( [classpath:/, classpath:/config, file:./, file:./config])。這不會將application.properties伺服器暴露給所有客戶端,因為伺服器中存在的任何屬性源在傳送到客戶端之前都會被刪除。

檔案系統後端非常適合快速入門和測試。要在生產中使用它,您需要確保檔案系統可靠,並在Config Server的所有例項中共享。

搜尋位置可以包含佔位符{application}{profile}{label}。通過這種方式,您可以分隔路徑中的目錄,並選擇一種對您有意義的策略(例如,每個應用程式的子目錄或每個配置檔案的子目錄)。

如果在搜尋位置中不使用佔位符,則此儲存庫還會將HTTP資源的{label}引數附加到搜尋路徑的字尾上,因此屬性檔案將從每個搜尋位置和與標籤名稱相同的子目錄中載入(在Spring環境中標記的屬性優先)。因此,沒有佔位符的預設行為與新增以結尾的搜尋位置相同/{label}/。比如file:/tmp/configfile:/tmp/config,file:/tmp/config/{label}是等同的。這種行為可以通過設定 spring.cloud.config.server.native.addLabelLocations=false來禁用。

5.1.4 Vault後端

Spring Cloud Config Server也支援Vault作為後端。

Vault是安全訪問機密的工具。機密就是你想要嚴格控制訪問的任何東西,比如API金鑰,密碼,證書等等。Vault為任何機密提供統一的介面,同時提供嚴格的訪問控制並記錄詳細的審計日誌。

有關 Vault 的更多資訊,請參閱 Vault快速入門指南

要使配置伺服器使用Vault後端,您可以使用配置vault檔案執行配置伺服器。例如在你的配置伺服器的application.properties你可以新增spring.profiles.active=vault

預設情況下,配置伺服器將假定您的Vault伺服器正在執行 http://127.0.0.1:8200。它也會假設後端的名字是secret並且鍵是application。所有這些預設值都可以在你的配置伺服器上的application.properties檔案中進行配置。以下是可配置的Vault屬性的表格。所有屬性都以 spring.cloud.config.server.vault為字首。

名稱 預設值
host 127.0.0.1
port 8200
scheme HTTP
backend secret
defaultKey application
profileSeparator

所有的配置屬性中可以找到 org.springframework.cloud.config.server.environment.VaultEnvironmentRepository

執行配置伺服器後,您可以向伺服器發出HTTP請求,以從Vault後端檢索值。要做到這一點,您將需要為您的 Vault 伺服器提供一個令牌。

首先將一些資料放在您的 Vault 中。例如

$ vault write secret/application foo=bar baz=bam
$ vault write secret/myapp foo=myappsbar

現在,讓HTTP請求到您的配置伺服器來檢索值。

$ curl -X "GET" "http://localhost:8888/myapp/default" -H "X-Config-Token: yourtoken"

在做出上述請求後,您應該看到類似於此的迴應。

{
   "name":"myapp",
   "profiles":[
      "default"
   ],
   "label":null,
   "version":null,
   "state":null,
   "propertySources":[
      {
         "name":"vault:myapp",
         "source":{
            "foo":"myappsbar"
         }
      },
      {
         "name":"vault:application",
         "source":{
            "baz":"bam",
            "foo":"bar"
         }
      }
   ]
}

多個屬性來源

使用 Vault 時,您可以為您的應用程式提供多個屬性來源。例如,假設您已經將資料寫入了Vault中的以下路徑。

secret/myApp,dev
secret/myApp
secret/application,dev
secret/application

寫入的屬性secret/application可用於 使用配置伺服器的所有應用程式。具有該名稱的應用程式myApp將具有寫入secret/myAppsecret/application可用的任何屬性。當myAppdev配置檔案,然後將會寫入到上述所有提供給它的路徑,在列表中的第一路徑屬性的優先順序比其他的都要高。

5.1.5 與所有應用程式共享配置

基於檔案的儲存庫

基於檔案(即:git,svn和本地)的倉庫,並在檔名稱資源application*的所有客戶端應用程式之間共享(application.propertiesapplication.ymlapplication-*.properties等)。您可以使用具有這些檔名的資源來配置全域性預設值,並根據需要使其覆蓋特定於應用程式的檔案。

The #_property_overrides [property overrides]特性也可用於設定全域性預設值,並且可以使用佔位符應用程式在本地覆蓋它們。

使用“本機”配置檔案(本地檔案系統後端),建議您使用不屬於伺服器自身配置的顯式搜尋位置。否則,在預設搜尋位置中的application* 資源將被刪除,因為它們是伺服器的一部分。

Vault 伺服器

將Vault用作後端時,可以通過在secret/application中放置配置來與所有應用程式共享配置。例如,如果您執行此Vault命令

$ vault write secret/application foo=bar baz=bam

所有使用配置伺服器的應用程式都將具有這些屬性 foo和baz,並可供它們使用。

5.1.6 JDBC後端

Spring Cloud Config Server支援JDBC(關係資料庫)作為配置屬性的後端。您可以通過新增spring-jdbc到類路徑,使用“jdbc”配置檔案或新增JdbcEnvironmentRepository型別的bean 來啟用此功能。如果您在類路徑中包含正確的依賴關係,Spring Boot將配置資料來源(有關更多詳細資訊,請參閱使用者指南)。

資料庫需要有一個名為“PROPERTIES”的表,其中包含“APPLICATION”,“PROFILE”,“LABEL”(通常Environment 含義)列以及Properties樣式中的鍵值對“KEY”和“VALUE” 。所有的欄位在Java中都是String型別的,所以你可以把它們變成VARCHAR型別並可以設定任何你需要的長度。屬性值的行為方式與它們來自Spring Boot屬性檔案{application}-{profile}.properties(包括所有加密和解密)的行為相同,後者將作為後處理步驟(即:不在儲存庫實現中直接使用)應用。

5.1.7 複合環境儲存庫

在某些情況下,您可能希望從多個環境儲存庫中提取配置資料。要做到這一點,你可以在配置伺服器的應用程式屬性或YAML檔案中啟用多個配置檔案。例如,如果您想要從Git儲存庫以及SVN儲存庫中提取配置資料,則可以為您的配置伺服器設定以下屬性。

spring:
  profiles:
    active: git, svn
  cloud:
    config:
      server:
        svn:
          uri: file:///path/to/svn/repo
          order: 2
        git:
          uri: file:///path/to/git/repo
          order: 1

除了指定一個URI的每個repo外,還可以指定一個order屬性。該order屬性允許您指定所有儲存庫的優先順序。order屬性的數值越低,優先順序越高。儲存庫的優先順序順序將有助於解決包含相同屬性值的儲存庫之間的任何潛在衝突。

從環境倉庫中檢索值時,任何型別的失敗都將導致整個複合環境的失敗。

使用複合環境時,重要的是所有倉庫包含相同的標籤。如果您的環境類似於上述環境,並且您使用master標籤請求配置資料,但不包含master分支的SVN倉庫的整個請求將失敗。

自定義組合環境儲存庫

除了使用Spring Cloud環境儲存庫之外,還可以提供自己的EnvironmentRepositorybean作為組合環境的一部分。要做到這一點,你的bean必須實現EnvironmentRepository介面。如果您想在EnvironmentRepository組合環境中控制自定義的優先順序,則還應該實現Ordered介面並覆蓋getOrdered方法。如果你沒有實現Ordered介面,那麼你的 EnvironmentRepository將被賦予最低優先順序。

5.1.8 屬性過載

配置伺服器具有“覆蓋”功能,允許操作員使用普通的 Spring Boot 鉤子為應用程式提供配置屬性,這些配置屬性不會被應用程式意外更改。要宣告覆蓋只需要新增一個名稱 – 值對的map到spring.cloud.config.server.overrides裡面。例如

spring:
   cloud:
     config:
       server:
         overrides:
           foo:bar

將導致配置客戶端的所有應用程式獨立於自己的配置進行讀取foo=bar 。(當然,應用程式可以用它喜歡的任何方式使用Config Server中的資料,因此覆蓋不可執行,但是如果它們是Spring Cloud Config客戶端,它們會提供有用的預設行為。)

一般來講,帶有“$ {}”的Spring環境佔位符可以通過使用反斜槓(“\”)轉義“$”或“{”,例如\${app.foo:bar}解析為“bar”,除非應用程式提供自己的“app.foo”。請注意,在YAML中,當您在伺服器上配置覆蓋時,您不需要轉義反斜槓本身,而是在屬性檔案中進行轉義。

您可以將客戶端中所有覆蓋的優先順序更改為預設值,允許應用程式通過spring.cloud.config.overrideNone=true在遠端儲存庫中設定標誌(預設值為false)在環境變數或系統屬性中提供自己的值 。

5.2 健康指標

配置伺服器附帶一個執行狀況指示器,檢查配置 EnvironmentRepository是否正常。預設情況下,它將詢問EnvironmentRepository 中命名為app的應用程式,default配置檔案和預設標籤由EnvironmentRepository實現來提供。

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

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

您可以通過設定spring.cloud.config.server.health.enabled=false來禁用健康指示器。

5.3 安全

您可以以任何對您有意義的方式(從物理網路安全到OAuth2承載令牌)自由地保護您的配置伺服器,Spring Security和Spring Boot可以輕鬆地做任何事情。

要使用預設的 Spring Boot 配置的HTTP Basic安全性,只需在類路徑中加入Spring Security(例如通過 spring-boot-starter-security)即可。預設是一個使用者名稱“user”和一個隨機生成的密碼,這在實際中並不會很有用,所以我們建議你配置密碼(通過 security.user.password)並加密它(參見下面的說明,瞭解如何做到這一點)。

5.4 加密和解密

重要

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

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

如果你正在為配置客戶端應用程式設定一個遠端配置庫,它可能包含這樣的一個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節點(假設這些將被保護,並且只能被授權代理訪問)。如果您正在編輯遠端配置檔案,則可以使用配置伺服器通過傳送到/encrypt節點來加密值,例如

$ curl localhost:8888 / encrypt -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda

如果您正在加密的值中包含需要進行網址編碼的字元,則應使用--data-urlencode選項來curl確保其編碼正確。

請確保不要在加密值中包含任何curl命令統計資訊。將該值輸出到檔案可以幫助避免此問題。

反向操作也可以通過/decrypt(假設伺服器配置有對稱金鑰或完整金鑰對):

$ curl localhost:8888/decrypt -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret 

如果你正在用curl來測試,那麼使用 --data-urlencode(而不是-d)或者設定一個顯式Content-Type: text/plain來確保curl在有特殊字元(’+’特別棘手)時正確地編碼資料。

在加入{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+...

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

5.5 金鑰管理

配置伺服器可以使用對稱(共享)金鑰或不對稱金鑰(RSA金鑰對)。非對稱選擇在安全性方面是優越的,但是使用對稱金鑰通常更方便,因為它在bootstrap.properties檔案中採用單獨的屬性值來配置。

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

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

  • location(一個Resource位置),
  • password (解鎖金鑰庫)和
  • alias (以識別儲存庫中的哪個金鑰將被使用)。

加密使用公鑰完成,解密需要私鑰。因此,原則上只能在伺服器上配置公用金鑰(如果您只想進行加密),並準備用私鑰在本地解密值。在實踐中,您可能不想這樣做,因為它將金鑰管理過程分散到所有客戶端,而不是集中在伺服器中。另一方面,如果您的配置伺服器確實相對不安全,或者只有少數客戶端需要加密的屬性,那麼這將會是一個有用的選項。

5.6 建立一個金鑰庫進行測試

要建立一個測試金鑰庫,可以這樣做:

$ 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檔案放入類路徑(例如),然後放到配置伺服器的bootstrap.yml中:

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

5.7 使用多個按鍵和按鍵旋轉

除了加密屬性值的{cipher}字首之外,配置伺服器還會在(Base64編碼的)密碼文字開始之前查詢{name:value}字首(零個或多個)。金鑰被傳遞給一個TextEncryptorLocator,它可以做任何邏輯以需要找到一個TextEncryptor密碼。如果你已經配置了一個keystore(encrypt.keystore.location),那麼預設的定位器將會在儲存器中尋找由“key”字首提供的別名,也就是說這樣的密文:

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

定位器將查詢名為“testkey”的鍵。祕密也可以通過{secret:…​}字首中的一個值來提供,但是如果它不是預設的,則使用金鑰庫密碼(這是您在構建金鑰庫時不會指定的祕密)。如果您確實提供了密碼,建議您使用自定義密碼SecretLocator來加密密碼。

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

如果你想讓配置伺服器處理所有的加密和解密,那麼{name:value}字首也可以被新增明文張貼到/encrypt節點。

5.8 服務加密屬性

有時候你希望客戶端在本地解密配置,而不是在伺服器端進行解密。在這種情況下,您仍然可以對節點進行加密或解密(如果您提供encrypt.*配置以查詢某個金鑰),但是您需要使用spring.cloud.config.server.encrypt.enabled=false來明確關閉對傳出屬性的解密。如果你不關心節點,並且如果你既不配置金鑰也不啟用標誌的話,那麼它應該工作。