网易首页 > 网易号 > 正文 申请入驻

使用 k8s/istio/cert-manager 和 vault 保障应用的 tls 安全

0
分享至

新钛云服已累计为您分享690篇技术干货

前言

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: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30725
hostPort: 8080
listenAddress: "127.0.0.1"
protocol: TCP
- containerPort: 32652
hostPort: 8443
listenAddress: "127.0.0.1"
protocol: TCP
- role: worker
- role: worker
- role: worker
- role: worker

使用 kind 来创建我们的集群

kind create cluster --name chris --config ~/kube.cfg

节点已启动

kubectl get nodes
NAME STATUS ROLES AGE VERSION
chris-control-plane Ready control-plane 21h v1.24.0
chris-worker Ready 21h v1.24.0
chris-worker2 Ready 21h v1.24.0
chris-worker3 Ready 21h v1.24.0
chris-worker4 Ready 21h v1.24.0

使用istioctl (https://github.com/istio/istio/releases) 命令安装 istio 。首先让我们定义一下配置内容。因为我们在本地运行,所以我们降低了一些资源要求。

---
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
name: installed-state
spec:
components:
ingressGateways:
-
enabled: true
name: istio-ingressgateway
namespace: istio-system
pilot:
k8s:
hpaSpec:
maxReplicas: 2
minReplicas: 1
resources:
requests:
cpu: 512m
memory: 512Mi
profile: default
values:
global:
istioNamespace: istio-system

安装 istio

istioctl manifest install -f ~/istio.cfg

删除默认类型的 istio-ingressgateway 的 service。

kubectl delete svc istio-ingressgateway -n istio-system

创建一个 NodePort 服务,从而实现从节点端口访问 istio-ingressgateway 。

apiVersion: v1
kind: Service
metadata:
labels:
app: istio-ingressgateway
istio: ingressgateway
name: istio-ingressgateway
namespace: istio-system
spec:
type: NodePort
ports:
- name: http
nodePort: 30725
port: 8080
protocol: TCP
targetPort: 8080
- name: https
nodePort: 32652
port: 443
protocol: TCP
targetPort: 8443
selector:
app: istio-ingressgateway

应用一下

kubectl apply -f svc.yml

此时,istio 应该正常运行。

kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-5f86977657-qfxrs 1/1 Running 0 21h
istiod-67db665bd9-4d8nl 1/1 Running 0 21h

我们将创建一个虚拟网关进行测试

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
namespace: istio-system
spec:
selector:
app: istio-ingressgateway
servers:
- port:
number: 8080
name: http
protocol: HTTP
hosts:
- "*"

同时应用

kubectl apply -f gateway.yml

使用 curl,我们能够从我们客户端去访问 istio 入口。注意:404 是预期的结果,因为我们还没有配置任何应用程序或 istio 虚拟服务。

curl localhost:8080 -vs
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< date: Thu, 28 Jul 2022 21:44:50 GMT
< server: istio-envoy
< content-length: 0
<
* Connection #0 to host localhost left intact
* Closing connection 0

我们不仅连接了(即使我们得到了 404 ),而且您可以看到服务器是 istio-envoy 响应,这意味着 envoy 正在处理流量。

最后一步,让我们创建一个命名空间并将其标记为 istio 注入以供将来工作。

kubectl create ns web
kubectl label namespace web istio-injection=enabled --overwrite

安装 Vault

如果这是一个生产环境,我们会按照严格标准去调整以及安装 vault,但当前只是一个一次性的测试环境,所以我们不做任何优化调整。

使用 helm 安装 Vault Chart

kubectl create namespace vault
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault --namespace vault

Vault pod 启动了,但它还没有就绪,因为它当前处于锁定状态。在 pod 中执行以下命令以解封。

kubectl -n vault exec vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > /tmp/token.json

从 /tmp/token.josn 中取出 unseal_keys_b64 密钥,并使用它来解封 vault。

kubectl exec -n vault vault-0 -- vault operator unseal

现在,vault 应该已解封并处于就绪状态。

kubectl get pods -n vault
NAME READY STATUS RESTARTS AGE
vault-0 1/1 Running 0 6m28s
vault-agent-injector-5d4c695bf4-zzgq5 1/1 Running 0 6m29s

现在,我们可以使用 port-forward 来转发访问 vault,并使用可以在 /tmp/token.json 中找到的根令牌登录 vault。

kubectl port-forward vault-0 8200 -n vault
# Open a browser to localhost:8200

现在 vault 已准备就绪,让我们创建一个新的 secret engine,启用新 engine -> PKI Certificates,我使用的是 pki/ 路径。或者,如果启用了 cli,您可以使用以下命令

vault secrets enable pki

将 vault 二进制文件下载到您本地并设置 vault 地址和令牌。

brew install vault
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=

现在我们可以从 cli 与 Vault 进行交互了

vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.10.3
Build Date n/a
Storage Type file
Cluster Name vault-cluster-d4e826eb
Cluster ID 76196d6e-0033-b892-4826-2674b6befe23
HA Enabled false

我们想给 istio 一个证书以供 CA 验证,所以让我们在 Vault 中创建一个。首先调整一些租期时间(10 年)。

vault secrets tune -max-lease-ttl=87600h pki

创建一个名为 allowit 的角色,然后定义要发送到 CA 的 CSR 的路径。本处将使用域名 somecompany.com 进行所有测试。

# create a role
vault write pki/roles/allowit allow_any_name=true
# generate
vault write -field=certificate pki/root/generate/internal \
common_name="somecompany.com" \
issuer_name="root" \
ttl=87600h > ca.crt
# config
vault write pki/config/urls \
issuing_certificates="$VAULT_ADDR/v1/pki/ca" \
crl_distribution_points="$VAULT_ADDR/v1/pki/crl"

我们当前在做的是为访问路径设置角色以与 CA 一起使用。

现在是时候获得中间证书了。CA 虽然很不错,它确认了证书属于正确的人,但它有很大的权力。中间证书基本上是一种从另一个 CA 创建 CA 的方法。最佳做法是使用中间证书。根证书将能够撤销任何中间 CA。

但如下所见,步骤类似,我们现在使用的是 pki_int 路径。

vault secrets enable -path=pki_int pki
vault secrets tune -max-lease-ttl=43800h pki_int
vault write -format=json pki_int/intermediate/generate/internal \
common_name="somecompany.com Intermediate Authority" \
issuer_name="somecompany-intermediate" \
| jq -r '.data.csr' > pki_intermediate.csr
vault write -format=json pki/root/sign-intermediate \
issuer_ref="root" \
csr=@pki_intermediate.csr \
format=pem_bundle ttl="43800h" \
| jq -r '.data.certificate' > intermediate.cert.pem

仍然使用 somecompany.com 域名,确保颁发者名称与根 CA 和中间 CA 的颁发者名称相同(在此示例中仅称为 root)。

将签名的证书写回 vault 。

vault write pki_int/intermediate/set-signed certificate=@intermediate.cert.pem

现在我们的 CA 和中间证书已经创建好了。我们应该为它创建一个角色。

vault write pki_int/roles/example-dot-com \
issuer_ref="$(vault read -field=default pki_int/config/issuers)" \
allowed_domains="somecompany.com" \
allow_subdomains=true \
max_ttl="720h"

目前,我们都准备好了!我们已经创建了一个带有 vault 的 CA 和中间 CA!

让我们测试一下!让我们向 vault 申请 chris.somecompany.com 的 24 小时有效证书。(这将返回 CA、证书和私钥)

vault write pki_int/issue/allowit common_name="chris.somecompany.com" ttl="24h"

本处只关心证书,所以将上面命令返回的base64复制并粘贴到一个临时文件中,然后使用openssl 进行检查。

openssl x509 -in site -text | head -n 10
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
4f:87:f9:6f:eb:68:db:2a:39:f5:06:1e:43:32:98:04:32:2e:df:4d
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=somecompany.com Intermediate Authority
Validity
Not Before: Jul 29 20:32:09 2022 GMT
Not After : Jul 30 20:32:39 2022 GMT
Subject: CN=chris.somecompany.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption

从上面的输出可以看出,证书有效期为 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

helm repo add jetstack https://charts.jetstack.io
helm repo update
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.crds.yaml
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.9.1

当前可以确认 pod 已在 cert-manager 命名空间中启动,我们也可以看到 cert-manager crds 被创建了。

kubectl get crd | grep cert
certificaterequests.cert-manager.io 2022-07-29T20:59:11Z
certificates.cert-manager.io 2022-07-29T20:59:11Z
challenges.acme.cert-manager.io 2022-07-29T20:59:11Z
clusterissuers.cert-manager.io 2022-07-29T20:59:11Z
issuers.cert-manager.io 2022-07-29T20:59:11Z
orders.acme.cert-manager.io 2022-07-29T20:59:11Z

当前 cert-manager 已经启动并运行,它如何对 vault 进行身份验证?Authrole 允许我们设置一个密钥来与 vault 对话。

通过如下命令启用审批

vault auth enable approle

创建 policy.hcl 文件,它可以访问 pki/ 和 pki-int 路径

#policy.hcl
path "pki*" { capabilities = [ "create", "read", "update", "delete", "list", "sudo"]}

写入 vault

vault policy write pki_policy policy.hcl

创建一个 certmanager 角色,该角色附加到 pki_policy vault策略

vault write auth/approle/role/certmanager secret_id_ttl=8760h token_num_uses=0 token_ttl=20m token_max_ttl=30m secret_id_num_uses=0 policies=pki_policy

我们现在有一个 role_id

vault read auth/approle/role/certmanager/role-id
Key Value
--- -----
role_id bb3cdc37-9fe0-f99f-99d4-1ff80d26ab1d

让我们来写入一个 secret

vault write -f auth/approle/role/certmanager/secret-id

这将返回一个 secret_id(你的密钥),获取,base64 ,然后创建一个 kubernetes secret并上传

apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: cert-manager
namespace: istio-system
data:
secretId:

看起来内容比较多,但我们所做的只是告诉 Vault 创建一个密钥。我们可以使用此密钥进行身份验证以进行保管。

配置 cert-manager

现在 cert-manager 可以与 vault 通信,让我们配置 cert-manager。

issuer 用于与 vault 对话,传递我们的应用角色密钥和路径。

本处,我们将所有这些东西都放在了 istio-system 命名空间中。

---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: istio
namespace: istio-system
spec:
vault:
path: pki_int/sign/allowit
server: http://vault-internal.vault.svc.cluster.local:8200
auth:
appRole:
path: approle
roleId: "bb3cdc37-9fe0-f99f-99d4-1ff80d26ab1d"
secretRef:
name: cert-manager
key: secretIda

然后我们创建一个证书 CRD 来定义我们的证书信息并告诉它把我们生成的证书放在哪里(在这个例子中是 my-cert )。

---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: istio
namespace: istio-system
spec:
secretName: my-cert
issuerRef:
name: istio
commonName: chris.somecompany.com
dnsNames:
- chris.somecompany.com

等待 30s ,如果没有意外,那么 cert-manager 将去 vault 请求一个证书,并将其保存为一个可以使用的密钥。

kubectl -n istio-system get Issuer
NAME READY AGE
istio True 5m34s
kubectl -n istio-system get Certificate
NAME READY SECRET AGE
istio True my-cert 5m57s

最重要的是,我们的证书是否已准备好用作 kubernetes secret?

kubectl -n istio-system get secret my-certNAME TYPE DATA AGEmy-cert kubernetes.io/tls 3 6m43s

在这个过程中,可以通过 kubectl describe 命令来查看详细信息。。

创建示例应用

一切准备就绪,让我们在 web 命名空间中启动一个 nginx pod 虚拟服务。请记住,我们标记了命名空间,因此该命名空间内启动的 pod 也将获得 istio sidecar。

kubectl -n web create deploy nginx --image=nginx --port 80
kubectl -n web expose deploy nginx --port 80

对于 istio,我们需要一个 VirtualService 来进行路由。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx
namespace: web
spec:
gateways:
- istio-system/https
hosts:
- "chris.somecompany.com"
http:
- route:
- destination:
host: nginx

此外,创建一个使用我们来自 vault 的新证书的网关

---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: https
namespace: istio-system
spec:
selector:
app: istio-ingressgateway
servers:
- port:
number: 8443
name: https
protocol: HTTPS
hosts:
- "chris.somecompany.com"
tls:
mode: SIMPLE
credentialName: my-cer

在真实环境中,我们会在 istio ingress 前面添加一个负载均衡器,但是因为我们使用的是 kind,所以本处会将主机添加到 /etc/hosts 并进行端口转发。

kubectl -n istio-system port-forward istio-ingressgateway-5f86977657-qfxrs 8443

kubectl -n istio-system get secret my-cert -o json | jq -r '.data["ca.crt"]' | base64 -d > ca.crt
open ca.crt
# mark as always trust

在浏览器中打开,我们现在可以使用由 vault 签名的有效 TLS 证书访问我们的 nginx 服务器 (https://chris.somecompany.com:8443)!

总结

通过本文,我们学习了如何使用 vault 来保存证书等密钥信息,如何使用 cert-manager 来申请免费的证书以及 istio 如何去使用这些信息,最终实现了一个基于 istio 的安全 web 应用。

了解新钛云服

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
勇媒晒照:2年前的今天 最经典的NBA照片出炉!

勇媒晒照:2年前的今天 最经典的NBA照片出炉!

直播吧
2024-06-17 19:09:11
震惊!哈马斯卡萨母旅处理叛徒画面流出,惊心动魄上热搜

震惊!哈马斯卡萨母旅处理叛徒画面流出,惊心动魄上热搜

亡海中的彼岸花
2024-06-16 16:42:12
美军刚刚收到最新情报,解放军的隐轰快了,将远远超出外界预料

美军刚刚收到最新情报,解放军的隐轰快了,将远远超出外界预料

蒋福伟
2024-06-17 15:12:30
革命性突破!美企成功研制核电池,几乎无辐射,电量够用100年

革命性突破!美企成功研制核电池,几乎无辐射,电量够用100年

十三级台阶
2024-06-15 15:51:27
险造欧洲杯最佳球?21岁中锋暴力远射中柱!身价5千万引3豪门哄抢

险造欧洲杯最佳球?21岁中锋暴力远射中柱!身价5千万引3豪门哄抢

我爱英超
2024-06-17 02:49:40
俄军最大外援曝光,1万集装箱满载480万发炮弹,从东亚直发俄罗斯

俄军最大外援曝光,1万集装箱满载480万发炮弹,从东亚直发俄罗斯

铁血战史1927
2024-06-16 14:17:56
地震级交易曝光,新疆2换1锁定顶级后卫,邱彪打造豪阵冲冠

地震级交易曝光,新疆2换1锁定顶级后卫,邱彪打造豪阵冲冠

维世话体坛
2024-06-17 16:16:02
菲律宾已成坏榜样,东盟国家不忍了,柬埔寨后,印尼也大声批评!

菲律宾已成坏榜样,东盟国家不忍了,柬埔寨后,印尼也大声批评!

史小纪
2024-06-17 15:10:05
奥巴马23岁女儿180斤,穿露脐装,手中夹烟,身材似大妈引热议

奥巴马23岁女儿180斤,穿露脐装,手中夹烟,身材似大妈引热议

亦纯杂谈
2024-06-17 13:07:10
中将宗顺留突然去世原因披露,两女儿定居美国,弟弟名下25家公司

中将宗顺留突然去世原因披露,两女儿定居美国,弟弟名下25家公司

求实者
2024-06-16 14:40:51
日媒:森保一将于本周末飞德国现场观看欧洲杯,直言日本队要进化

日媒:森保一将于本周末飞德国现场观看欧洲杯,直言日本队要进化

直播吧
2024-06-17 11:09:21
章子怡女儿成学霸,汪峰:醒醒上二年级已超卷,常提醒她要多玩!

章子怡女儿成学霸,汪峰:醒醒上二年级已超卷,常提醒她要多玩!

娱乐圈宇桐
2024-06-17 14:04:59
东莞炒房客全军覆没,东莞楼市松山湖某小区房价跌破20000元

东莞炒房客全军覆没,东莞楼市松山湖某小区房价跌破20000元

有事问彭叔
2024-06-17 16:26:17
后续!江苏教育部门回应:姜萍大学梦破灭,强基计划恐成唯一途径

后续!江苏教育部门回应:姜萍大学梦破灭,强基计划恐成唯一途径

校长侃财
2024-06-17 11:54:32
大胃王浪胃仙现身贵州狂吃火锅,从大叔变美女,身体暴瘦疑变性!

大胃王浪胃仙现身贵州狂吃火锅,从大叔变美女,身体暴瘦疑变性!

八卦爱侃娱
2024-06-15 16:55:28
女儿高考完睡了3天3夜,家长不敢喊,醒来说一席话让父母破防

女儿高考完睡了3天3夜,家长不敢喊,醒来说一席话让父母破防

子芫伴你成长
2024-06-14 22:57:44
16GB+1TB!新机突然官宣:6月20日,新品全新发布!

16GB+1TB!新机突然官宣:6月20日,新品全新发布!

最潮家居评
2024-06-17 17:40:24
99年,女子被推土坑活埋,死前哀求:求你放了我,女儿还在家等我

99年,女子被推土坑活埋,死前哀求:求你放了我,女儿还在家等我

星辰故事屋
2024-06-11 13:32:59
下半年贵人相助,职场开挂的星座,转运在即,机会来了要接住

下半年贵人相助,职场开挂的星座,转运在即,机会来了要接住

别人都叫我阿螫
2024-06-17 21:45:41
港媒曝王祖贤疑似怀孕,57岁肚大像大妈,本人特意晒照澄清?

港媒曝王祖贤疑似怀孕,57岁肚大像大妈,本人特意晒照澄清?

柴叔带你看电影
2024-06-16 22:09:24
2024-06-17 22:58:44
新钛云服
新钛云服
云管理服务专家
371文章数 29关注度
往期回顾 全部

科技要闻

为什么你的iPhone,肯定用不上"苹果AI"?

头条要闻

北约秘书长称正讨论将核武器置于待命状态 俄方回应

头条要闻

北约秘书长称正讨论将核武器置于待命状态 俄方回应

体育要闻

豪华阵容,原始战术 英格兰10亿天团就这?

娱乐要闻

上影节红毯:倪妮好松弛,娜扎吸睛

财经要闻

人均养老金上调3% 怎么年轻人吵翻了?

汽车要闻

传奇新篇章 全新一代大众迈腾来了

态度原创

时尚
教育
数码
亲子
家居

永不过时的高级感,这个风格已经美了20年了

教育要闻

今年高考评卷情况怎么样?带你直击阅卷现场!

数码要闻

ILOVBEE B87 客制化三模键盘知速轴开售,299 元

亲子要闻

马桶爆改洗发椅。加一个垫子瞬间完成

家居要闻

研己实景 古典与现代的交融

无障碍浏览 进入关怀版