Skip to content

Commit 05b03c7

Browse files
authored
Merge pull request #31591 from liggitt/tls-example
Update TLS doc to use example signer for arbitrary https server
2 parents 5313a87 + 111c3ea commit 05b03c7

File tree

2 files changed

+143
-25
lines changed

2 files changed

+143
-25
lines changed

content/en/docs/tasks/tls/managing-tls-in-a-cluster.md

Lines changed: 128 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -76,30 +76,25 @@ cat <<EOF | cfssl genkey - | cfssljson -bare server
7676
"192.0.2.24",
7777
"10.0.34.2"
7878
],
79-
"CN": "system:node:my-pod.my-namespace.pod.cluster.local",
79+
"CN": "my-pod.my-namespace.pod.cluster.local",
8080
"key": {
8181
"algo": "ecdsa",
8282
"size": 256
83-
},
84-
"names": [
85-
{
86-
"O": "system:nodes"
87-
}
88-
]
83+
}
8984
}
9085
EOF
9186
```
9287

9388
Where `192.0.2.24` is the service's cluster IP,
9489
`my-svc.my-namespace.svc.cluster.local` is the service's DNS name,
9590
`10.0.34.2` is the pod's IP and `my-pod.my-namespace.pod.cluster.local`
96-
is the pod's DNS name. You should see the following output:
91+
is the pod's DNS name. You should see the output similar to:
9792

9893
```
99-
2017/03/21 06:48:17 [INFO] generate received request
100-
2017/03/21 06:48:17 [INFO] received CSR
101-
2017/03/21 06:48:17 [INFO] generating key: ecdsa-256
102-
2017/03/21 06:48:17 [INFO] encoded CSR
94+
2022/02/01 11:45:32 [INFO] generate received request
95+
2022/02/01 11:45:32 [INFO] received CSR
96+
2022/02/01 11:45:32 [INFO] generating key: ecdsa-256
97+
2022/02/01 11:45:32 [INFO] encoded CSR
10398
```
10499

105100
This command generates two files; it generates `server.csr` containing the PEM
@@ -120,7 +115,7 @@ metadata:
120115
name: my-svc.my-namespace
121116
spec:
122117
request: $(cat server.csr | base64 | tr -d '\n')
123-
signerName: kubernetes.io/kubelet-serving
118+
signerName: example.com/serving
124119
usages:
125120
- digital signature
126121
- key encipherment
@@ -131,7 +126,7 @@ EOF
131126
Notice that the `server.csr` file created in step 1 is base64 encoded
132127
and stashed in the `.spec.request` field. We are also requesting a
133128
certificate with the "digital signature", "key encipherment", and "server
134-
auth" key usages, signed by the `kubernetes.io/kubelet-serving` signer.
129+
auth" key usages, signed by an example `example.com/serving` signer.
135130
A specific `signerName` must be requested.
136131
View documentation for [supported signer names](/docs/reference/access-authn-authz/certificate-signing-requests/#signers)
137132
for more information.
@@ -147,14 +142,16 @@ kubectl describe csr my-svc.my-namespace
147142
Name: my-svc.my-namespace
148143
Labels: <none>
149144
Annotations: <none>
150-
CreationTimestamp: Tue, 21 Mar 2017 07:03:51 -0700
145+
CreationTimestamp: Tue, 01 Feb 2022 11:49:15 -0500
151146
Requesting User: [email protected]
147+
Signer: example.com/serving
152148
Status: Pending
153149
Subject:
154-
Common Name: my-svc.my-namespace.svc.cluster.local
150+
Common Name: my-pod.my-namespace.pod.cluster.local
155151
Serial Number:
156152
Subject Alternative Names:
157-
DNS Names: my-svc.my-namespace.svc.cluster.local
153+
DNS Names: my-pod.my-namespace.pod.cluster.local
154+
my-svc.my-namespace.svc.cluster.local
158155
IP Addresses: 192.0.2.24
159156
10.0.34.2
160157
Events: <none>
@@ -175,30 +172,136 @@ kubectl certificate approve my-svc.my-namespace
175172
certificatesigningrequest.certificates.k8s.io/my-svc.my-namespace approved
176173
```
177174

175+
You should now see the following:
178176

179-
## Download the Certificate and Use It
177+
```shell
178+
kubectl get csr
179+
```
180+
181+
```none
182+
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
183+
my-svc.my-namespace 10m example.com/serving [email protected] <none> Approved
184+
```
185+
186+
This means the certificate request has been approved and is waiting for the
187+
requested signer to sign it.
188+
189+
## Sign the Certificate Signing Request
190+
191+
Next, you'll play the part of a certificate signer, issue the certificate, and upload it to the API.
192+
193+
A signer would typically watch the Certificate Signing Request API for objects with its `signerName`,
194+
check that they have been approved, sign certificates for those requests,
195+
and update the API object status with the issued certificate.
196+
197+
### Create a Certificate Authority
198+
199+
First, create a signing certificate by running the following:
200+
201+
```shell
202+
cat <<EOF | cfssl gencert -initca - | cfssljson -bare ca
203+
{
204+
"CN": "My Example Signer",
205+
"key": {
206+
"algo": "rsa",
207+
"size": 2048
208+
}
209+
}
210+
EOF
211+
```
212+
213+
You should see the output similar to:
180214

