甲方中的KMS密钥管理以及vault的使用笔记(上) 2024-09-30 11:33:27 Steven Xeldax > 本篇为《甲方中的KMS密钥管理以及vault的使用笔记(上)》,下半部分地址:https://xeldax.top/article/kms_with_vault_note_part2 [TOC] ## 密钥管理现状 对于一个应用都可能会涉及到和数据库进行通信或者和其他API 进行访问,应用开发的过程当中就会涉及到我的应用配置如何存放,API密钥,AK、SK各种票据如何使用和存放? 通常往往会遇到这几种情况: 1. 硬编码在代码里 2. 硬编码在Docker镜像里,然后存放到register仓库中(例如harbor) 3. 代码和镜像里都没,硬编码在Dockerfile中 4. 密钥配置通过apollo和nacos管理,应用发版的时候通过CICD在启动的时候通过注入到env环境变量中 5. 密钥配置通过apollo和nacos管理,应用发版的时候通过CICD流程发布一个config配置文件 第一种和第二种就是安全中最为常见的硬编码安全问题,只要代码拿到或者harbor镜像配置的匿名可读就能导致配置密钥的泄露。对于通过dockerfile同样如此,red team可喜欢通过代码仓库或者镜像反编译拿密钥。 相比前三种情况在启动的时候注入到环境变量中和应用发版的时候通过CICD流程发布一个配置文件这两种方式相对更安全一些,因为它们可以减少密钥直接暴露在代码或镜像中的风险,同时能够在一定程度上控制密钥的访问和传输过程中的安全性。 其实不难发现生产环境对于密钥和配置的管理有个比较通用的准则: 1.运行时密钥加载安全性大于运行前落地集成,配置和密钥的加载在应用运行时越晚加载安全程度会比在运行前的安全性高,对于运行时的攻击面需要攻击者在内存中寻找我们的密钥。 2.统一管理比碎片化管理要安全,各个业务owner自己管理自己的密钥容易造成泄露问题,集中化管理不单单利于防泄漏同样利于密钥生命周期管理。 ## 统一配置管理和统一密钥管理 虽然运行时注入密钥是一个比较安全的做法,但对于第四和第五种情况仍然还没达到最优实践,apollo和nacos是两种常用的配置中心,用于集中管理应用程序的配置信息,但对于密钥管理而言使用KMS 密钥管理系统是更安全的做法。相比而言KMS专门设计用于安全存储和管理密钥、凭证等敏感信息的服务,提供了更严格的安全控制和加密功能,此外KMS通常支持密钥轮换、密钥版本管理等功能,有助于提高密钥的安全性并符合安全最佳实践。 统一配置管理和统一密钥管理是两个在企业信息技术管理中常见的概念,它们区别如下: 1. **统一配置管理**: - **定义**:统一配置管理是指将应用程序、系统和服务中的配置信息集中管理和统一化的过程。这些配置信息可以包括数据库连接字符串、API密钥、日志级别、应用程序行为等。 - **目的**:统一配置管理的目的是简化配置管理流程、提高配置信息的可维护性和可管理性,减少配置错误和提高系统的稳定性。 - **实现方式**:通常通过配置中心(如Nacos、Apollo等)或配置管理工具(如Ansible、Chef等)来实现统一配置管理。 2. **统一密钥管理**: - **定义**:统一密钥管理是指将企业中使用的各种密钥(如加密密钥、数字证书、API密钥等)集中管理和安全保护的过程。 - **目的**:统一密钥管理的目的是确保敏感信息的安全性,防止密钥泄露、滥用和未经授权的访问。 - **实现方式**:通常通过密钥管理服务(如KMS、Key Vault等)来实现统一密钥管理,这些服务提供了安全的密钥存储、加密和访问控制功能。 主要区别在于统一配置管理主要关注配置信息的管理和维护,而统一密钥管理则专注于敏感信息(如密钥、凭证)的安全管理和保护。对于apollo和nacos而言侧重于统一配置管理,而对于KMS而言侧重于统一密钥管理。 ## KMS介绍 ``` 密钥管理系统(Key Management Service,KMS)是一款安全管理类服务,可以让您轻松创建和管理密钥,保护密钥的保密性、完整性和可用性,满足用户多应用多业务的密钥管理需求,符合监管和合规要求。 ``` KMS的意义主要在于: 简化密码管理:KMS可以集中管理密码和密钥,使得密码管理更加简单和高效。通过KMS,您可以在一个地方管理和存储所有的密码,而无需在多个系统中分散存储和管理密码。 自动化密码轮换:KMS通常提供自动化密码轮换功能,可以定期更改密码,减少人工干预,提高密码安全性。这有助于防止密码被长时间滥用或泄露。 灵活的集成选项:KMS通常提供与各种应用程序和服务的集成选项,可以轻松地将KMS与现有系统集成,实现对密码和密钥的统一管理和保护。 遵守法规和标准:许多行业标准和法规要求对密码和密钥进行严格的管理和保护。通过使用KMS,您可以更容易地符合这些法规和标准,降低合规风险。 减少人为错误:通过KMS,可以减少人为错误导致的密码泄露或丢失。KMS的自动化和严格的访问控制可以降低人为因素对系统安全性的影响。 ## 参考资料 https://m.freebuf.com/articles/es/229311.html https://pandaychen.github.io/2021/07/10/A-KMS-STUDY/ https://www.secrss.com/articles/8141 https://www.cnblogs.com/sealio/p/16664999.html https://blog.fleeto.us/post/secret-to-vault-k8s/ [TOC] ## 密钥管理现状 对于一个应用都可能会涉及到和数据库进行通信或者和其他API 进行访问,应用开发的过程当中就会涉及到我的应用配置如何存放,API密钥,AK、SK各种票据如何使用和存放? 通常往往会遇到这几种情况: 1. 硬编码在代码里 2. 硬编码在Docker镜像里,然后存放到register仓库中(例如harbor) 3. 代码和镜像里都没,硬编码在Dockerfile中 4. 密钥配置通过apollo和nacos管理,应用发版的时候通过CICD在启动的时候通过注入到env环境变量中 5. 密钥配置通过apollo和nacos管理,应用发版的时候通过CICD流程发布一个config配置文件 第一种和第二种就是安全中最为常见的硬编码安全问题,只要代码拿到或者harbor镜像配置的匿名可读就能导致配置密钥的泄露。对于通过dockerfile同样如此,red team可喜欢通过代码仓库或者镜像反编译拿密钥。 相比前三种情况在启动的时候注入到环境变量中和应用发版的时候通过CICD流程发布一个配置文件这两种方式相对更安全一些,因为它们可以减少密钥直接暴露在代码或镜像中的风险,同时能够在一定程度上控制密钥的访问和传输过程中的安全性。 其实不难发现生产环境对于密钥和配置的管理有个比较通用的准则: 1.运行时密钥加载安全性大于运行前落地集成,配置和密钥的加载在应用运行时越晚加载安全程度会比在运行前的安全性高,对于运行时的攻击面需要攻击者在内存中寻找我们的密钥。 2.统一管理比碎片化管理要安全,各个业务owner自己管理自己的密钥容易造成泄露问题,集中化管理不单单利于防泄漏同样利于密钥生命周期管理。 ## 统一配置管理和统一密钥管理 虽然运行时注入密钥是一个比较安全的做法,但对于第四和第五种情况仍然还没达到最优实践,apollo和nacos是两种常用的配置中心,用于集中管理应用程序的配置信息,但对于密钥管理而言使用KMS 密钥管理系统是更安全的做法。相比而言KMS专门设计用于安全存储和管理密钥、凭证等敏感信息的服务,提供了更严格的安全控制和加密功能,此外KMS通常支持密钥轮换、密钥版本管理等功能,有助于提高密钥的安全性并符合安全最佳实践。 统一配置管理和统一密钥管理是两个在企业信息技术管理中常见的概念,它们区别如下: 1. **统一配置管理**: - **定义**:统一配置管理是指将应用程序、系统和服务中的配置信息集中管理和统一化的过程。这些配置信息可以包括数据库连接字符串、API密钥、日志级别、应用程序行为等。 - **目的**:统一配置管理的目的是简化配置管理流程、提高配置信息的可维护性和可管理性,减少配置错误和提高系统的稳定性。 - **实现方式**:通常通过配置中心(如Nacos、Apollo等)或配置管理工具(如Ansible、Chef等)来实现统一配置管理。 2. **统一密钥管理**: - **定义**:统一密钥管理是指将企业中使用的各种密钥(如加密密钥、数字证书、API密钥等)集中管理和安全保护的过程。 - **目的**:统一密钥管理的目的是确保敏感信息的安全性,防止密钥泄露、滥用和未经授权的访问。 - **实现方式**:通常通过密钥管理服务(如KMS、Key Vault等)来实现统一密钥管理,这些服务提供了安全的密钥存储、加密和访问控制功能。 主要区别在于统一配置管理主要关注配置信息的管理和维护,而统一密钥管理则专注于敏感信息(如密钥、凭证)的安全管理和保护。对于apollo和nacos而言侧重于统一配置管理,而对于KMS而言侧重于统一密钥管理。 ## KMS介绍 ``` 密钥管理系统(Key Management Service,KMS)是一款安全管理类服务,可以让您轻松创建和管理密钥,保护密钥的保密性、完整性和可用性,满足用户多应用多业务的密钥管理需求,符合监管和合规要求。 ``` KMS的意义主要在于: 简化密码管理:KMS可以集中管理密码和密钥,使得密码管理更加简单和高效。通过KMS,您可以在一个地方管理和存储所有的密码,而无需在多个系统中分散存储和管理密码。 自动化密码轮换:KMS通常提供自动化密码轮换功能,可以定期更改密码,减少人工干预,提高密码安全性。这有助于防止密码被长时间滥用或泄露。 灵活的集成选项:KMS通常提供与各种应用程序和服务的集成选项,可以轻松地将KMS与现有系统集成,实现对密码和密钥的统一管理和保护。 遵守法规和标准:许多行业标准和法规要求对密码和密钥进行严格的管理和保护。通过使用KMS,您可以更容易地符合这些法规和标准,降低合规风险。 减少人为错误:通过KMS,可以减少人为错误导致的密码泄露或丢失。KMS的自动化和严格的访问控制可以降低人为因素对系统安全性的影响。 kms有很多种,首先使用的云而言每个云厂商都有各自的KMS的安全产品,本文选择了开源中个人认为好用的vault来作为KMS的选型使用。常见的KMS有: | 厂商 | 产品 | | ------------ | ------------ | | aliyun | 阿里云密钥管理服务(Key Management Service,KMS)https://cn.aliyun.com/product/kms?from_alibabacloud= | | huawei cloud |数据加密服务 DEW https://www.huaweicloud.com/theme/481660-1-M | | azure | azure key vault https://azure.microsoft.com/en-us/products/key-vault | | GCP | cloud key management https://cloud.google.com/security/products/security-key-management?hl=zh_cn | | AWS | AWS Key Management Service(KMS)https://aws.amazon.com/kms/ | | hashicorp 开源 | vault https://developer.hashicorp.com/vault/docs/what-is-vault | ## KMS 使用:vault ### vault 安全模型 以下摘自官方文档: ``` 由于 Vault 的性质及其管理的数据的机密性,Vault 的安全模型非常关键。 Vault 安全模型的总体目标是提供机密性、完整性、可用性、问责制和身份验证。 这意味着数据在传输中以及落盘后都必须是安全的,不会被窃听或篡改。客户端必须经过适当的身份验证和授权才能访问数据或修改策略。所有交互都必须是可审计的,并且可以唯一地追溯到原始实体。系统必须能够抵御故意绕过其访问控制的任何尝试。 威胁模型 以下是 Vault 威胁模型的各个部分: 对 Vault 通信的窃听。客户端与 Vault 的通信,以及从 Vault 到其存储后端,或 Vault 集群节点之间的通信应该是安全的,不会被窃听。 篡改已存储的或传输中的数据。任何篡改都应该是可检测的,并导致 Vault 中止事务处理。 未经身份验证以及授权的数据访问或是系统控制。所有的请求都必须按照相关的安全策略进行。 对数据的访问或管理系统的行为无法审计。如果启用审计日志,所有的请求与响应都必须在客户端接收到任何机密材料之前被记录下来。 系统存储的机密的机密性。任何通过 Vault 保存在存储后端的数据都必须是安全的,不会被窃听。实际上,这意味着所有落盘数据都必须加密。 系统发生故障时机密材料的可用性。Vault 支持在高可用性配置中运行,以避免失去可用性。 以下部分不在 Vault 威胁模型范围内: 防止对存储后端的随意控制。可以对存储后端执行任意操作的攻击者可以通过多种难以或不可能防御的方式破坏安全性。例如,攻击者可以删除或破坏存储后端的所有内容,从而导致 Vault 的全部数据丢失。控制读取的能力将允许攻击者以众所周知的状态进行快照并回滚状态更改,如果这对他们有利的话。 防止机密材料的存在性的泄露。可以读取存储后端的攻击者可能会观察到机密材料的存在和存储,即使它是保密的。 防止对正在运行的 Vault 进行内存分析。如果攻击者能够检查正在运行的 Vault 实例的内存状态,那么数据的机密性可能会受到威胁。 防止 Vault 使用的外部系统或服务中的缺陷。一些身份验证方法或机密引擎将敏感操作委托给 Vault 外部的系统。如果攻击者可以破坏凭据或以其他方式利用这些外部系统中的漏洞,则数据的机密性或完整性可能会受到损害。 防止底层主机上的恶意插件或代码执行。如果攻击者可以获得对底层主机的代码执行或写入权限,那么数据的机密性或完整性可能会受到损害。 外部威胁综述 鉴于 Vault 的架构,我们关注 3 个不同的 Vault 系统。 客户端,它通过 API 与 Vault 对话 Vault 服务,它提供 API 和服务请求 存储后端,服务器利用它来读取和写入数据 Vault 客户端和服务器之间没有默认的相互信任。客户端使用 TLS 来验证服务器的身份并建立安全的通信通道。服务器要求客户端为用于识别客户端的每个请求提供客户端令牌。只允许没有令牌的客户端发出登录请求。 集群内 Vault 实例之间的所有服务器之间的流量(即高可用性、企业复制或集成存储)都使用相互验证的 TLS 来确保传输中数据的机密性和完整性。节点在加入集群之前通过解封质询或一次性激活令牌进行身份验证。 Vault 使用的存储后端在设计上也是不受信任的。 Vault 对向后端发出的所有请求使用安全屏障(Security Barrier)。安全屏障使用具有 96 位随机数的 Galois Counter Mode (GCM) 的 256 位高级加密标准 (AES) 密码自动加密离开 Vault 的所有数据。随机数是为每个加密对象随机生成的。当从安全屏障读取数据时,在解密过程中验证 GCM 身份验证标签以检测数据有无篡改。 使用某些后端时,Vault 可能会通过 TLS 与后端通信,以提供额外的安全层。在某些情况下,例如文件后端不需要这样做。由于存储后端是不可信的,即使与后端的通信被拦截,窃听者也只能访问加密数据。 内部威胁综述 在 Vault 系统中,一个关键的安全问题是攻击者试图访问他们无权访问的机密材料。如果攻击者已被允许对 Vault 进行某种级别的访问并且能够进行身份验证,则这是一种内部威胁。 当客户端首次通过 Vault 进行身份验证时,auth 身份验证方法用于验证客户端的身份并返回关联的 ACL 策略列表。该关联是由 Vault 的运维团队提前配置的。例如,"engineering" 团队中的 GitHub 用户可能会映射到 "engineering" 和 "ops" Vault 策略。然后 Vault 生成一个客户端令牌,它是一个随机生成的序列化值,并将其映射到策略列表,然后将此客户端令牌返回给客户端。 在每个请求中,客户端都会提供此令牌。然后 Vault 使用它来检查令牌是否有效并且没有被吊销或过期,并根据关联的策略生成 ACL。 Vault 使用严格的默认拒绝执行策略。这意味着除非相关策略允许给定操作,否则它将被拒绝。每个策略都指定了授予 Vault 中路径的访问级别。合并策略时(如果多个策略与客户端相关联),则使用允许的最高访问级别。例如,如果 "engineering" 策略允许对"eng/" 路径进行读或者更新操作,而 "ops" 策略允许对 "ops/" 路径进行读访问,则用户将获得这些路径的并集。使用最具体的定义策略匹配策略,可能是完全匹配或最长前缀匹配 glob 模式。有关详细信息,请参阅策略语法。 某些操作仅允许 "root" 用户操作,这是 Vault 中内置的一项杰出策略。这类似于 Unix 系统上的 root 用户或 Windows 上的管理员的概念。尽管可以为客户端提供根令牌或与根策略相关联,但 Vault 支持 "sudo" 特权的概念。作为策略的一部分,用户可能会被授予某些路径的 "sudo" 权限,这样他们仍然可以执行安全敏感操作,而无需被授予对 Vault 的全局 root 访问权限。 最后,Vault 支持通过 Shamir 算法支持双人规则解封。当 Vault 启动时,它以密封状态启动。这意味着 Vault 此时并不知晓从存储后端读取和写入所需的加密密钥。解封过程需要提供主密钥,以便可以获取加密密钥。分发主密钥的风险在于,有权访问它的单个恶意行为者可以解密整个 Vault。相反,Shamir 算法允许我们将主密钥拆分为多个分片或多个部分。分片的数量和所需的阈值是可配置的,但默认情况下,Vault 会生成 5 个分片,必须提供其中的任意 3 个才能重建主密钥。 通过使用机密分片算法,我们避免了对主密钥持有者的绝对信任,并完全避免存储主密钥。只能通过重建分片来检索主密钥。这些分片对向 Vault 提出任何请求没有用处,只能用于解封。解封后,标准 ACL 机制将用于所有请求。 打个比方,银行将保险箱放在保险库内。每个保险箱都有一把钥匙,而金库门既有密码也有钥匙。拱顶被钢和混凝土包裹着,所以门是唯一可以通行的入口。类似于 Vault,加密算法是保护数据的钢筋混凝土。虽然可以通过混凝土隧道或暴力破解加密密钥,但这将非常耗时。打开银行金库需要两个因素:钥匙和组合。同样,Vault 需要提供多个分片来重建主密钥。解封后,每个保险箱仍然需要所有者提供密钥,同样,Vault ACL 系统会保护所有存储的机密。 ``` ### vault 安装使用 由于vault是golang开发的推荐使用二进制的模式直接部署,方便替换并且大多数企业内网没有公网访问的情况下可以直接用。 https://developer.hashicorp.com/vault/docs/install/install-binary  https://developer.hashicorp.com/vault/install  ``` export VAULT_DATA=/opt/vault/data export VAULT_CONFIG=/etc/vault.d sudo mv PATH/TO/VAULT/BINARY /usr/bin/ sudo setcap cap_ipc_lock=+ep $(readlink -f $(which vault)) sudo mkdir -p ${VAULT_DATA} sudo mkdir -p ${VAULT_CONFIG} sudo useradd --system --home ${VAULT_DATA} --shell /sbin/nologin vault sudo chown vault:vault ${VAULT_DATA} sudo chmod -R 750 ${VAULT_DATA} sudo tee ${VAULT_CONFIG}/vault.hcl <<EOF ui = true cluster_addr = "http://172.17.0.1:8201" api_addr = "https://172.17.0.1:8200" disable_mlock = true storage "raft" { path = "${VAULT_DATA}" node_id = "172.17.0.1" } listener "tcp" { address = "172.17.0.1:8200" cluster_address = "172.17.0.1:8201" tls_disable = 1 } EOF sudo chown vault:vault "${VAULT_CONFIG}/vault.hcl" && \ sudo chmod 640 "${VAULT_CONFIG}/vault.hcl" vault -h # dev mode vault server -dev -config ${VAULT_CONFIG}/vault.hcl ``` ### vault 高可用部署 高可用部署可以参考如下文章: https://blog.csdn.net/qq_42844168/article/details/120025669 https://blog.csdn.net/WEARE001/article/details/131413961 https://developer.hashicorp.com/vault/tutorials/raft/raft-storage 生成证书 ``` # 创建 CA 私钥,生成一个新的私钥文件 ca.key openssl genrsa -out ca.key 4096 # 接下来,使用以下命令自签名生成 CA 证书 openssl req -new -x509 -days 36500 -key ca.key -out ca.crt -subj "/C=国家/ST=省份/L=城市/O=公司/OU=组织/CN=域名" openssl req -new -x509 -days 36500 -key ca.key -out ca.crt -subj "/CN= " # 效验 CA 证书 openssl x509 -noout -text -in ca.crt # 创建 Server 私钥,生成一个新的私钥文件 serverkey.pem openssl genrsa -out server.key 2048 # 创建服务器证书请求,使用以下命令生成服务器证书请求 openssl req -new -key server.key -out server.csr -subj "/CN= " # 使用 CA 签署服务器证书,向 CA 提交服务器证书请求文件 server.csr。接下来,使用以下命令生成服务器证书 echo subjectAltName=IP:127.0.0.1,IP:172.17.0.2,IP:172.17.0.3,IP:172.17.0.4 > extfile.cnf echo 01 > ca.srl openssl x509 -req -extfile extfile.cnf -days 18250 -CA ca.crt -CAkey ca.key -in server.csr -out server.crt ``` 启动docker ``` docker run --name vault01 -itd ubuntu:22.04 docker run --name vault02 -itd ubuntu:22.04 docker run --name vault03 -itd ubuntu:22.04 ``` 三台集群的配置文件 vault01 config.hcl ``` storage "raft" { path = "/opt/vault/data" node_id = "vault-node-1" retry_join { leader_api_addr = "https://172.17.0.2:8200" # leader_tls_servername = "vault01" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } retry_join { leader_api_addr = "https://172.17.0.3:8200" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } retry_join { leader_api_addr = "https://172.17.0.4:8200" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } } listener "tcp" { address = "172.17.0.2:8200" tls_disable = false tls_cert_file = "/opt/cert.pem" tls_key_file = "/opt/key.pem" tls_client_ca_file = "/opt/ca.pem" } api_addr = "https://172.17.0.2:8200" cluster_addr = "https://172.17.0.2:8201" disable_mlock = true seal "shamir" { secret_shares = 5 secret_threshold = 3 } ui = true ``` vault02 config.hcl ``` storage "raft" { path = "/opt/vault/data" node_id = "vault-node-2" retry_join { leader_api_addr = "https://172.17.0.2:8200" # leader_tls_servername = "vault01" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } retry_join { leader_api_addr = "https://172.17.0.3:8200" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } retry_join { leader_api_addr = "https://172.17.0.4:8200" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } } listener "tcp" { address = "172.17.0.3:8200" tls_disable = false tls_cert_file = "/opt/cert.pem" tls_key_file = "/opt/key.pem" tls_client_ca_file = "/opt/ca.pem" } api_addr = "https://172.17.0.3:8200" cluster_addr = "https://172.17.0.3:8201" disable_mlock = true seal "shamir" { secret_shares = 5 secret_threshold = 3 } ui = true ``` vault03 config.hcl ``` storage "raft" { path = "/opt/vault/data" node_id = "vault-node-3" retry_join { leader_api_addr = "https://172.17.0.2:8200" # leader_tls_servername = "vault01" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } retry_join { leader_api_addr = "https://172.17.0.3:8200" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } retry_join { leader_api_addr = "https://172.17.0.4:8200" leader_ca_cert_file = "/opt/ca.pem" leader_client_cert_file = "/opt/cert.pem" leader_client_key_file = "/opt/key.pem" } } listener "tcp" { address = "172.17.0.4:8200" tls_disable = false tls_cert_file = "/opt/cert.pem" tls_key_file = "/opt/key.pem" tls_client_ca_file = "/opt/ca.pem" } api_addr = "https://172.17.0.4:8200" cluster_addr = "https://172.17.0.4:8201" disable_mlock = true seal "shamir" { secret_shares = 5 secret_threshold = 3 } ui = true ``` 复制文件 ``` docker cp 1.hcl vault01:/root/config.hcl docker cp ca.crt vault01:/opt/ca.pem docker cp server.crt vault01:/opt/cert.pem docker cp server.key vault01:/opt/key.pem docker cp 2.hcl vault02:/root/config.hcl docker cp ca.crt vault02:/opt/ca.pem docker cp server.crt vault02:/opt/cert.pem docker cp server.key vault02:/opt/key.pem docker cp 3.hcl vault03:/root/config.hcl docker cp ca.crt vault03:/opt/ca.pem docker cp server.crt vault03:/opt/cert.pem docker cp server.key vault03:/opt/key.pem ``` 运行一台vault ``` ./vault server -config ./config.hcl ``` init 初始化 ``` VAULT_CACERT=/opt/ca.pem ./vault operator init -key-shares=3 -key-threshold=2 -address https://172.17.0.2:8200 ```  解封 vault01 ``` VAULT_CACERT=/opt/ca.pem ./vault operator unseal -address https://172.17.0.2:8200 ``` 解封vault02 ``` VAULT_CACERT=/opt/ca.pem ./vault operator unseal -address https://172.17.0.3:8200 ``` 解封vault03 ``` VAULT_CACERT=/opt/ca.pem ./vault operator unseal -address https://172.17.0.2:8200 ```  nginx 配置 ``` upstream vault_cluster { server 172.17.0.2:8200; # 第一个Vault节点的IP和端口 server 172.17.0.3:8200; # 第二个Vault节点的IP和端口 server 172.17.0.4:8200; # 第三个Vault节点的IP和端口 } server { listen 443 ssl; server_name vault.xeldax.com; ssl_certificate /opt/cert.pem; ssl_certificate_key /opt/key.pem; location / { proxy_pass http://vault_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` nginx -s reload    ### vault 常见命令 cheat sheet * https://gist.github.com/aderesh/ee60b0f15a6796e6f9f0546c927bc71e * https://github.com/devopshobbies/vault-cheatsheet * https://github.com/sloniki/vault-helper ``` vault server -dev export VAULT_TOKEN=hvs.AmC4RCGKiDipbj2xWx2lvTvP export VAULT_CACERT=/opt/ca.crt export VAULT_ADDR=https://127.0.0.1 vault login vault login -method=userpass username=$userName vault kv put $kvName/$secretName $key=$value vault kv get $kvName/$secretName vault kv list secretEngineName vault secrets list vault write auth/userpass/users/arthur password=dent vault list auth/userpass/users ``` ### vault UI secret配置  secret的种类  认证  认证方式  ACL策略管理  ### vault 策略 Vault策略是指在使用Vault这种工具时定义和控制访问权限的规则和策略。Vault是一个用于安全地存储、管理和控制访问敏感信息(如密码、API密钥、证书等)的工具,它可以帮助组织有效地保护其机密数据。 Vault策略可以定义哪些实体(如用户、应用程序)可以访问Vault中的哪些资源(如秘钥、凭证),以及可以执行哪些操作(如读取、写入、删除)。通过制定细粒度的策略,组织可以实现最小权限原则,确保每个实体只能访问其所需的资源,从而降低安全风险。 Vault 模拟了一个文件系统,Vault 中所有的信息,包括机密、配置等,都是依照各自的路径来使用的。使用 Vault 策略,我们可以使用声明式的语法来赋予或者禁止对特定路径的特定操作。 Vault 的策略默认情况下是拒绝一切访问的,所以一个空的策略不会赋予对系统的任何访问权限。  具体文档可以参考: https://developer.hashicorp.com/vault/docs/concepts/policies ``` vault policy write my-policy - << EOF # Dev servers have version 2 of KV secrets engine mounted by default, so will # need these paths to grant permissions: path "secret/data/*" { capabilities = ["create", "update"] } path "secret/data/foo" { capabilities = ["read"] } EOF ``` ``` [root@mytest ~]# vault policy write app1-readonly - <<EOF path "kv2/data/app1/*" { capabilities = ["read"] } EOF # 添加测试数据 [root@mytest ~]# vault kv put kv2/app1/config foo=bar ``` ### vault 认证和授权 在客户端可以与 Vault 交互之前,它必须根据 auth method 进行身份验证。身份验证后,将生成 access token, 后续的请求使用的是生成的 access token。 在 Vault 中,access token 的权限是通过策略(Policy)来管理的。 一般流程如下: 客户端发起身份验证请求,该请求流经 Core 模块并进入 Auth methods,Auth methods 确定请求是否有效并返回关联策略(Policies)的列表。在通过 Auth methods 完成了身份认证,并且检查的关联策略也符合授权之后,Token Store 将会生成并管理一个新的 Token, 这个 Token 会被返回给客户端,用于进行后续请求。需要注意的是,此 token 也都存在一个 Lease 租期(有效期),同时 Token 关联了相关的策略 Policies,这些策略将被用于验证请求的权限。 请求经过验证后,将被路由到 Secret engine 模块。如果 Secret engine 返回了一个 Secret(由 Vault 自动生成的 Secret), Core 会将其注册到 Expiration manager,并给它附加一个 lease ID。lease ID 被客户端用于更新(Renew)或吊销(Revoke)它得到的 Secret。如果客户端允许租约(Lease)到期,Expiration manager 将自动吊销这个 Secret  vault中支持的认证方式如下,也可以通过官方文档进行查阅(https://developer.hashicorp.com/vault/docs/concepts/identity) | 认证方法 | 名称报告的认证方法 | |----------------------|-----------------------------------| | AliCloud | Principal ID | | AppRole | Role ID | | AWS IAM | Configurable via iam_alias to one of: Role ID (default), IAM unique ID, Canonical ARN, Full ARN | | AWS EC2 | Configurable via ec2_alias to one of: Role ID (default), EC2 instance ID, AMI ID | | Azure | Subject (from JWT claim) | | Cloud Foundry | App ID | | GitHub | User login name associated with token | | Google Cloud | Configurable via iam_alias to one of: Role ID (default), Service account unique ID | | JWT/OIDC | Configurable via user_claim to one of the presented claims (no default value) | | Kerberos | Username | | Kubernetes | Configurable via alias_name_source to one of: Service account UID (default), Service account name | | LDAP | Username | | OCI | Role name | | Okta | Username | | RADIUS | Username | | TLS Certificate | Subject CommonName | | Token | entity_alias, if provided | | Username (userpass) | Username | 可以通过```vault auth list```来查看支持的auth  #### vault 认证和授权:Token Token认证方法是内置的,并且自动在/auth/token路径下提供。它允许用户使用令牌进行身份验证,同时也可以创建新令牌、通过令牌撤销密钥等操作。 当任何其他认证方法返回一个身份时,Vault核心会调用令牌方法为该身份创建一个新的唯一令牌。 令牌存储还可以用于绕过任何其他认证方法:您可以直接创建令牌,以及执行各种其他操作,如令牌的续订和撤销。 #### vault 认证和授权:Userpass userpass认证方法允许用户使用用户名和密码组合对Vault进行身份验证。 用户名/密码组合直接配置到auth方法中,使用users/路径。该方法无法从外部源读取用户名和密码。 该方法将所有提交的用户名转换为小写,例如Mary和mary被视为相同的输入。 本文档假定用户名和密码方法已挂载到Vault中默认的/auth/userpass路径。由于可以在任何位置启用认证方法,请相应使用-path标志更新您的CLI调用。 ``` vault auth enable userpass vault write auth/userpass/users/test1 \ password=1qaz@WSX \ policies=jenkins ``` 直接登录   #### vault 认证和授权:APP Role https://developer.hashicorp.com/vault/tutorials/auth-methods/approle  ``` root@terraform-auto-host-0:~# vault auth enable approle Error enabling approle auth: Error making API request. URL: POST https://127.0.0.1/v1/sys/auth/approle Code: 400. Errors: * path is already in use at approle/ root@terraform-auto-host-0:~# vault policy write jenkins -<<EOF # Read-only permission on secrets stored at 'secret/data/mysql/webapp' path "secret/data/mysql/webapp" { capabilities = [ "read" ] } EOF Success! Uploaded policy: jenkins root@terraform-auto-host-0:~# vault write auth/approle/role/jenkins token_policies="jenkins" \ token_ttl=1h token_max_ttl=4h Success! Data written to: auth/approle/role/jenkins root@terraform-auto-host-0:~# vault read auth/approle/role/jenkins Key Value --- ----- bind_secret_id true local_secret_ids false secret_id_bound_cidrs <nil> secret_id_num_uses 0 secret_id_ttl 0s token_bound_cidrs [] token_explicit_max_ttl 0s token_max_ttl 4h token_no_default_policy false token_num_uses 0 token_period 0s token_policies [jenkins] token_ttl 1h token_type default root@terraform-auto-host-0:~# vault read auth/approle/role/jenkins/role-id Key Value --- ----- role_id b0722f5d-5d8e-7eb6-fd88-aa6661e15033 root@terraform-auto-host-0:~# vault write -force auth/approle/role/jenkins/secret-id Key Value --- ----- secret_id d4a91d53-0321-4705-50ff-74db30b901ad secret_id_accessor 33f03926-d635-bef1-b503-98f21d4f1207 secret_id_num_uses 0 secret_id_ttl 0s root@terraform-auto-host-0:~# vault write auth/approle/login role_id="b0722f5d-5d8e-7eb6-fd88-aa6661e15033" \ secret_id="d4a91d53-0321-4705-50ff-74db30b901ad" Key Value --- ----- token hvs.CAESIK1m5anyn7VhCFQ1BfMWhi0KWU-NJ6cgrTK-a2lcQP7bGh4KHGh2cy5CM29yempjd3cwRzd3R3g5cURsb1JwNGE token_accessor vxKw7c4VBxYnj208uA1vIACI token_duration 1h token_renewable true token_policies ["default" "jenkins"] identity_policies [] policies ["default" "jenkins"] token_meta_role_name jenkins root@terraform-auto-host-0:~# export APP_TOKEN="hvs.CAESIK1m5anyn7VhCFQ1BfMWhi0KWU-NJ6cgrTK-a2lcQP7bGh4KHGh2cy5CM29yempjd3cwRzd3R3g5cURsb1JwNGE" root@terraform-auto-host-0:~# VAULT_TOKEN=$APP_TOKEN vault kv get secret/mysql/webapp ====== Secret Path ====== secret/data/mysql/webapp ======= Metadata ======= Key Value --- ----- created_time 2024-09-28T03:11:52.004508804Z custom_metadata <nil> deletion_time n/a destroyed false version 1 ====== Data ====== Key Value --- ----- db_name users password passw0rd~ username admin ``` #### vault 认证和授权:TLS 开启TLS 认证,写入证书 ``` vault auth enable cert vault write auth/cert/certs/web \ display_name=jenkins \ policies=jenkins \ certificate=@/root/vault/client.crt \ ttl=3600 ``` 登录尝试,不通过nginx,直接访问后端这样mtls不会报错。 export VAULT_ADDR=https://172.17.0.2:8200 ``` export VAULT_CACERT=/opt/ca.crt export VAULT_ADDR=https://172.17.0.2:8200 vault login \ -method=cert \ -ca-cert=/opt/ca.crt \ -client-cert=/root/vault/client.crt \ -client-key=/root/vault/client.key \ name=jenkins ``` 