An Intro to Vault – 保险库的介绍

最后修改: 2018年 9月 7日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll explore Hashicorp’s Vault – a popular tool used to securely manage sensitive information in modern application architectures.

在本教程中,我们将探讨Hashicorp的Vault–一种用于安全管理现代应用架构中敏感信息的流行工具

The main topics we’ll cover, include:

我们将涉及的主要议题包括。

  • What problem does Vault try to solve
  • Vault’s architecture and main concepts
  • Setup of a simple test environment
  • Interacting with Vault using its command line tool

2. The Problem with Sensitive Information

2.敏感信息的问题

Before digging into Vault, let’s try to understand the problem it tries to solve: sensitive information management.

在深入了解Vault之前,让我们试着了解它试图解决的问题:敏感信息管理。

Most applications need access to sensitive data in order to work properly. For instance, an e-commerce application may have a username/password configured somewhere in order to connect to its database. It may also need API keys to integrate with other service providers, such as payment gateways, logistics, and other business partners.

大多数应用程序需要访问敏感数据,以便正常工作。例如,一个电子商务应用程序可能在某处配置了一个用户名/密码,以便连接到其数据库。它还可能需要API密钥来与其他服务提供商整合,如支付网关、物流和其他业务伙伴。

Database credentials and API Keys are some examples of sensitive information that we need to store and make available to our applications in a secure way.

数据库凭证和API密钥是一些敏感信息的例子,我们需要以安全的方式存储和提供给我们的应用程序。

A simple solution is to store those credentials in a configuration file and read them at startup time. The problem with this approach is obvious, though. Whoever has access to this file share the same database privileges our application have – usually giving her full access to all stored data.

一个简单的解决方案是将这些凭证存储在一个配置文件中,并在启动时读取它们。不过,这种方法的问题是显而易见的。无论谁拥有这个文件的访问权,都与我们的应用程序拥有的数据库权限相同–通常让她可以完全访问所有存储的数据。

We can try to make things a bit harder by encrypting those files. This approach, however, will not add much in terms of overall security. Mainly, because our application must have access to the master key. Encryption, when used in this way, will only achieve a “false” sense of security.

我们可以尝试通过对这些文件进行加密来增加难度。然而,这种方法在整体安全性方面不会增加多少。主要是由于我们的应用程序必须能够访问主密钥。加密,当以这种方式使用时,只会达到一种 “虚假 “的安全感。

Modern applications and cloud environments tend to add some extra complexity: distributed services, multiple databases, messaging systems and so on, all have sensitive information spread a bit everywhere, thus increasing the risk of a security breach.

现代应用和云环境往往会增加一些额外的复杂性:分布式服务、多个数据库、信息传递系统等等,都会使敏感信息有点到处散布,从而增加安全漏洞的风险。

So, what can we do? Let’s Vault it!

那么,我们能做什么?让我们跳伞吧

3. What Is Vault?

3.什么是金库?

Hashicorp Vault addresses the problem of managing sensitive information – a secret in Vault’s parlance. “Managing” in this context means that Vault controls all aspects of a sensitive piece of information: its generation, storage, usage and, last but not least, its revocation.

Hashicorp Vault解决了管理敏感信息的问题–用Vault的说法就是secret“管理 “在这里意味着Vault控制敏感信息的所有方面:它的生成、存储、使用以及最后但并非最不重要的,它的撤销。

Hashicorp offers two versions of Vault. The open-source version, used in this article, is free to use, even in commercial environments. A paid version is also available, which includes technical support at different SLAs and additional features, such as HSM (Hardware Security Module) support.

Hashicorp提供两个版本的Vault。本文中使用的开源版本可以免费使用,甚至在商业环境中也可以使用。也有付费版本,其中包括不同SLA的技术支持和附加功能,如HSM(硬件安全模块)支持。

3.1. Architecture & Key Features

3.1.结构和主要特点

Vault’s architecture is deceivingly simple. Its main components are:

Vault的架构简单得令人难以置信。它的主要组成部分是。

  • A persistence backend – storage for all secrets
  • An API server which handles client requests and performs operations on secrets
  • A number of secret engines, one for each type of supported secret type

By delegating all secret handling to Vault, we can mitigate some security issues:

通过将所有秘密处理委托给Vault,我们可以减轻一些安全问题。

  • Our applications don’t have to store them anymore – just ask Vault when needed and discard it
  • We can use short-lived secrets, thus limiting the “window of opportunity” where an attacker can use a stolen secret

