14.5.1 在 Git 中加密属性

除了使用未加密的值外,Config Server 还支持在 Git 存储的配置文件中使用加密值。在 Git 存储中使用加密值的关键,实际上是一个密钥,一个用于加密的密钥。

要启用对属性加密,需要使用加密密钥。在将值传到客户端之前,使用密钥对加密值进行解密。Config Server 支持对称加密和非对称加密。设置对称加密的密钥,可在 Config Server 自身的配置中设置 encrypt.key 属性值。这个值可以用作加密和解密:

encrypt:
  key: s3cr3t

在启动配置(例如 bootstrap.propertiesbootstrap.yml 中)中设置此属性非常重要。这样使 Config Server 对外提供服务之前,可以通过自动配置加载此属性。

为了提高安全性,您可以选择使用非对称加密密钥,如 RSA 密钥对或对 keystore 的引用。要创建这样的密钥对,可以使用 keytool 命令行工具:

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

生成的 keystore 将写入名为 keystore.jks 的文件中,可以选择把 keystore 文件保存在文件系统上,或将其放置在应用程序本身中。无论哪种情况,您都需要在 Config Server 的 bootstrap.yml 文件中,指定 keystore 文件的位置以及授权信息。

注意:要在 Config Server 中使用加密功能,必须安装 Java Cryptography Extensions Unlimited Strength 策略文件。详细信息请参阅 Oracle 的 Java SE 页:http://www.oracle.com/technetwork/java/javase/downloads/index.html

假设您选择将 keystore 打包到应用程序中,并放在类路径的根目录。然后就可以通过配置 Config Server 的以下属性使用 keystore:

encrypt:
  key-store:
    alias: tacokey
    location: classpath:/keystore.jks
    password: l3tm31n
    secret: s3cr3t

有了密钥或 keystore,您现在需要一些加密的数据。Config Server 提供了 /encrypt 加密接口。所要做的就是通过 POST 请求,把一些要加密的数据发送到 /encrypt 接口。例如,假设您要加密 MongoDB 数据库的密码。使用 curl 可以这样加密这个密码:

$ curl localhost:8888/encrypt -d "s3cr3tP455w0rd"
93912a660a7f3c04e811b5df9a3cf6e1f63850cdcd4aa092cf5a3f7e1662fab7

提交 POST 请求后,您将收到一个加密值作为响应。剩下的就是复制该值,并将其粘贴到在 Git 存储库中保存的配置文件中。

要设置 MongoDB 密码,请在 application.yml 中添加 spring.data.mongodb.password 属性:

spring:
  data:
    mongodb:
      password: '{cipher}93912a660a7f3c04e811b5df9a3cf6e1f63850...'

请注意,给 spring.data.mongodb.password 设置的值是用单引号(')引起来的,前缀为 {cipher}。这会让 Config Server 识别到,这是一个加密值,而不是普通的未加密值。

application.yml 的修改提交并推送到到 Git 存储库以后,Config Server 就准备好了提供加密属性服务。要查看它的运行情况,可使用 curl 模拟客户端调用:

$ curl localhost:8888/application/default | jq
{
  "name": "app",
  "profiles": [
    "prof"
  ],
  "label": null,
  "version": "464adfd43485182e4e0af08c2aaaa64d2f78c4cf",
  "state": null,
  "propertySources": [
    {
      "name": "http://localhost:10080/tacocloud/tacocloudconfig/application.yml",
      "source": {
        "spring.data.mongodb.password": "s3cr3tP455w0rd"
      }
    }
  ]
}

如你所见,属性 spring.data.mongodb.password 的值是解密的形式。默认情况下,Config Server 提供的任何加密值,在后端 Git 存储库中都是加密的;它们在被使用之前会被解密。这意味着使用 Config Server 的客户端应用程序,不需要任何特殊的代码或配置来接收在 Git 中加密的属性。

如果您希望 Config Server 提供仍然加密的属性,您可以设置 spring.cloud.config.server.encrypt.enabled 属性为 false:

spring:
  cloud:
    config:
      server:
        git:
          uri: http://localhost:10080/tacocloud/tacocloud-config
        encrypt:
          enabled: false

这将导致 Config Server 提供的所有属性值,包括加密属性值,与 Git 存储库中设置的值完全相同。再次使用 curl 命令模拟客户端调用,以显示禁用解密后的效果:

$ curl localhost:8888/application/default | jq
{
  ...
  "propertySources": [
    {
        "name": "http://localhost:10080/tacocloud/tacocloudconfig/application.yml",
        "source": {
        "spring.data.mongodb.password": "{cipher}AQA4JeVhf2cRXW..."
        }
    }
  ]
}

当然,如果客户端接收到加密后的属性值,那么客户端现在就负责自行解密了。

尽管可以将加密的属性存储在 Git 中,再由 Config Server 提供服务。但我们已经看到加密并不是 Git 原生的能力,这需要您做一些工作,以便使用任何写入 Git 存储库的数据。而且,除非您的应用程序自行解密,否则使用 Config Server API 能够让任何人获取解密后的信息。让我们看看另一种配置 Config Server 的选择,它只为那些有权看到他们的使用方提供服务。

最后更新于