181-
Once the CSR is signed and approved you should see the following:
215+
```none
216+
2022/02/01 11:50:39 [INFO] generating a new CA key and certificate from CSR
217+
2022/02/01 11:50:39 [INFO] generate received request
218+
2022/02/01 11:50:39 [INFO] received CSR
219+
2022/02/01 11:50:39 [INFO] generating key: rsa-2048
220+
2022/02/01 11:50:39 [INFO] encoded CSR
221+
2022/02/01 11:50:39 [INFO] signed certificate with serial number 263983151013686720899716354349605500797834580472
222+
```
223+
224+
This produces a certificate authority key file (`ca-key.pem`) and certificate (`ca.pem`).
225+
226+
### Issue a Certificate
227+
228+
{{< codenew file="tls/server-signing-config.json" >}}
229+
230+
Use a `server-signing-config.json` signing configuration and the certificate authority key file
231+
and certificate to sign the certificate request:
232+
233+
```shell
234+
kubectl get csr my-svc.my-namespace -o jsonpath='{.spec.request}' | \
235+
base64 --decode | \
236+
cfssl sign -ca ca.pem -ca-key ca-key.pem -config server-signing-config.json - | \
237+
cfssljson -bare ca-signed-server
238+
```
239+
240+
You should see the output similar to:
241+
242+
```
243+
2022/02/01 11:52:26 [INFO] signed certificate with serial number 576048928624926584381415936700914530534472870337
244+
```
245+
246+
This produces a signed serving certificate file, `ca-signed-server.pem`.
247+
248+
### Upload the Signed Certificate
249+
250+
Finally, populate the signed certificate in the API object's status:
251+
252+
```shell
253+
kubectl get csr my-svc.my-namespace -o json | \
254+
jq '.status.certificate = "'$(base64 ca-signed-server.pem | tr -d '\n')'"' | \
255+
kubectl replace --raw /apis/certificates.k8s.io/v1/certificatesigningrequests/my-svc.my-namespace/status -f -
256+
```
257+
258+
{{< note >}}
259+
This uses the command line tool [jq](https://stedolan.github.io/jq/) to populate the base64-encoded content in the `.status.certificate` field.
260+
If you do not have `jq`, you can also save the JSON output to a file, populate this field manually, and upload the resulting file.
261+
{{< /note >}}
262+
263+
Once the CSR is approved and the signed certificate is uploaded you should see the following:
182264

183265
```shell
184266
kubectl get csr
185267
```
186268

187269
```none
188-
NAME AGE REQUESTOR CONDITION
189-
my-svc.my-namespace 10m [email protected] Approved,Issued
270+
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
271+
my-svc.my-namespace 20m example.com/serving [email protected] <none> Approved,Issued
190272
```
191273

192-
You can download the issued certificate and save it to a `server.crt` file
193-
by running the following:
274+
## Download the Certificate and Use It
275+
276+
Now, as the requesting user, you can download the issued certificate
277+
and save it to a `server.crt` file by running the following:
194278

195279
```shell
196280
kubectl get csr my-svc.my-namespace -o jsonpath='{.status.certificate}' \
197281
| base64 --decode > server.crt
198282
```
199283

200-
Now you can use `server.crt` and `server-key.pem` as the keypair to start
201-
your HTTPS server.
284+
Now you can populate `server.crt` and `server-key.pem` in a secret and mount
285+
it into a pod to use as the keypair to start your HTTPS server:
286+
287+
```shell
288+
kubectl create secret tls server --cert server.crt --key server-key.pem
289+
```
290+
291+
```none
292+
secret/server created
293+
```
294+
295+
Finally, you can populate `ca.pem` in a configmap and use it as the trust root
296+
to verify the serving certificate:
297+
298+
```shell
299+
kubectl create configmap example-serving-ca --from-file ca.crt=ca.pem
300+
```
301+
302+
```none
303+
configmap/example-serving-ca created
304+
```
202305

203306
## Approving Certificate Signing Requests
204307

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"signing": {
3+
"default": {
4+
"usages": [
5+
"digital signature",
6+
"key encipherment",
7+
"server auth"
8+
],
9+
"expiry": "876000h",
10+
"ca_constraint": {
11+
"is_ca": false
12+
}
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)