Vault encrypts all data with an encryption key before writing it to the store. This encryption key is encrypted by yet another key – the master key, used only at startup.

Vault在将所有数据写入存储空间之前,会用一个加密密钥进行加密。这个加密密钥由另一个密钥加密–主密钥,只在启动时使用。

A key point in Vault’s implementation is that it doesn’t store the master key in the server. This means that not even Vault can access its saved data after startup. At this point, a Vault instance is said to be in a “sealed” state.

Vault实现的一个关键点是,它不在服务器中存储主密钥。这意味着在启动后,甚至Vault都不能访问其保存的数据。在这一点上,Vault实例被认为处于 “密封 “状态。

Later on, we’ll go through the steps needed to generate the master key and unseal a Vault instance.

稍后,我们将通过生成主密钥和解封Vault实例所需的步骤。

Once unsealed, Vault will be ready to accept API requests. Those requests, of course, need authentication, which brings us to how Vault authenticates clients and decides what they can or can’t do.

一旦解封,Vault将准备接受API请求。当然,这些请求需要认证,这就涉及到Vault如何认证客户并决定他们可以或不可以做什么。

3.2. Authentication

3.2.认证

To access secrets in Vault a client needs to authenticate itself using one of the supported methods. The simplest method uses Tokens, which are just strings sent on every API request using a special HTTP header.

为了访问Vault中的秘密,客户需要使用支持的方法之一来验证自己。最简单的方法是使用令牌,这只是在每个API请求中使用特殊HTTP头发送的字符串。

When initially installed, Vault automatically generates a “root token”. This token is the equivalent as root superuser in Linux systems, so its use should be limited to a minimum. As a best practice, we should use this root token just to create other tokens with fewer privileges and then revoke it. This isn’t a problem, though, since we can later generate another root token using unseal keys.

最初安装时,Vault会自动生成一个 “根令牌”。这个令牌相当于Linux系统中的root超级用户,所以它的使用应该被限制到最低限度。作为一个最佳实践,我们应该使用这个根令牌只是为了创建其他权限较少的令牌,然后撤销它。不过这并不是一个问题,因为我们以后可以使用解封密钥生成另一个根令牌。

Vault also support other authentication mechanisms such as LDAP, JWT, TLS Certificates, among others. All those mechanisms build on top of the basic token mechanism: once Vault validates our client, it will provide a token that we can then use to access other APIs.

Vault还支持其他认证机制,如LDAP、JWT、TLS证书等。所有这些机制都建立在基本的令牌机制之上:一旦Vault验证了我们的客户端,它将提供一个令牌,然后我们可以用它来访问其他API。

Tokens have a few properties associated with them. The main properties are:

代币有一些与之相关的属性。主要的属性是。

  • A set of associated Policies (see next section)
  • Time-to-live
  • Whether it can be renewed
  • Maximum usage count

Unless told otherwise, tokens created by Vault will form a parent-child relationship. A child token can have at most the same level of privileges it parent has.

除非另有告知,Vault创建的令牌将形成父子关系。一个子代币最多可以拥有与它的父代币相同的权限。

The opposite isn’t true: we can – and usually do – create a child token with restrictive policies Another key point about this relationship: When we invalidate a token, all child tokens, and their descendants are also invalidated.

事实并非如此:我们可以–而且通常也会–创建一个具有限制性策略的子代币 关于这种关系的另一个关键点。当我们使一个令牌失效时,所有的子令牌,以及它们的后代也会失效

3.3. Policies

3.3.政策

Policies define exactly which secrets a client can access and which operations it can perform with them. Let’s see how a simple policy looks like:

策略确切地定义了客户端可以访问哪些秘密以及可以对其进行哪些操作。让我们看看一个简单的策略是什么样子的。

path "secret/accounting" {
    capabilities = [ "read" ]
}

Here we have used the HCL (Hashicorp’s Configuration Language) syntax to define our policy. Vault also supports JSON for this purpose, but we’ll stick to HCL in our examples since it is easier to read.

这里我们使用了HCL(Hashicorp的配置语言)语法来定义我们的策略。Vault也支持JSON用于此目的,但我们将在我们的例子中坚持使用HCL,因为它更容易阅读。

