
使用 k8s/istio/cert-manager 和 vault 保障应用的 tls 安全
前言
Vault 是安全应用维护人员最喜欢的 hashcorp 产品之一 。Vault 是存储机密、证书、管理策略、加密数据等内容的安全工具。Vault 使用受信任的身份集中密码和控制访问权限,以此减少对静态、硬编码凭证的需求。它使用集中托管和受保护的加密密钥来动态和静态加密敏感数据,所有一切均可通过单个工作流和 API 实现。
Istio 非常重要的一个功能是能够锁定并且保护网格内的来往流量。本文的目的是基于 TLS 启动一个简单的 Web 应用程序,然后使用 Vault 生成对应的安全证书,从而保证 Istio 管理的服务安全。
简单点说,使用 TLS 时候,当您建立连接时,服务器会提供一个公钥,您可以使用此密钥对传输中的数据进行加密,一旦被目标服务器接收,数据将使用私钥解密。为了验证密钥是否有效,可以使用 CA(通常 CA 是付费服务),但我们可以通过 vault 创建一个自签名 CA)。
现在先让我们忽略 vault,让我们在系统上创建一个测试环境。为此使用 kind (https://kind.sigs.k8s.io/) 来快速创建一个测试环境。
用 kind 建立一个 kubernetes 集群
下载 kind 后,我们可以定义一个 kind 配置文件来启动 4 个 worker。我们还可以配置一些端口映射,以确保我们可以直接访问入口网关。
使用 kind 来创建我们的集群
节点已启动
使用istioctl (https://github.com/istio/istio/releases) 命令安装 istio 。首先让我们定义一下配置内容。因为我们在本地运行,所以我们降低了一些资源要求。
安装 istio
删除默认类型的 istio-ingressgateway 的 service。
创建一个 NodePort 服务,从而实现从节点端口访问 istio-ingressgateway 。
应用一下
此时,istio 应该正常运行。
我们将创建一个虚拟网关进行测试
同时应用
使用 curl,我们能够从我们客户端去访问 istio 入口。注意:404 是预期的结果,因为我们还没有配置任何应用程序或 istio 虚拟服务。
我们不仅连接了(即使我们得到了 404 ),而且您可以看到服务器是 istio-envoy 响应,这意味着 envoy 正在处理流量。
最后一步,让我们创建一个命名空间并将其标记为 istio 注入以供将来工作。
安装 Vault
如果这是一个生产环境,我们会按照严格标准去调整以及安装 vault,但当前只是一个一次性的测试环境,所以我们不做任何优化调整。
使用 helm 安装 Vault Chart
Vault pod 启动了,但它还没有就绪,因为它当前处于锁定状态。在 pod 中执行以下命令以解封。
从 /tmp/token.josn 中取出 unseal_keys_b64 密钥,并使用它来解封 vault。
现在,vault 应该已解封并处于就绪状态。
现在,我们可以使用 port-forward 来转发访问 vault,并使用可以在 /tmp/token.json 中找到的根令牌登录 vault。
现在 vault 已准备就绪,让我们创建一个新的 secret engine,启用新 engine -> PKI Certificates,我使用的是 pki/ 路径。或者,如果启用了 cli,您可以使用以下命令
将 vault 二进制文件下载到您本地并设置 vault 地址和令牌。
现在我们可以从 cli 与 Vault 进行交互了
我们想给 istio 一个证书以供 CA 验证,所以让我们在 Vault 中创建一个。首先调整一些租期时间(10 年)。
创建一个名为 allowit 的角色,然后定义要发送到 CA 的 CSR 的路径。本处将使用域名 somecompany.com 进行所有测试。
我们当前在做的是为访问路径设置角色以与 CA 一起使用。
现在是时候获得中间证书了。CA 虽然很不错,它确认了证书属于正确的人,但它有很大的权力。中间证书基本上是一种从另一个 CA 创建 CA 的方法。最佳做法是使用中间证书。根证书将能够撤销任何中间 CA。
但如下所见,步骤类似,我们现在使用的是 pki_int 路径。
仍然使用 somecompany.com 域名,确保颁发者名称与根 CA 和中间 CA 的颁发者名称相同(在此示例中仅称为 root)。
将签名的证书写回 vault 。
现在我们的 CA 和中间证书已经创建好了。我们应该为它创建一个角色。
目前,我们都准备好了!我们已经创建了一个带有 vault 的 CA 和中间 CA!
让我们测试一下!让我们向 vault 申请 chris.somecompany.com 的 24 小时有效证书。(这将返回 CA、证书和私钥)
本处只关心证书,所以将上面命令返回的base64复制并粘贴到一个临时文件中,然后使用openssl 进行检查。
从上面的输出可以看出,证书有效期为 24 小时,对 chris.somecompany.com 有效,包含我们要求的所有内容!
目前的操作都是通过命令行,忽略使用 vault UI,但我们也可以使用 UI 来执行上述所有步骤。例如,我们可以在 UI 上看到我们的证书。
Cert manager
kubernetes、istio 和 vault 就这样配置好了。我们的最终目标是启动一个使用 vault 的 TLS 证书的应用程序。
Cert-manager (https://cert-manager.io/) 允许我们向 kubernetes secret api 请求和写入证书。然后 istio 将这些证书与网关 crd 一起使用。
使用 helm 安装Cert-manager
当前可以确认 pod 已在 cert-manager 命名空间中启动,我们也可以看到 cert-manager crds 被创建了。
当前 cert-manager 已经启动并运行,它如何对 vault 进行身份验证?Authrole 允许我们设置一个密钥来与 vault 对话。
通过如下命令启用审批
创建 policy.hcl 文件,它可以访问 pki/ 和 pki-int 路径
写入 vault
创建一个 certmanager 角色,该角色附加到 pki_policy vault策略
我们现在有一个 role_id
让我们来写入一个 secret
这将返回一个 secret_id(你的密钥),获取,base64 ,然后创建一个 kubernetes secret并上传
看起来内容比较多,但我们所做的只是告诉 Vault 创建一个密钥。我们可以使用此密钥进行身份验证以进行保管。
配置 cert-manager
现在 cert-manager 可以与 vault 通信,让我们配置 cert-manager。
issuer 用于与 vault 对话,传递我们的应用角色密钥和路径。
本处,我们将所有这些东西都放在了 istio-system 命名空间中。
然后我们创建一个证书 CRD 来定义我们的证书信息并告诉它把我们生成的证书放在哪里(在这个例子中是 my-cert )。
等待 30s ,如果没有意外,那么 cert-manager 将去 vault 请求一个证书,并将其保存为一个可以使用的密钥。
最重要的是,我们的证书是否已准备好用作 kubernetes secret?
在这个过程中,可以通过 kubectl describe 命令来查看详细信息。。
创建示例应用
一切准备就绪,让我们在 web 命名空间中启动一个 nginx pod 虚拟服务。请记住,我们标记了命名空间,因此该命名空间内启动的 pod 也将获得 istio sidecar。
对于 istio,我们需要一个 VirtualService 来进行路由。
此外,创建一个使用我们来自 vault 的新证书的网关
在真实环境中,我们会在 istio ingress 前面添加一个负载均衡器,但是因为我们使用的是 kind,所以本处会将主机添加到 /etc/hosts 并进行端口转发。
在我们点击页面之前,让我们从 k8s 中获取公共 CA 并信任它。
在浏览器中打开,我们现在可以使用由 vault 签名的有效 TLS 证书访问我们的 nginx 服务器 (https://chris.somecompany.com:8443)!
总结
通过本文,我们学习了如何使用 vault 来保存证书等密钥信息,如何使用 cert-manager 来申请免费的证书以及 istio 如何去使用这些信息,最终实现了一个基于 istio 的安全 web 应用。
文章转载自公众号:新钛云服
