Sägetstrasse 18, 3123 Belp, Switzerland +41 79 173 36 84 info@ict.technology

    HashiCorp Vault 深入解析 - 第 1 部分:Secrets Engines 基础

    Secrets Engines 是 Vault 的核心组件 —— 它们使我们可以将安全性不仅仅视为一个存储问题,而是一个过程问题。无论是数据库密码、SSH 访问还是 JWT 签名:一切都可以以动态、安全且可追踪的方式进行管理 —— 前提是您了解正确的 Engines,并正确地加以使用。关键不在于种类的繁多,而在于理解与设计。想要在生产环境中有效使用 Vault,就必须深入理解 Secrets Engines。

    本文将深入概述 Secrets Engines 的功能、应用场景和生命周期 —— 从如 KVTransitPKI 等通用 Engines,到面向 CloudDatenbankplattformen 的专用模块。

     

    什么是 Secrets Engines?

    Secrets Engines 是 Vault 中的专用组件,用于存储、生成、加密机密数据,或代表用户执行操作。可以将 Secrets Engine 想象为一种“可插拔服务”,它通过 Vault 中的专用路径进行启用,并根据类型执行不同的任务。

    某些 Secrets Engines 主要作为安全存储使用 —— 可比作加密版本的 RedisMemcached。而其他则与外部系统交互,动态生成访问凭据,例如用于 AWS IAMOracle 数据库或 SSH 访问的凭据。还有一些则提供加密服务,如 Encryption as a ServiceTOTPQR-Code 生成,或用于签发证书。

    从技术角度看,每个 Secrets Engine 类似于一个虚拟文件系统,用户通过 readwritedelete 等操作与之交互。发送到 Vault 的请求会自动路由到挂载了对应 Engine 的路径。每个 Engine 会定义自己的一组路径和功能。

    Secrets Engines 类型:Vault 生态系统概览

    Vault 提供种类丰富的 Secrets Engines,大致可分为两类:

    专用型 Secrets Engines

    这些 Engines 面向特定平台和服务,通常需要对目标平台具备深入的专业知识:

    • Cloud:AWS、Azure、Google Cloud、AliCloud
    • 数据库:Cassandra、Couchbase、ElasticSearch、HANA、IBM DB2、Influx DB、MongoDB、MongoDB Atlas、MSSQL、MariaDB、MySQL、Oracle Database、PostgreSQL、Redis、Redis Elasticache、Redshift、Snowflake
    • 身份服务:Kerberos、LDAP、各类云服务(包括 OCI)、RADIUS、SAML、JWT/OIDC、Okta、Github、CloudFoundry 等
    • 基础设施工具:Consul、Nomad、Terraform Cloud
    • 消息系统:RabbitMQ
    • 其他:Venafi、SSH、TOTP、Transform、多种外部 KMS 等

    需要注意的是:Vault 工程师不可能是每个平台的专家。正确配置这些 Engines 通常需要与相应平台的领域专家密切协作。

    通用型 Secrets Engines

    这些 Engines 属于标准组件,所有 Vault 用户都应熟悉:

    • Cubbyhole:临时性、与令牌绑定的数据存储。适用于仅保存在内存中、重启后会丢失或应被丢弃的私密和易失性 Secrets。
    • Key/Value (KV):最常见的 Engine,用于定义 Key 及其关联的 Value,例如用户名和密码。KV v2 支持版本控制,而 KV v1 已被视为过时。
    • Database:通过插件支持 13 种以上的平台,可自动创建和吊销数据库凭据。
    • Transit:提供无存储的加密服务。适用于本地处理敏感数据、但需要集中密钥管理的应用场景。
    • PKI:创建和管理 X.509 证书 —— 是构建内部 CA 方案的必备组件。
    • Identity:支持身份映射、别名管理和策略分配。

    考试相关的 Secrets Engines

    在 Vault Associate 与 Vault Operations Professional 认证考试中,您应熟练掌握以下 Secrets Engines:

    • Cubbyhole
    • KV
    • Identity
    • PKI
    • Database
    • Transit

    我们将在后续的独立文章中对这些 Engines 进行详细讲解。

     

    Secrets Engines 的生命周期


    每个 Secrets Engine 通常都会经历以下生命周期:

    1. 被启用,
    2. 被配置,
    3. 被使用,
    4. 被定期调优(“tuned”),以及
    5. 在多数使用场景下,最终被停用。

    尤其是那些动态生成的 Secrets Engines(如用于自动创建的数据库、云账户或租户)不仅需要启用,还必须定期进行调整(调优),并在相关基础设施组件移除时及时停用。这不仅是清理工作,更是确保数据质量与合规性(如数据保护要求)的重要措施。因此,对每一个操作的可审计性是 Vault 安全架构中的核心要素。

    Secrets Engines 的启用与隔离

    要使用某个 Secrets Engine,必须首先将其启用 —— 可通过 CLIAPIUI 完成。

    Secrets Engines 必须由用户主动启用(CubbyholeIdentity 除外,它们默认启用)。启用时需选择一个唯一的、可自定义的路径,作为 mount point 使用。Vault 在此过程中执行以下原则:

    • 区分大小写的路径kv/KV/ 是不同的挂载点
    • 避免命名冲突:存在 foo/ 挂载点时不能启用 foo/bar/
    • 每个 Engine 是隔离的:仅能访问自身的数据空间

    作为工程师或终端用户,以下特性务必牢记 —— 它们也是认证考试中常见的考点:

    • 默认启用CubbyholeIdentity 两个 Engine 是系统预设启用,无法停用。
    • 手动启用:所有其他 Engines 都需要显式启用。
    • 启用方式:可通过命令行(CLI)、API 或图形界面(UI)进行启用。
    • 通过路径进行交互:与 Secrets Engine 的所有交互均通过其挂载路径进行。
    • 隔离路径:每个启用的 Engine 与系统其他部分在逻辑和物理上都是隔离的。若启用租户功能,即使挂载路径相同,各个租户的 Engine 也彼此隔离。
    • 路径命名灵活:路径名称不必与 Secrets Engine 的名称或类型一致。
    • 区分大小写:路径对大小写敏感,kv/ 与 KV/ 属于两个不同的 Engine。

    在后台,每个被启用的 Engine 会在 Vault 的存储层中分配一个随机生成的基于 UUID 的路径。该存储路径类似于 chroot。这种“Barrier View” 模型确保每个 Engine 仅能访问自身的数据。即便某个 Engine 被攻破,也无法访问同一命名空间(租户)中的其他 Secrets Engines。

    专家提示:建议为 Secrets Engines 制定一套组织内部统一且一致的命名规范。若使用命名空间,强制性的命名规范可有效降低整体系统的复杂度、运维风险和操作成本。

    通过命令行启用

    命令 vault secrets 是通过 CLI 管理 Secrets Engines 的主要入口。常用子命令包括:

    • disable:禁用 Secrets Engine
    • enable:启用新的 Secrets Engine
    • list:列出所有已启用的 Secrets Engines
    • move:更改 Secrets Engine 的挂载路径
    • tune:配置 Secrets Engine 的参数

    示例

    1. 在默认路径上启用 KV(Key/Value)Secrets Engine
    [rramge@ol9 ~]$ vault secrets enable kv
    Success! Enabled the kv secrets engine at: kv/
    [rramge@ol9 ~]$ 

    验证:

    [rramge@ol9 ~]$ vault secrets list
    Path          Type         Accessor              Description
    ----          ----         --------              -----------
    cubbyhole/    cubbyhole    cubbyhole_fe623ade    per-token private secret storage
    identity/     identity     identity_cd5a6252     identity store
    kv/           kv           kv_62ea76c1           n/a
    sys/          system       system_b247c51c       system endpoints used for control, policy and debugging
    [rramge@ol9 ~]$ 

    如您所见,除了 KV Secrets Engine 外,系统还列出了 Cubbyhole 和 Identity Engines,它们始终存在。System Engine 并不用于存储数据,而用于 Vault 的控制、策略和调试 —— 我们将在后续文章中视需要展开。

    2. 在自定义路径上启用 KV(Key/Value)Secrets Engine:

    在此示例中,还传入了参数 --path=<mount-point>

    [rramge@ol9 ~]$ vault secrets enable -path=mykv kv
    Success! Enabled the kv secrets engine at: mykv/
    [rramge@ol9 ~]$ 
    

    验证:

    [rramge@ol9 ~]$ vault secrets list
    Path          Type         Accessor              Description
    ----          ----         --------              -----------
    cubbyhole/    cubbyhole    cubbyhole_fe623ade    per-token private secret storage
    identity/     identity     identity_cd5a6252     identity store
    kv/           kv           kv_62ea76c1           n/a
    mykv/         kv           kv_5fa9f096           n/a
    sys/          system       system_b247c51c       system endpoints used for control, policy and debugging
    [rramge@ol9 ~]$ 
    3. 使用描述信息启用 KV(Key/Value)Secrets Engine

    您也可以传入 --description 参数:

    [rramge@ol9 ~]$ vault secrets enable -path=mykv --description="My K/V Secret Store" kv 
    Success! Enabled the kv secrets engine at: mykv/
    [rramge@ol9 ~]$ 

    最终效果如下:

    [rramge@ol9 ~]$ vault secrets list
    Path          Type         Accessor              Description
    ----          ----         --------              -----------
    cubbyhole/    cubbyhole    cubbyhole_fe623ade    per-token private secret storage
    identity/     identity     identity_cd5a6252     identity store
    kv/           kv           kv_62ea76c1           n/a
    mykv/         kv           kv_645ae3a2           My K/V Secret Store
    sys/          system       system_b247c51c       system endpoints used for control, policy and debugging
    [rramge@ol9 ~]$ 
    4. 停用 Secrets Engine

    我们现在将 kv/ 和 mykv/ 这两个 Secrets Engines 移除:

    [rramge@ol9 ~]$ vault secrets disable mykv
    Success! Disabled the secrets engine (if it existed) at: mykv/
    [rramge@ol9 ~]$ vault secrets disable kv
    Success! Disabled the secrets engine (if it existed) at: kv/
    [rramge@ol9 ~]$ 

    注意:如果您禁用了一个已有数据的 Secrets Engine,可能会造成数据丢失!停用 Secrets Engine 会删除所有相关数据 —— 在处理像 KVPKI 等持久性 Engine 时,务必提前做好备份。

    通过 Terraform 的 API 启用

    除了 CLI,也可通过 Terraform 以声明式方式管理 Secrets Engine。您可以在此处找到用于管理 Secrets Engines 及其属性的 Terraform 模块:https://github.com/ICT-technology/terraform-vault-mount/

    该模块支持在一次模块调用中动态创建和管理多个 Secrets Engines,能够主动捕捉 API 错误,实施最佳实践,并支持使用 terraform test 的自动化测试流水线。

    使用示例

    您可以在 examples/ 子目录中找到一个可直接运行的示例。请正确设置您的环境变量 $VAULT_ADDR$VAULT_TOKEN,之后便可直接在该目录中执行该示例 —— 但请确保您是在私有开发环境中运行,而非生产环境。

    该模块将创建以下 Secrets Engines:

    • kv-v2
    • pki
    • kubernetes
    • ldap
    • transit
    • aws

    成功执行 terraform apply 后,该模块将输出已创建 Secrets Engines 的 mount-accessors 列表。这些 mount-accessors 可用于在其他 Terraform 资源的配置中作为引用,也适用于审计、动态策略分配等场景。

    examples/main.tf:

    ### BEGIN FILE: examples/main.tf ###
    
    module "vault\_mounts" {
    source = "git::[https://github.com/ICT-technology/terraform-vault-mount.git?ref=v2025.1.3](https://github.com/ICT-technology/terraform-vault-mount.git?ref=v2025.1.3)"
    
    mounts = {
    kvv2 = {
    path        = "kv-v2"
    type        = "kv-v2"
    description = "Key-Value Version 2 Secrets Engine"
    options     = { version = "2" }
    }
    
    ```
    pki = {
      path                      = "pki"
      type                      = "pki"
      description               = "PKI Secrets Engine"
      default_lease_ttl_seconds = 3600
      max_lease_ttl_seconds     = 86400
    }
    
    kubernetes = {
      path        = "kubernetes"
      type        = "kubernetes"
      description = "Kubernetes Auth Engine"
    }
    
    ldap = {
      path        = "ldap"
      type        = "ldap"
      description = "LDAP Auth Engine"
      options     = { case_sensitive_names = "true" }
    }
    
    transit = {
      path        = "transit"
      type        = "transit"
      description = "Transit Secrets Engine for Encryption-as-a-Service"
      options = {
        convergent_encryption = false
      }
    }
    
    aws = {
      path        = "aws"
      type        = "aws"
      description = "AWS Secrets Engine"
    }
    ```
    
    }
    }
    
    ### END FILE: examples/main.tf ###

    examples/outputs.tf:

    ### BEGIN FILE: examples/outputs.tf ###
    
    output "mount\_accessors" {
    description = "Accessors for the configured Vault mounts"
    value       = module.vault\_mounts.mount\_accessor
    }
    
    ### END FILE: examples/outputs.tf ###

    在实际操作中,对该示例执行 terraform apply 会如下所示:

    [rramge@ol9 examples]$ terraform apply
    [...]
    Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes module.vault\_mounts.vault\_mount.this\["aws"]: Creating... module.vault\_mounts.vault\_mount.this\["transit"]: Creating... module.vault\_mounts.vault\_mount.this\["kvv2"]: Creating... module.vault\_mounts.vault\_mount.this\["ldap"]: Creating... module.vault\_mounts.vault\_mount.this\["kubernetes"]: Creating... module.vault\_mounts.vault\_mount.this\["pki"]: Creating... module.vault\_mounts.vault\_mount.this\["aws"]: Creation complete after 1s \[id=aws] module.vault\_mounts.vault\_mount.this\["pki"]: Creation complete after 1s \[id=pki] module.vault\_mounts.vault\_mount.this\["transit"]: Creation complete after 1s \[id=transit] module.vault\_mounts.vault\_mount.this\["kvv2"]: Creation complete after 1s \[id=kv-v2] module.vault\_mounts.vault\_mount.this\["kubernetes"]: Creation complete after 1s \[id=kubernetes] module.vault\_mounts.vault\_mount.this\["ldap"]: Creation complete after 1s \[id=ldap] Apply complete! Resources: 6 added, 0 changed, 0 destroyed. Outputs: mount\_accessors = { "aws" = "aws\_e2982916" "kubernetes" = "kubernetes\_6671be50" "kvv2" = "kv\_26a6e11a" "ldap" = "ldap\_8fbb6083" "pki" = "pki\_2d96cba8" "transit" = "transit\_25465e3f" } \[rramge\@ol9 examples]\$

    通过 Web 界面启用

    Secrets Engines 也可以通过 Web 界面启用。Vault 提供一个可选启用的 Web UI,但它设计非常简洁,更适合作为营销演示的展示界面,而非在大型生产环境中进行日常管理。

    在此不打算详细介绍基于 Web 的启用方式 —— 作为一名技术娴熟、经验丰富的读者,您应已认识到在安全关键环境中,复现性配置步骤和自动化的重要性,而非依赖鼠标点击。建议您深入学习 CLI 命令,并理解 Infrastructure-as-Code 的价值,这对实践操作和认证考试准备都至关重要。

    展望

    在下一篇关于 HashiCorp Vault 的深度文章中,我们将初步探讨 Key/Value Secrets Engine,随后再深入展开详细内容。