Policies in Vault are “deny by default”. A token attached to this sample policy will get access to secrets stored under secret/accounting and nothing else. At creation time a token can be attached to multiple policies. This is very useful because it allows us to create and test smaller policies and then apply them as required.

Vault中的政策是 “默认拒绝 “的。附在这个样本策略上的令牌将获得对存储在secret/accounting下的秘密的访问,而不是其他。在创建时,一个令牌可以附加到多个策略。这非常有用,因为它允许我们创建和测试较小的策略,然后根据需要应用它们。

Another important aspect of policies is that they leverage lazy-evaluation. This means that we can update a given policy and all tokens will be affected immediately.

策略的另一个重要方面是,它们利用了懒人评价。这意味着我们可以更新一个给定的策略,所有令牌将立即受到影响。

The policies described so far are also called Access Control List Policies, or ACL Policies. Vault also supports two additional policy types: EGP and RGP policies. Those are only available in the paid versions and extend the basic policy syntax with Sentinel support.

到目前为止描述的策略也被称为访问控制列表策略,或ACL策略。Vault还支持另外两种策略类型。EGP和RGP策略。这些策略仅在付费版本中提供,并通过Sentinel支持扩展基本策略语法。

When available, this allows us to take into account in our policies additional attributes such as time of the day, multiple authentication factors, client network origin, and so on. For instance, we can define a policy that allows access to a given secret only on business hours.

在可用的情况下,这使我们能够在我们的策略中考虑到额外的属性,如一天中的时间、多种认证因素、客户网络来源等。例如,我们可以定义一个政策,只允许在工作时间访问一个特定的秘密。

We can find more details on the policy syntax in Vault’s documentation.

我们可以在Vault的文档中找到有关策略语法的更多细节。

4. Secret Types

4.秘密类型

Vault support a range of different secret types which address different use cases:

Vault支持一系列不同的秘密类型,解决不同的使用情况。

  • Key-Value: simple static key-values pairs
  • Dynamically generated credentials: generated by Vault upon request by a client
  • Cryptographic keys: Used to perform cryptographic functions with client data

Each secret type is defined by the following attributes:

每个秘密类型由以下属性定义。

  • mount point, which defines its REST API prefix
  • A set of operations exposed through the corresponding API
  • A set of configuration parameters

A given secret instance is accessible via a path, much like a directory tree in a file system. The first component of this path corresponds to the mount point where all secrets of this type are located.

一个给定的秘密实例可以通过一个路径来访问,很像文件系统中的目录树。该路径的第一个组成部分对应于挂载点,该类型的所有秘密都位于此

For instance, the string secret/my-application corresponds to the path under which we can find key-value pairs for my-application.

例如,字符串secret/my-application对应于我们可以找到my-application的键值对的路径。

4.1. Key-Value Secrets

4.1.键值秘密

Key-Value secrets are, as the name implies, simple pairs in the available under a given path. For instance, we can store the pair foo=bar under the path /secret/my-application. 

键值秘密,顾名思义,就是在给定路径下可用的简单配对。例如,我们可以将一对foo=bar存储在/secret/my-application>路径下。

Later on, we use the same path to retrieve the same pair or pairs – multiple pairs can be stored under the same path.

以后,我们用同一路径检索同一对或多对数据–同一路径下可以存储多个数据对。

Vault support three kinds of Key-Value secrets:

Vault支持三种类型的密钥-价值秘密。

  • Non-versioned Key-Pairs, where updates replace existing values
  • Versioned Key-Pairs, which keep up to a configurable number of old versions
  • Cubbyhole, a special type of non-versioned key-pairs whose values are scoped to a given access token (more on those later).

Key-Value secrets are static by nature, so there is no concept of an associated expiration associated with them. The main use case for this kind of secret is to store credentials to access external systems, such as API keys.

键值型秘密在本质上是静态的,所以不存在与之相关的过期概念。这种秘密的主要用例是存储访问外部系统的凭证,如API密钥。

In such scenarios credential updates are a semi-manual process, usually requiring someone to acquire new credentials and using Vault’s command line or its UI to enter the new values.

在这种情况下,凭证更新是一个半手工的过程,通常需要有人获得新的凭证,并使用Vault的命令行或其用户界面来输入新的值。

4.2. Dynamically Generated Secrets

4.2.动态生成的秘密

Dynamic secrets are generated on the fly by Vault when requested by an application. Vault support several types of dynamic secrets, including the following ones:

