上一篇文章我们使用cert-manager的ACME功能从自己的Vault生成了数字证书,其实cert-manager也能直接与Vault的非ACME API交互。
过程很简单,cert-manager在Vault那里验证身份,通过后就可以提交证书请求,有权限的话就拿到证书。
身份验证与权限
Vault支持多种身份验证方式
先改下安全凭据的默认有效期:
1
2
|
vault login # 用root的token登录,照我第一篇文章那样搞的日常管理员用户没权限读下面的路径
vault read sys/auth/approle/tune
|
可以看到当前的也是默认的设置:
1
2
3
4
5
6
7
|
Key Value
--- -----
default_lease_ttl 768h
description n/a
force_no_cache false
max_lease_ttl 768h
token_type default-service
|
喜欢的话可以把它改长点:
1
|
vault auth tune -default-lease-ttl=8760h -max-lease-ttl=8760h approle/
|
㊟ 确保/etc/vault.d/
这里没有文件定义了上面的时间。
⚠️ 本系列文章都不适合于生产环境,这些只是过家家的。
验证方式默认都是关闭的:我们手动打开AppRole类型的验证方式
1
|
vault auth enable approle
|
然后可以创建一个服务账号:
1
2
3
4
5
6
7
|
vault write auth/approle/role/certmanager-approle \
token_type=batch \
# secret_id_ttl=720h \ # 从这行开始我都注释掉的,过家家无所谓什么过期时间,默认是0——永不过期
token_ttl=720h \
token_max_ttl=720h \
secret_id_num_uses=20 \ #使用次数
secret_id_bound_cidrs="" # 使用反向代理服务器或负载均衡器的填写对端地址,比如“127.0.0.1/32”
|
可以查看它的信息:
1
|
vault read auth/approle/role/certmanager-approle
|
可以改,比如:
1
|
vault write auth/approle/role/certmanager-approle secret_id_bound_cidrs="192.168.0.0/16, 127.0.0.1/32"
|
获取role ID,四舍五入约等于用户名:
1
2
3
4
|
vault read auth/approle/role/certmanager-approle/role-id
Key Value
--- -----
role_id 24d0b1fc-de60-cd1e-b69c-e53be481c864
|
创建一条ACL,这决定了关联的服务账号能不能搞证书,能在哪里搞:
1
2
3
4
5
6
|
vault policy write cert-manager - <<EOF
path "ca*" { capabilities = ["read", "list"] }
path "ca-int-x1/roles/cert-test" { capabilities = ["create", "update"] }
path "ca-int-x1/sign/cert-test" { capabilities = ["create", "update"] }
path "ca-int-x1/issue/cert-test" { capabilities = ["create"] }
EOF
|
将策略与服务账号关联:
1
|
vault write auth/approle/role/certmanager-approle policies=cert-manager
|
给它生成secure ID,四舍五入相当于密码:
1
2
3
4
5
|
vault write -f auth/approle/role/certmanager-approle/secret-id
Key Value
--- -----
secret_id 51434556-11ed-1447-157f-5ad363a38727
secret_id_accessor 8c666f20-a127-7464-a08b-783e1bd3574e
|
㊟ 只显示一次,坏掉了忘记了等等情况就要再生成一个。
看看密码过期时间:
1
|
vault write auth/approle/role/certmanager-approle/secret-id/lookup secret_id='<secret_id>'
|
编个码:
1
2
|
echo -n '<secret-id>' | openssl base64
ZTRkY2IzMzYtMzQzYy0wYmZiLThlYzMtY2ViMmE4ZDk0NjVl # 记下来
|
我们那个发证书的角色我手贱乱改过,先看看信息:
1
|
vault read ca-int-x1/roles/cert-test
|
有什么地方不满意的话可以改,比如:
1
2
3
4
|
vault write ca-int-x1/roles/cert-test \
key_type=any \
allowed_domains=miyunda.com,.local \
allow_subdomains=true
|
Kubernetes 这边
这回与上次不同,这次实验不再需要搞什么DNS劫持什么IP转发了,因为不再有ACME挑战,而是有权限就能给。让我们到minikube机器上:
1
2
3
|
minikube stop
minikube delete
minikube start
|
Secret
“密码”存这里:
1
2
3
4
|
mkdir ~/hellonerd-certmanager-approle && cd ~/hellonerd-certmanager-approle
nano secret.yaml
kubectl create -f secret.yaml
secret/certmanager-vault-approle created
|
1
2
3
4
5
6
7
8
9
|
# secret.yaml
piVersion: v1
kind: Secret
type: Opaque
metadata:
name: certmanager-vault-approle
namespace: default # 这行的内容和楼下的文件要一致
data:
secretId: "<secret_id>"
|
Issuer
还得把Vault的信息给它,让它知道去哪能得到证书:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# issuer.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: vault-dev-approle
namespace: default
spec:
vault:
path: ca-int-x1/sign/cert-test
server: https://vault-dev.miyunda.com
# caBundle: <base64 encoded caBundle PEM file> # Vault使用自签名CA提供服务的话得把CA证书放在这里
auth:
appRole:
path: approle
roleId: "<rold_id>"
secretRef:
name: certmanager-vault-approle
key: secretId
|
1
2
3
|
nano issuer.yaml
kubectl create -f issuer.yaml
certificate.cert-manager.io/foo-miyunda-com created
|
建好之后可以看看状态:
1
2
3
|
kubectl get issuer
NAME READY AGE
vault-dev-approle True 3s
|
不行的话可以看看:
1
|
kubectl describe issuer <issuer名字> # -n <namespace>
|
打印的信息会报告哪里有问题。
证书
从Vault获取证书:
1
2
|
nano mycert.yaml
kubectl create -f mycert.yaml
|
这文件很多地方不用填写的,我就是为了举例子弄成这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# mycert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: foo-miyunda-com
namespace: default
annotations:
cert-manager.io/issuer: "vault-dev-approle"
spec:
secretName: foo-miyunda-com
subject:
organizations:
- "Miyunda & Co Inc"
countries:
- Haidian # ???
- Xuanwu # ???
localities:
- Beijing
organizationalUnits:
- "Marketing"
provinces:
- Asia
commonName: foo.miyunda.com
dnsNames:
- bar.miyunda.com
- foo.bar.miyunda.com
issuerRef:
name: vault-dev-approle
kind: Issuer
group: cert-manager.io
privateKey:
# Vault那边叫“EC”
algorithm: ECDSA
duration: 2160h
# 默认是三个月有效期,提前一个月续期
renewBefore: 360h
isCA: false
usages:
- server auth
- client auth
|
看看状态:
1
2
3
|
kubectl get certificate foo-miyunda-com
NAME READY SECRET AGE
foo-miyunda-com True foo-miyunda-com 2s
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
kubectl describe certificate foo-miyunda-com # -n <namespace>
Name: foo-miyunda-com
Namespace: default
Labels: <none>
Annotations: cert-manager.io/issuer: vault-dev-approle
API Version: cert-manager.io/v1
Kind: Certificate
Metadata:
Creation Timestamp: 2024-09-15T14:13:51Z
Generation: 1
Resource Version: 187301
UID: c74f8a18-bdde-4c90-ba55-fa89c98d3351
Spec:
Common Name: foo.miyunda.com
Dns Names:
bar.miyunda.com
foo.bar.miyunda.com
Duration: 2160h
Is CA: false
Issuer Ref:
Group: cert-manager.io
Kind: Issuer
Name: vault-dev-approle
Private Key:
Algorithm: ECDSA
Renew Before: 360h
Secret Name: foo-miyunda-com
Subject:
Countries:
Haidian
Xuanwu
Localities:
Beijing
Organizational Units:
Marketing
Organizations:
Miyunda & Co Inc
Provinces:
Asia
Usages:
server auth
client auth
Status:
Conditions:
Last Transition Time: 2024-09-15T14:13:51Z
Message: Certificate is up to date and has not expired
Observed Generation: 1
Reason: Ready
Status: True
Type: Ready
Not After: 2024-12-12T14:27:12Z
Not Before: 2024-09-13T14:26:42Z
Renewal Time: 2024-11-27T14:27:12Z
Events: <none>
kubectl describe certificate hellonerd-example-tls-approle
Name: hellonerd-miyunda-com-tls-approle
Namespace: default
Labels: <none>
Annotations: <none>
API Version: cert-manager.io/v1
Kind: Certificate
Metadata:
Creation Timestamp: 2024-09-15T14:12:37Z
Generation: 1
Owner References:
API Version: networking.k8s.io/v1
Block Owner Deletion: true
Controller: true
Kind: Ingress
Name: kuard
UID: c273e1c4-68ca-48bf-bb86-775ed5e86d40
Resource Version: 187229
UID: 85bc79a6-bff5-469b-bee6-18568e45e14a
Spec:
Common Name: hellonerd.miyunda.com
Dns Names:
hellonerd.miyunda.com
Duration: 2160h0m0s
Issuer Ref:
Group: cert-manager.io
Kind: Issuer
Name: vault-dev-approle
Private Key:
Algorithm: ECDSA
Rotation Policy: Always
Size: 384
Renew Before: 720h0m0s
Secret Name: hellonerd-miyunda-com-tls-approle
Subject:
Countries:
CN
Localities:
Beijing
Organizational Units:
Marketing
Organizations:
Miyunda & Co Inc
Provinces:
Haidian
Xuanwu
Usages:
key agreement
digital signature
server auth
Status:
Conditions:
Last Transition Time: 2024-09-15T14:12:37Z
Message: Certificate is up to date and has not expired
Observed Generation: 1
Reason: Ready
Status: True
Type: Ready
Not After: 2024-12-14T13:31:50Z
Not Before: 2024-09-15T13:31:20Z
Renewal Time: 2024-11-14T13:31:50Z
Events: <none>
|
然后在随便什么资源里面引用这个证书就好了。
Ingress
也可以搞成纯自动的,自动申请安装续期等等。
先把上一篇文章那个DNS私有解析去掉——用不上了:
1
2
|
sudo sed -i '/hellonerd/d' /etc/hosts
nslookup hellonerd.miyunda.com
|
准备一个文件,同上面的例子一样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kuard
annotations:
cert-manager.io/issuer: "vault-dev-approle" #必填
cert-manager.io/common-name: "hellonerd.miyunda.com" #必填
cert-manager.io/subject-organizations: "Miyunda & Co Inc"
cert-manager.io/subject-organizationalunits: "Marketing"
cert-manager.io/subject-countries: "CN"
cert-manager.io/subject-provinces: "Haidian,Xuanwu"
cert-manager.io/subject-localities: "Beijing"
cert-manager.io/private-key-algorithm: "ECDSA" #默认是RSA
cert-manager.io/private-key-size: "384" # 选了ECDSA那么默认是256
cert-manager.io/duration: "2160h" # 默认就是这个
cert-manager.io/renew-before: "720h" # 同上
cert-manager.io/usages: "key agreement, digital signature, server auth" # 同上
cert-manager.io/private-key-rotation-policy: "Always" # 默认是永不改
spec:
ingressClassName: nginx
tls:
- hosts:
- hellonerd.miyunda.com
secretName: hellonerd-miyunda-com-tls-approle
rules:
- host: hellonerd.miyunda.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kuard
port:
number: 80
|
创建:
1
|
kubectl create -f ingress.yaml
|
可以看看它的信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
kubectl describe certificate hellonerd-miyunda-com-tls-approle -n <namespace>
Name: hellonerd-miyunda-com-tls-approle
Namespace: default
Labels: <none>
Annotations: <none>
API Version: cert-manager.io/v1
Kind: Certificate
Metadata:
Creation Timestamp: 2024-09-15T14:12:37Z
Generation: 1
Owner References:
API Version: networking.k8s.io/v1
Block Owner Deletion: true
Controller: true
Kind: Ingress
Name: kuard
UID: c273e1c4-68ca-48bf-bb86-775ed5e86d40
Resource Version: 187229
UID: 85bc79a6-bff5-469b-bee6-18568e45e14a
Spec:
Common Name: hellonerd.miyunda.com
Dns Names:
hellonerd.miyunda.com
Duration: 2160h0m0s
Issuer Ref:
Group: cert-manager.io
Kind: Issuer
Name: vault-dev-approle
Private Key:
Algorithm: ECDSA
Rotation Policy: Always
Size: 384
Renew Before: 720h0m0s
Secret Name: hellonerd-miyunda-com-tls-approle
Subject:
Countries:
CN
Localities:
Beijing
Organizational Units:
Marketing
Organizations:
Miyunda & Co Inc
Provinces:
Haidian
Xuanwu
Usages:
key agreement
digital signature
server auth
Status:
Conditions:
Last Transition Time: 2024-09-15T14:12:37Z
Message: Certificate is up to date and has not expired
Observed Generation: 1
Reason: Ready
Status: True
Type: Ready
Not After: 2024-12-14T13:31:50Z
Not Before: 2024-09-15T13:31:20Z
Renewal Time: 2024-11-14T13:31:50Z
Events: <none>
|
从minikube机器上去访问网站,注意观察打印出的服务器端证书信息:
1
2
3
4
5
|
curl -o my-ca.crt $VAULT_ADDR/v1/ca-root-x1/ca/pem
curl -ivL \
--cacert my-ca.crt \
--resolve hellonerd.miyunda.com:443:192.168.49.2 \
https://hellonerd.miyunda.com
|
㊟ 503 Service Temporarily Unavailable 错误是正常的,因为后面根本就没有服务,这里只看证书,别的不管。
好了,Kubernetes用AppRole验证获取Vault证书的介绍就这么多了。我们可以看到它配置起来很简单,但是它有个明显的缺点,就是secret id会过期,生产环境中很少有人使用永不过期的密码。一旦过期了,还得有人更新。
下一片文章我们将验证方式改为Kubernetes,看看能不能有完全不用人工操作的自动化证书管理。
看过了就等于学会了。 下次见~ 📅