您如何存储秘密?
密码,API密钥,安全令牌和机密数据属于秘密类别。 那是不应该存在的数据。 在容易猜测的位置,不得以纯文本格式提供。 实际上,不得在任何位置以明文形式存储它。
可以使用Spring Cloud Config Server或TomEE对敏感数据进行加密。 加密数据比未加密数据好了一步。 加密在另一方面强加了对用户端解密的需求,这要求分发解密密钥。 现在,您将钥匙放在哪里? 密钥受密码保护吗? 您将密码放在哪里? 您在多少系统上分发密钥和密码?
如您所见,加密引入了鸡蛋问题。 存储解密密钥使应用程序可以解密数据。 它还允许攻击向量。 未经授权的人可以通过访问机器来访问解密密钥。 该人可以解密可通过此密钥解密的数据。 该密钥是静态的,因此泄漏的密钥需要更改密钥。 数据需要重新加密,凭据需要更改。 在线测量不可能发现这种泄漏,因为一旦获得数据就可以离线解密。
一种方法是在应用程序启动之前将密钥放在难以猜测的位置,并在将密钥读取到内存后擦除密钥。 按键可用的时间缩短了。 缩短了攻击时间范围,但关键仍然在那里。 擦除密钥仅对一个应用程序启动有效。 众所周知,云中的容器和微服务一旦崩溃就会重新启动。 由于密钥已丢失,因此不再可能重新启动应用程序。
等等,有希望!
正确地进行加密非常困难,而如果自己进行加密,则管理秘密就更加困难。 保险柜正好解决了这些问题。 它有助于解决鸡蛋问题,并且带有加密功能。 保险柜是一项用于管理机密的服务。 它提供了一个API,可根据策略访问机密。 API的任何用户都需要进行身份验证,并且只能看到其被授权的机密。 保管箱使用带有GCM的 256位AES加密数据。 它可以将数据存储在各种后端(文件,Amazon DynamoDB,Consul等)中。 另一个关键方面是,保管箱从不将密钥存储在持久位置中。 启动/重新启动保管库始终需要一个或多个操作员才能解封保管库。 但是,让我们先从基础开始。
保险柜并不是所有安全问题的答案。 值得检查Vault安全模型文档以了解威胁模型。
要引导Vault,您需要从https://www.vaultproject.io/downloads.html下载二进制文件。 Vault用Go编写,二进制文件可用于各种平台。 解压缩下载的文件,即可开始使用Vault。
接下来启动Vault服务器。 您需要一个配置文件来指定一些选项。
vault.conf
backend "inmem" {
}listener "tcp" {address = "0.0.0.0:8200"tls_disable = 1
}disable_mlock = true
此配置适用于大多数平台,可以尝试使用Vault的第一步。 不要在生产中使用它。
通过启动Vault
$ vault server -config vault.conf
保管箱将作为前台进程启动。
恭喜,您已启动保险柜。
现在是打开第二个控制台以使用Vault执行管理任务的好时机。 Vault现在以纯文本模式运行,因为已禁用TLS / SSL。 您需要设置VAULT_ADDR
环境变量,以告知Vault客户端使用纯文本:
$ export VAULT_ADDR=http://127.0.0.1:8200
保管箱已启动。 在实际开始使用保管库之前,它需要另外两个步骤。 保管箱需要初始化和启封。 初始化是初始密钥生成的过程。 启封正在为Vault提供密钥,因此Vault可以解密加密的数据并开始为客户端提供服务。
保管箱在初始化时会创建两件事:
- 主密钥和密钥拆分
- 根令牌
保险柜允许使用Shamir Secret Sharing算法共享密钥。 数据通常用一个密钥加密。 有权访问密钥的人作为一个人就可以完全控制所有数据。 有时您不想要那样。 通常,您希望在多个人之间分配主密钥,因此,没有一个人可以控制所有加密数据。 保管箱允许指定总数的密钥共享和初始化期间解封Vault所需的密钥共享数。 保险柜初始化后,便无法更改该设置。 从控制台初始化保管库将显示完整密钥。 您可能希望通过DevOps工具采用API进行初始化,例如,向应该接收密钥共享的操作员发送安全消息。
使用以下方法初始化保管箱:
$ vault init -key-shares=5 -key-threshold=2
保管箱将显示密钥共享和根密钥。 请注意,这些值是随机的,并且在每次初始化时都会更改。 请小心该输出,因为您只会看到一次。 之后没有办法检索密钥和令牌。 将Vault与真实数据一起使用时,请仔细阅读说明,否则会丢失数据。
Key 1: 99eb89735688ad7a29bb1ff27383bd1005a22a62c97f14357ea4f5f98c1d2c8c01
Key 2: 0c5605b16905794a302603bbeb8f6c8ad5ecf7e877f0e29084f838eba931b86902
Key 3: 7f3d88067c7e355acea4fe756a8b23fc6cd6bc671d7cb0f3d2cc8ae543dc3dc303
Key 4: 3d37062e1704ca2a02073b29c097d5a56e7056e710f515c16b40b9cfe3698bb804
Key 5: 4e5c8b99027f863afc85c6e741939ad3d74a1d687a7947a23d740bc109840e1205
Initial Root Token: 9a63de21-8af7-311a-9a5a-151b6a0d4795Vault initialized with 5 keys and a key threshold of 2. Please
securely distribute the above keys. When the Vault is re-sealed,
restarted, or stopped, you must provide at least 2 of these keys
to unseal it again.Vault does not store the master key. Without at least 2 keys,
your Vault will remain permanently sealed.
然后,您需要打开Vault的密封。 保管箱不会将密钥存储在磁盘上。 它一直存储在内存中。 初始化后,(重新)启动Vault后,您需要使用所需数量的密钥共享来打开Vault的密封,以便Vault可以提供机密信息。 在这种情况下,这是两个关键部分。 注意:还有一个Seal命令可以使Vault停止提供机密信息。
$ vault unseal 99eb89735688ad7a29bb1ff27383bd1005a22a62c97f14357ea4f5f98c1d2c8c01
Sealed: true
Key Shares: 5
Key Threshold: 2
Unseal Progress: 1$ vault unseal 7f3d88067c7e355acea4fe756a8b23fc6cd6bc671d7cb0f3d2cc8ae543dc3dc303
Sealed: false
Key Shares: 5
Key Threshold: 2
Unseal Progress: 0
保险柜开封后,您可以开始在保险柜内部存储机密数据。
保险柜需要经过身份验证的访问权限才能从此处继续。 保险柜将令牌用作其传输级别的常规身份验证。
还记得初始化的输出吗? 密钥共享之后的最后一项是根令牌。 目前最简单的方法是使用根令牌。 在控制台上使用令牌的最简单方法是将其存储在环境变量中:
$ export VAULT_TOKEN=9a63de21-8af7-311a-9a5a-151b6a0d4795
$ vault write secret/my-application password=H@rdT0Gu3ss
通用秘密后端允许将任意值存储为键值存储。 单个上下文可以存储一个或多个键值元组。 上下文可以按层次进行组织,使用的数据格式为JSON。
Vault提供除一般的秘密后台其它后端,使证书产生的MySQL,SQL服务器和PostgreSQL,领事和更多 。
认证方式
保险柜主要与令牌一起使用。 每个令牌都分配给可能限制操作和路径的策略。 策略使用基于路径的匹配来应用规则。 令牌可以获取元数据(键值)并显示分配的名称,这使管理对操作更加友好。
您可以手动创建令牌并将其分配给应用程序和用户。 除此之外,还有两种身份验证机制 (LDAP,用户名/密码,GitHub令牌……),允许用户登录并获取令牌。 令牌和身份验证机制可以撤销,这使得锁定特定用户变得容易。
Spring Cloud Vault
我们在Pivotal考察了Vault,并认为它是一种很有前途的工具。 这就是我们构建Spring Cloud Vault的原因。 Spring Cloud Vault是类似于Spring Cloud Config的配置扩展。 Spring Cloud Config的目标是外部配置管理,该管理由存储在各种存储库(例如GitHub,SVN甚至Vault)中的数据支持。
借助Spring Cloud Vault,您可以访问Vault中的秘密。 在启动应用程序时会获取机密。 Spring Cloud Vault使用应用程序中的数据(应用程序名称,活动上下文)来确定存储机密的上下文路径。
/secret/{application}/{profile}
/secret/{application}
/secret/{defaultContext}/{profile}
/secret/{defaultContext}
Spring Cloud Vault入门
首先,您需要一个Spring Boot项目。 start.spring.io是一个很好的起点。 任何空项目都足够。
在您的项目中包含Spring Cloud Vault入门
将以下代码添加到您的构建配置文件中。 这些行包括具有所有必需依赖项的Spring Cloud Vault入门程序。
马文
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-vault-starter-config</artifactId><version>1.0.0.BUILD-SNAPSHOT</version>
</dependency><repositories><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/libs-snapshot</url><snapshots><enabled>true</enabled></snapshots></repository>
</repositories>
摇篮
repositories {maven {url 'https://repo.spring.io/libs-snapshot'}
}dependencies {compile("org.springframework.cloud:spring-cloud-vault-starter-config:1.0.0.BUILD-SNAPSHOT")
}
使用SNAPSHOT
依赖项时,请确保包括Snapshots存储库。
设置配置
Spring Cloud Vault默认使用application
作为默认上下文,并使用spring.application.name
的值作为应用程序上下文。 所有配置都需要在引导程序配置中指定。 对于此示例,我们在src/main/resources
使用bootstrap.yml
:
spring:application.name: my-applicationcloud.vault:token: 9a63de21-8af7-311a-9a5a-151b6a0d4795scheme: http
由于我们已以纯文本HTTP模式启动Vault,因此spring.cloud.vault.scheme
设置为http
。 不要在生产中这样做。 纯文本使整个秘密故事变得毫无用处,因为网络上的所有听众都可以看到您的秘密。 spring.cloud.vault.scheme
默认为https
。
请注意,此处的令牌取自根令牌。 您可以使用以下方法创建新令牌:
$ vault token-create
Key Value
--- -----
token 728d26ae-53a6-d8b6-d7a0-c5f62238ea55
token_accessor 2fd7dcba-39d0-04d3-8d6b-096c3529cf14
token_duration 0
token_renewable true
token_policies [root]
将数据写入保险柜
将一些数据写入保险柜:
$ vault write secret/my-application password=H@rdT0Gu3ss
更新您的Spring Boot应用程序
现在转到您的应用程序启动器类,并增强它以注入秘密。 使用与将其写入保险柜时相同的属性名称:
package example;import javax.annotation.PostConstruct;import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBootVaultHelloWorldApplication {public static void main(String[] args) {SpringApplication.run(SpringBootVaultHelloWorldApplication.class, args);}@Value("${password}")String password;@PostConstructprivate void postConstruct() {System.out.println("My password is: " + password);}
}
其他所有事情都由Spring Cloud Vault本身处理。 现在运行您的应用程序。
恭喜,您成功了!
外表
Spring Cloud Vault现在位于Cloud Incubator中。 它支持令牌和AppId身份验证。 Spring Cloud Vault带有用于各种数据库集成和RabbitMQ / Consul支持的启动程序和依赖项。 您可以在ttps://github.com/spring-cloud-incubator/spring-cloud-vault-config上签出项目和文档 。
我们准备了一些示例,以给您留下印象,如何将Spring Cloud Vault与应用程序集成。 您可以在https://github.com/mp911de/spring-cloud-vault-config-samples中找到示例。
翻译自: https://www.javacodegeeks.com/2016/07/managing-secrets-vault.html