当应用程序要求时,Vault会即时生成动态秘密。Vault支持几种类型的动态秘密,包括以下几种。

  • Database credentials
  • SSH Key Pairs
  • X.509 Certificates
  • AWS Credentials
  • Google Cloud service accounts
  • Active Directory accounts

All these follow the same usage pattern. First, we configure the secret engine with the details required to connect to the associated service. Then, we define one or more roles, which describe the actual secret creation.

所有这些都遵循相同的使用模式。首先,我们用连接到相关服务所需的细节来配置秘密引擎。然后,我们定义一个或多个角色,描述实际的秘密创建。

Let’s take the Database secret engine as an example. First, we must configure Vault with all user database connections details, including credentials from a preexisting user with admin privileges to create new users.

让我们以数据库秘密引擎为例。首先,我们必须用所有的用户数据库连接细节来配置Vault,包括来自一个具有管理权限的预先存在的用户的凭证来创建新用户。

Then we create one or more roles (Vault roles, not Database roles) containing the actual SQL statements used to create a new user. Those usually include not only the user creation statement but also all the required grant statements required to access schema objects (tables, views and so on).

然后我们创建一个或多个角色(Vault角色,而不是数据库角色),包含用于创建新用户的实际SQL语句。这些通常不仅包括用户创建语句,还包括访问模式对象(表、视图等)所需的所有grant语句。

When a client accesses the corresponding API, Vault will create a new temporary user in the database using the provided statements and return its credentials. The client can then use those credentials to access the database during the period defined by the time-to-live attribute of the requested role.

当客户访问相应的API时,Vault将使用提供的语句在数据库中创建一个新的临时用户,并返回其证书。然后,客户可以使用这些凭证在所请求的角色的生存时间属性所定义的期间内访问数据库。

Once a credential reaches its expiration time, Vault will automatically revoke any privilege associated with this user. A client can also request Vault to renew those credentials. The renewal process will happen only if supported by the specific database driver and allowed by the associated policy.

一旦一个凭证达到其有效期,Vault将自动撤销与该用户相关的任何特权。客户端也可以要求Vault更新这些凭证。只有在特定的数据库驱动程序支持和相关策略允许的情况下,更新过程才会发生。

4.3. Cryptographic Keys

4.3.加密密钥

Secret engines of type handle cryptographic functions such as encryption, decryption, signing and so on. All those operations use cryptographic keys generated and stored internally by Vault. Unless explicitly told to do so, Vault will never expose a given cryptographic key.

类型的秘密引擎处理加密功能,如加密、解密、签名等。所有这些操作都使用Vault内部生成和存储的加密密钥。除非被明确告知这样做,否则Vault将永远不会暴露一个给定的加密密钥。

The associated API allows clients to send Vault plain-text data and receive an encrypted version of it. The opposite is also possible: We can send encrypted data and get back the original text.

相关的API允许客户发送Vault的纯文本数据并接收其加密版本。反过来也是可以的。我们可以发送加密的数据,并获得原始文本。

Currently, there is only one engine of this type: the Transit engine. This engine supports popular keys types, such as RSA and ECDSA, and also supports Convergent Encryption. When using this mode, a given plaintext value always result in the same cyphertext result, a property that is very useful in some applications.

目前,这种类型的引擎只有一个:Transit引擎。这个引擎支持流行的密钥类型,如RSA和ECDSA,也支持转换加密。当使用这种模式时,一个给定的明文值总是会产生相同的密文结果,这一特性在某些应用中非常有用。

For instance, we can use this mode to encrypt credit card numbers in a transaction log table. With convergent encryption, every time we insert a new transaction, the encrypted credit card value would be the same, thus allowing the use of regular SQL queries for reporting, searching and so on.

例如,我们可以使用这种模式来加密交易日志表中的信用卡号码。通过聚合加密,每次我们插入一个新的交易时,加密的信用卡值将是相同的,从而允许使用常规的SQL查询进行报告、搜索等。

5. Vault Setup

5.金库设置

In this section, we will create a local test environment so we test the Vault’s capabilities.

在本节中,我们将创建一个本地测试环境,以便测试Vault的能力。

Vault’s deployment is simple: just download the package that corresponds to our operating system and extracts its executable (vault or vault.exe on Windows) to some directory on our PATH. This executable contains the server and is also the standard client. There is also an official Docker image available, but we will not cover it here.

