为生产配置 Spring Cloud Config Server 和 Spring Cloud Vault

Posted

技术标签:

【中文标题】为生产配置 Spring Cloud Config Server 和 Spring Cloud Vault【英文标题】:Configuring Spring Cloud Config Server and Spring Cloud Vault for production 【发布时间】:2017-06-23 23:21:21 【问题描述】:

我正在尝试设置由 Spring Cloud Vault 秘密管理支持的 Spring Cloud Config Server。我对 Spring 比较陌生,但我在这里尝试了以下说明和示例:-

http://cloud.spring.io/spring-cloud-vault-config/

只要您按照默认设置(如 Vault 端点的 http、localhost 和 8200)以及 tls_disable = 1 来关闭 SSL,一切都会正常工作。但是,对于任何真实环境,这些设置都不是实用的设置,并且几乎没有任何示例可以对此有所帮助。任何人都可以提供一个工作示例吗?

我已成功设置启用 TLS 的保管库。我已经成功设置了一个使用自签名证书连接的配置服务器。我什至可以将一个秘密值注入配置服务器并通过@Value@PostConstruct 公开它。

所有这些都有效。但是,当我尝试利用 Spring Conig 端点访问保险库时,我得到以下信息:-


  "timestamp": 1486413850574,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "org.springframework.web.client.ResourceAccessException",
  "message": "I/O error on GET request for \"http://127.0.0.1:8200/v1/secret/myapp\": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect",
  "path": "/myapp/default"

即使我在bootstrap.yml 中设置了覆盖,配置服务器仍在使用默认值。:-

server:
    port: 8888

spring:
    profiles:
        active: vault

spring.cloud.vault:
    host: myhost.mydomain.com
    port: 8200
    scheme: https
    authentication: TOKEN
    token: 0f1887c3-d8a8-befd-a5a2-01e4e066c50
    ssl:
        trust-store: configTrustStore.jks
        trust-store-password: changeit

如您所见,它应该指向 myhost.mydomain.com 而不是 127.0.0.1,它应该使用 https,而不是 http 作为协议方案。

我不确定为什么它将这些默认值用于配置服务器端点,但在 spring cloud vault 启动期间使用正确的设置。我正在使用 Spring Dalsten.M1 和 Spring Cloud Vault 1.0.0.M1 的所有最新稳定版本。我意识到这些是里程碑版本。我也试过卡姆登和布里克斯顿的组合,但没有运气。如果需要,我可以提供代码。

非常感谢任何帮助。

【问题讨论】:

cloud.spring.io/spring-cloud-vault-config 根本不使用配置服务器。它直接进入保险库。要使用带有保险库的配置服务器作为后端,请参阅github.com/spring-cloud/spring-cloud-config/blob/master/docs/…。否则更改标题以删除配置服务器,我将按原样查看问题。 感谢您的快速回复。问题的本质来自 Spring Cloud Config Server 和 Spring Cloud Vault Config Starter 的使用。我现在已经在自己解决这个问题上取得了一些成功,我将在此回复后发布为已接受的答案,并对问题进行一些澄清。 【参考方案1】:

正如我在回复 spensergibb 时提到的,我自己已经成功解决了这个问题。根据他的 cmets,我将澄清我的意图,因为这将有助于对这个问题达成共识。我正在尝试做两件事:-

    建立一个使用 Vault 作为后端的配置服务器(与默认的 GIT 后端相反)并将 Vault API 公开给客户端应用程序(通过 TLS),以便他们可以检索自己的机密。我不希望我的所有客户端应用程序都直接连接到 Vault。我希望他们通过让配置服务器连接到 Vault 来从配置服务器获取配置。直到昨晚我都无法实现这个目标,除非我将所有内容都设置为默认值,禁用 TLS 并使用环回地址、Vault 软件的端口 8200 等。显然默认值对于我们部署的任何环境都不实用。我会提到 spencergibb 发布的链接确实帮助我理解了为什么这不起作用,但原因的微妙之处在于我之前错过了它。请继续阅读我的解释。

    我希望配置服务器直接从 Vault 配置自身。即通过 Spring Cloud Vault Config 连接到 Vault。如文档中所述,这立即对我有用。然而,这个目标有点微不足道,因为我目前没有真正的用例。但我想了解它是否可以完成,因为我没有看到为什么不这样做的真正原因,而且这似乎是集成 Vault 的良好第一步。

这两种功能之间的区别帮助我理解了问题源于 Spring Cloud Config Server 和 Spring Cloud Vault 似乎使用两个不同的 bean 来注入 Vault 配置属性这一事实。 Spring Cloud Config Server 使用带有 @ConfigurationProperties("spring.cloud.config.server.vault") 注释的 VaultEnvironmentRepository,Spring Cloud Vault 使用带有 @ConfigurationProperties("spring.cloud.vault") 注释的 VaultProperties。

这导致我向我的引导 yml 添加了两个不同的配置。

