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位置(例如“ git@github.com: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}。
如果您使用AWS CodeCommit URI提供用户名和密码,则这些必须是用于访问存储库的AWS accessKeyId和secretAccessKey。如果您未指定用户名和密码,则将使用AWS Default Credential Provider Chain检索accessKeyId和secretAccessKey 。
如果您的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: git@gitserver.com: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.basedir
或spring.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/config
和file:/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/myApp
和secret/application
可用的任何属性。当myApp
有dev
配置文件,然后将会写入到上述所有提供给它的路径,在列表中的第一路径属性的优先级比其他的都要高。
5.1.5 与所有应用程序共享配置
基于文件的存储库
基于文件(即:git,svn和本地)的仓库,并在文件名称资源application*
的所有客户端应用程序之间共享(application.properties
,application.yml
, application-*.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环境存储库之外,还可以提供自己的
EnvironmentRepository
bean作为组合环境的一部分。要做到这一点,你的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
),或者通过密钥库(例如,由keytool
JDK附带的实用程序创建的密钥库)。密钥存储属性是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
来明确关闭对传出属性的解密。如果你不关心节点,并且如果你既不配置密钥也不启用标志的话,那么它应该工作。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/98431.html