Vault的部署很简单:只需下载与我们的操作系统相对应的软件包,并将其可执行文件(vaultvault.exe在Windows中)提取到我们PATH上的某个目录。这个可执行文件包含服务器,也是标准客户端也有一个官方的Docker镜像可用,但我们在此不做介绍。

Vault support a development mode, which is fine for some quick testing and getting used to its command line tool, but it is way too simplistic for real use cases: all data is lost on restart and API access uses plain HTTP.

Vault支持开发模式,这对于一些快速测试和习惯其命令行工具来说是不错的,但对于真正的使用情况来说,它太简单了。所有数据在重启时都会丢失,API访问使用普通HTTP

Instead, we’ll use file-based persistent storage and setup HTTPS so we can explore some of the real-life configuration details that can be a source of problems.

相反,我们将使用基于文件的持久性存储,并设置HTTPS,这样我们就可以探索一些现实生活中的配置细节,这可能是问题的来源。

5.1. Starting Vault Server

5.1.启动Vault服务器

Vault uses a configuration file using HCL or JSON format. The following file defines all the configuration needed to start our server using a file storage and a self-signed certificate:

Vault使用了一个使用HCL或JSON格式的配置文件。以下文件定义了使用文件存储和自签名证书启动我们的服务器所需的所有配置。

storage "file" {
  path = "./vault-data"
}
listener "tcp" {
  address = "127.0.0.1:8200"
  tls_cert_file = "./src/test/vault-config/localhost.cert"
  tls_key_file = "./src/test/vault-config/localhost.key"
}

Now, let’s run Vault. Open a command shell, go to the directory containing our configuration file and run this command:

现在,让我们来运行Vault。打开一个命令外壳,进入包含我们的配置文件的目录,运行这个命令。

$ vault server -config ./vault-test.hcl

Vault will start and show a few initialization messages. They’ll include its version, some configuration details and the address where the API is available. That’s it – our Vault server is up and running.

Vault将启动并显示一些初始化信息。它们将包括其版本、一些配置细节和API可用的地址。就这样,我们的Vault服务器已经启动并运行了。

5.2. Vault Initialization

5.2.金库初始化

Our Vault server now is running, but since this is its first run, we need to initialize it.

我们的Vault服务器现在正在运行,但由于这是它的第一次运行,我们需要初始化它。

Let’s open a new shell and execute the following commands to achieve this:

让我们打开一个新的shell,执行以下命令来实现这一目标。

$ export VAULT_ADDR=https://localhost:8200
$ export VAULT_CACERT=./src/test/vault-config/localhost.cert
$ vault operator init

Here we have defined a few environment variables, so we don’t have to pass them to Vault every time as parameters:

这里我们定义了一些环境变量,所以我们不必每次都把它们作为参数传给Vault。

  • VAULT_ADDR: base URI where our API server will serve requests
  • VAULT_CACERT: Path to our server’s certificate public key

In our case, we use the VAULT_CACERT so we can use HTTPS to access Vault’s API. We need this because we’re using self-signed certificates. This would not be necessary for productions environments, where we usually have access to CA-signed certificates.

在我们的案例中,我们使用VAULT_CACERT,所以我们可以使用HTTPS来访问Vault的API。我们需要这个,因为我们使用的是自签名的证书。这对于生产环境来说是没有必要的,在那里我们通常可以获得CA签名的证书。

After issuing the above command, we should see a message like this:

发出上述命令后,我们应该看到这样的信息。

Unseal Key 1: <key share 1 value>
Unseal Key 2: <key share 2 value>
Unseal Key 3: <key share 3 value>
Unseal Key 4: <key share 4 value>
Unseal Key 5: <key share 5 value>

Initial Root Token: <root token value>

... more messages omitted

The five first lines are the master key shares that we will later use to unseal Vault’s storage. Please note that Vault only displays the master key shares will during initialization – and never more. Take note and store them safely or we’ll lose access to our secrets upon server restart!

前面的五行是主密钥共享,我们以后将用它来解封Vault的存储。请注意,Vault只在初始化期间显示主密钥共享–而不是更多。 注意并安全地存储它们,否则在服务器重新启动时,我们将失去对秘密的访问!

Also, please take note of the root token, as we will need it later. Unlike unseal keys, root tokens can easily be generated at a later time, so it is safe to destroy it once all configuration tasks are complete. Since we will be issuing commands later that require an authentication token, let’s save the root token for now in an environment variable:

另外,请注意根令牌,因为我们以后会需要它。与解封密钥不同,根令牌很容易在以后生成,所以在所有配置任务完成后销毁它是安全的。由于我们以后会发布需要认证令牌的命令,让我们暂时把根令牌保存在一个环境变量中。

$ export VAULT_TOKEN=<root token value> (Unix/Linux)

Let’s see our server status now that we have initialized it, with the following command:

让我们看看我们的服务器状态,现在我们已经初始化了它,使用以下命令。

$ vault status
Key                Value
---                -----
Seal Type          shamir
Sealed             true
Total Shares       5
Threshold          3
Unseal Progress    0/3
Unseal Nonce       n/a
Version            0.10.4
HA Enabled         false

We can see that Vault is still sealed. We can also follow the unseal progress: “0/3” means that Vault needs three shares, but got none so far. Let’s move ahead and provide it with our shares.

我们可以看到,金库仍然被密封。我们也可以关注解封的进度。”0/3 “意味着Vault需要三份股份,但到目前为止还没有得到。让我们继续前进,向它提供我们的股份。

5.3. Vault Unseal

5.3. 保险库解封

We now unseal Vault so we can start using its secret services. We need to provide any three of the five key shares in order to complete the unseal process:

我们现在解除Vault的封印,这样我们就可以开始使用它的秘密服务。我们需要提供五个密钥份额中的任何三个,以完成解封过程。

$ vault operator unseal <key share 1 value>
$ vault operator unseal <key share 2 value>
$ vault operator unseal <key share 3 value>

After issuing each command vault will print the unseal progress, including how many shares it needs. Upon sending the last key share, we’ll see a message like this:

在发出每条命令后,vault将打印解封的进度,包括它需要多少个份额。在发送最后一个密钥共享时,我们会看到这样的信息。

Key             Value
---             -----
Seal Type       shamir
Sealed          false
... other properties omitted

The “Sealed” property is “false” in this case, which means that Vault is ready to accept commands.

在这种情况下,”密封 “属性为 “假”,这意味着Vault已经准备好接受命令。

6. Testing Vault

6.测试金库

In this section, we will test our Vault setup using two of its supported secret types: Key/Value and Database. We will also show how to create new tokens with specific policies attached to them.

在本节中,我们将使用其支持的两种秘密类型来测试我们的Vault设置。密钥/值和数据库。我们还将展示如何创建带有特定策略的新令牌。

6.1. Using Key/Value Secrets

6.1.使用键/值秘诀

First, let’s store secret Key-Value pairs and read them back. Assuming the command shell used to initialize Vault is still open, we use the following command to store those pairs under the secret/fakebank path:

首先,让我们存储秘密的Key-Value对并将其读回。假设用于初始化Vault的命令外壳仍然是开放的,我们使用下面的命令将这些对存储在secret/fakebank路径下。

$ vault kv put secret/fakebank api_key=abc1234 api_secret=1a2b3c4d

We can now recover those pairs at any time with the following command:

现在我们可以在任何时候用以下命令恢复这些配对。

$ vault kv get secret/fakebank
======= Data =======
Key           Value
---           -----
api_key       abc1234
api_secret    1a2b3c4d

This simple test shows us that Vault is working as it should. We can now test some additional functionalities.

这个简单的测试告诉我们,Vault正在正常工作。我们现在可以测试一些额外的功能。

6.2. Creating New Tokens

6.2.创建新令牌

So far we have used the root token in order to authenticate our requests. Since a root token is way too powerful, it is considered a best practice to use tokens with fewer privileges and shorter time-to-live.

到目前为止,我们已经使用了根令牌,以验证我们的请求。由于根令牌的功能过于强大,因此使用权限较少、存活时间较短的令牌被认为是最佳做法。

Let’s create a new token that we can use just like the root token, but expires after just a minute:

让我们创建一个新的令牌,我们可以像根令牌一样使用,但只在一分钟后过期。

$ vault token create -ttl 1m
Key                  Value
---                  -----
token                <token value>
token_accessor       <token accessor value>
token_duration       1m
token_renewable      true
token_policies       ["root"]
identity_policies    []
policies             ["root"]

Let’s test this token, using it to read the key/value pairs that we’ve created before:

让我们测试一下这个令牌,用它来读取我们之前创建的键/值对。