server:
    port: 8888

spring:
    profiles:
        active: local, vault

    application:
        name: quoting-domain-configuration-server

    cloud:
        vault:
            host: VDDP03P-49A26EF.lm.lmig.com
            port: 8200
            scheme: https
            authentication: TOKEN
            token: 0f1997c3-d8a8-befd-a5a2-01e4e066c50a
            ssl:
                trust-store: configTrustStore.jks
                trust-store-password: changeit

        config:
            server:
                vault:
                    host: VDDP03P-49A26EF.lm.lmig.com
                    port: 8200
                    scheme: https
                    authentication: TOKEN
                    token: 0f1997c3-d8a8-befd-a5a2-01e4e066c50a

注意相同的配置细节。只是不同的 yml 路径。这是我错过的微妙点,因为我首先让目标 1 开始工作,并假设相同的配置适用于两个目标。 (注意:令牌和密码是人为设计的)。

除了 SSL 握手错误之外,这几乎可以正常工作。如您所见,spring.cloud.config.server.vault 路径上没有设置 SSL 属性。 VaultProperties bean 不支持它们。我不知道如何处理这个问题(也许是我找不到的另一个非保险库特定的 bean)。我的解决方案是像这样简单地强制自己进行证书配置:-

@SpringBootApplication
@EnableConfigServer
public class Application

    public static void main(String[] args)
    
        System.setProperty("javax.net.ssl.trustStore",
            Application.class.getResource("/configTrustStore.jks").getFile());
        System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
        SpringApplication.run(Application.class, args);
    

这个 SSL 解决方案非常丑陋。我确信必须有更好的方法来完成这部分。所以我愿意接受其他建议。但是,一旦我完成了上述所有步骤,现在一切正常。

【讨论】:

看起来我可以使用 yml 中的 server.ssl 属性来整理它。【参考方案2】:

感谢您的来信。我正在努力让这个工作。我能够让客户端服务连接到 Spring Cloud Config 服务器和 Vault 服务器,但我无法让 Spring Cloud Config 服务器连接到 Vault 服务器。

在将您的配置复制到我的 Spring Cloud Config 服务器后,我什至感到很吃力。虽然我最终让它与您的配置一起使用,但我能够将它削减很多。关键是令牌不属于 Spring Cloud Config 服务器。它属于客户端。

我在浏览器中尝试http://localhost:8888/application/default,但得到以下结果:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu May 11 14:21:31 EDT 2017
There was an unexpected error (type=Bad Request, status=400).
Missing required header: X-Config-Token

我使用 PostMan 发送带有 X-Config-Token 标头的请求,其中包含 Vault 令牌并且它有效。

这是我的最终配置。

server:
  port: $PORT:8888

management:
  context-path: /manage
  security:
    enabled: true

spring:
  profiles:
    active: git,vault

  application:
    name: config-server

  cloud:
    config:
      server:
        git:
          order: 1
          uri: file:///temp/config-server/config

        vault:
          order: 0
          host: localhost
          port: 8200
          scheme: http

所以看起来您需要将令牌添加到客户端。也许使用spring.cloud.config.token

【讨论】:

【参考方案3】:

改为

@SpringBootApplication
@EnableConfigServer
public class Application

    public static void main(String[] args)
    
        System.setProperty("javax.net.ssl.trustStore",
            Application.class.getResource("/configTrustStore.jks").getFile());
        System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
        SpringApplication.run(Application.class, args);
    

bootstrap yml ->
javax.net.ssl.trustStore: /configTrustStore.jks
javax.net.ssl.trustStorePassword: changeit

【讨论】:

【参考方案4】:

虽然我回复晚了。但我能够配置 Spring Cloud 配置服务器以使用 Vault 作为后端,并通过证书进行 CERT 身份验证。此外,您不需要在 GET 请求中发送 X-Config-Token。因此,您的配置服务器 GET 请求将以与 GITHUB 作为后端相同的方式工作。因为我的实现将即时获取令牌并通过附加标头更改传入请求。我建议检查我的教程和 github repo 中的所有步骤。

这是我的教程:https://medium.com/@java.developer.raman/enable-spring-config-server-to-use-cert-authentication-with-vault-as-back-end-ff84e1ef2de7?sk=45a26d7f1277437d91a5cff3d5997287

还有 GitHub 仓库:https://github.com/java-developer-raman/config-server-vault-backend

【讨论】:

以上是关于为生产配置 Spring Cloud Config Server 和 Spring Cloud Vault的主要内容,如果未能解决你的问题,请参考以下文章

Spring cloud config 分布式配置中心 总结

Spring Cloud学习笔记 篇一:分布式配置中心 Spring Colud Config

Spring Cloud云服务架构 - commonservice-config配置服务搭建

Spring Cloud Config

整合Spring Cloud云服务架构 - commonservice-config配置服务搭建

整合spring cloud云服务架构 - commonservice-config配置服务搭