$ export VAULT_TOKEN=<token value>
$ vault kv get secret/fakebank
======= Data =======
Key           Value
---           -----
api_key       abc1234
api_secret    1a2b3c4d

If we wait a minute and try to reissue this command, we get an error message:

如果我们等待一分钟,并试图重新发出这个命令,我们会得到一个错误信息。

$ vault kv get secret/fakebank
Error making API request.

URL: GET https://localhost:8200/v1/sys/internal/ui/mounts/secret/fakebank
Code: 403. Errors:

* permission denied

The message indicates that our token is no longer valid, which is what we’ve expected.

该信息表明我们的令牌不再有效,这正是我们所期望的。

6.3. Testing Policies

6.3.测试政策

The sample token we’ve created in the previous section was shorted lived, but still very powerful. Let’s now use policies to create more restricted tokens.

我们在上一节中创建的样本令牌是短命的,但仍然非常强大。现在让我们使用策略来创建更多的限制性令牌。

For instance, let’s define a policy that allows only read access to the secret/fakebank path we used before:

例如,让我们定义一个策略,只允许对我们之前使用的secret/fakebank路径的读取访问。

$ cat > sample-policy.hcl <<EOF
path "secret/fakebank" {
    capabilities = ["read"]
}
EOF
$ export VAULT_TOKEN=<root token>
$ vault policy write fakebank-ro ./sample-policy.hcl
Success! Uploaded policy: fakebank-ro

Now we create a token with this policy with the following command:

现在我们用下面的命令为这个策略创建一个令牌。

$ export VAULT_TOKEN=<root token>
$ vault token create -policy=fakebank-ro
Key                  Value
---                  -----
token                <token value>
token_accessor       <token accessor value>
token_duration       768h
token_renewable      true
token_policies       ["default" "fakebank-ro"]
identity_policies    []
policies             ["default" "fakebank-ro"]

As we’ve done before, let’s read our secret values using this token:

正如我们之前所做的,让我们使用这个令牌来读取我们的秘密值。

$ export VAULT_TOKEN=<token value>
$ vault kv get secret/fakebank
======= Data =======
Key           Value
---           -----
api_key       abc1234
api_secret    1a2b3c4d

So far, so good. We can read data, as expected. Let’s see what happens when we try to update this secret:

到目前为止,情况良好。我们可以读取数据,正如预期的那样。让我们看看当我们试图更新这个秘密时会发生什么。

$ vault kv put secret/fakebank api_key=foo api_secret=bar
Error writing data to secret/fakebank: Error making API request.

URL: PUT https://127.0.0.1:8200/v1/secret/fakebank
Code: 403. Errors:

* permission denied

Since our policy does not explicitly allows writes, Vault returns a 403 – Access Denied status code.

由于我们的政策没有明确允许写入,Vault返回一个403 – 拒绝访问的状态代码。

6.4. Using Dynamic Database Credentials

6.4.使用动态数据库凭证

As our final example in this article, let’s use Vault’s Database secret engine in order to create dynamic credentials. We assume here that we have a MySQL server available locally and that we can access it with “root” privileges. We will also use a very simple schema consisting of a single table – account .

作为本文的最后一个例子,让我们使用Vault的数据库秘密引擎,以创建动态凭证。在这里我们假设我们有一个本地可用的MySQL服务器,并且我们可以用 “root “权限访问它。我们还将使用一个非常简单的模式,包括一个单一的表 – account

The SQL script used to create this schema and the privileged user is available here.

用来创建这个模式和特权用户的SQL脚本在这里可以找到。

Now, let’s configure Vault to use this database. The database secret engine is not enabled by default, so we must fix this before we can proceed:

现在,让我们来配置Vault以使用这个数据库。数据库的秘密引擎在默认情况下没有启用,所以我们必须在继续之前解决这个问题。

$ vault secrets enable database
Success! Enabled the database secrets engine at: database/

We now create a database configuration resource :

我们现在创建一个数据库配置资源。

$ vault write database/config/mysql-fakebank \
  plugin_name=mysql-legacy-database-plugin \
  connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/fakebank" \
  allowed_roles="*" \
  username="fakebank-admin" \
  password="Sup&rSecre7!"

The path prefix database/config is where all database configurations must be stored.  We choose the name mysql-fakebank so we can easily figure out to which database this configuration refers to. As for the configuration keys:

路径前缀database/config是所有数据库配置必须存储的地方。 我们选择了mysql-fakebank这个名字,这样我们就可以很容易地知道这个配置指的是哪个数据库。至于配置的键。

  • plugin_name: Defines which database plugin will be used. The available plugin names are described in Vault’s docs
  • connection_url: This is a template used by the plugin when connecting to the database. Notice the {{username}} and {{password}} template placeholders. When connecting to the database, Vault will replace those placeholders by actual values
  • allowed_roles: Define which Vault roles (discussed next) can use this configuration. In our case we use “*”, so its available to all roles
  • username & password: This is the account that Vault will use to perform database operations, such as creating a new user and revoking its privileges

Vault Database Role Setup

金库数据库角色设置

The final configuration task is to create a Vault database role resource that contains the SQL commands required to create a user. We can create as many roles as needed, according to our security requirements.

最后的配置任务是创建一个Vault数据库角色资源,其中包含创建用户所需的SQL命令。我们可以根据我们的安全要求,根据需要创建尽可能多的角色。

Here, we create a role that grants read-only access to all tables of the fakebank schema:

在这里,我们创建一个角色,授予对fakebank模式的所有表的只读权限。

$ vault write database/roles/fakebank-accounts-ro \
    db_name=mysql-fakebank \
    creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON fakebank.* TO '{{name}}'@'%';"

The database engine defines the path prefix database/roles as the location to store roles. fakebank-accounts-ro is the role name that we’ll later use when creating dynamic credentials. We also supply the following keys:

数据库引擎定义了路径前缀数据库/roles作为存储角色的位置。fakebank-accounts-ro是我们以后在创建动态凭证时使用的角色名称。我们还提供了以下键。

  • db_name: Name of an existing database configuration. Corresponds to the last part of the path we used when creating the configuration resource
  • creation_statements: A list of SQL statement templates that Vault will use to create a new user

Creating Dynamic Credentials

创建动态证书

Once we have a database role and its corresponding configuration ready, we generate new dynamic credentials with the following command:

一旦我们准备好了数据库角色及其相应的配置,我们就用下面的命令生成新的动态凭证。

$ vault read database/creds/fakebank-accounts-ro
Key                Value
---                -----
lease_id           database/creds/fakebank-accounts-ro/0c0a8bef-761a-2ef2-2fed-4ee4a4a076e4
lease_duration     1h
lease_renewable    true
password           <password>
username           <username>

The database/creds prefix is used to generate credentials for the available roles. Since we have used the fakebank-accounts-ro role, the returned username/password will be restricted to select operations.

database/creds前缀用于生成可用角色的凭证。由于我们使用了fakebank-accounts-ro 角色,返回的用户名/密码将被限制在select操作。

We can verify this by connecting to the database using the supplied credentials and then performing some SQL commands:

我们可以通过使用提供的凭证连接到数据库,然后执行一些SQL命令来验证这一点。

$ mysql -h 127.0.0.1 -u <username> -p fakebank
Enter password:
MySQL [fakebank]> select * from account;
... omitted for brevity
2 rows in set (0.00 sec)
MySQL [fakebank]> delete from account;
ERROR 1142 (42000): DELETE command denied to user 'v-fake-9xoSKPkj1'@'localhost' for table 'account'

We can see that the first select completed successfully, but we could not perform the delete statement. Finally, if we wait for one hour and try to connect using those same credentials, we will not be able to connect anymore to the database. Vault has automatically revoked all privileges from this user

我们可以看到,第一个选择成功完成,但是我们无法执行删除语句。最后,如果我们等待一个小时并尝试使用这些相同的凭证进行连接,我们将无法再连接到数据库。Vault已经自动撤销了这个用户的所有权限

7. Conclusion

7.结语

In this article have explored the basics of Hashicorp’s Vault, including some background on the problem it tries to address, its architecture and basic use.

在这篇文章中,我们探讨了Hashicorp的Vault的基本情况,包括它试图解决的问题的一些背景,它的架构和基本用途。

Along the way, we have created a simple but functional test environment that we´ll use in follow-up articles.

在这一过程中,我们已经创建了一个简单但实用的测试环境,我们将在后续文章中使用。

The next article will cover a very specific use case for Vault: Using it in the context of Spring Boot application. Stay tuned!

下一篇文章将介绍Vault的一个非常具体的用例。在Spring Boot应用程序的背景下使用它。敬请关注!