Update TLS doc to use example signer for arbitrary https server

This commit is contained in:
Jordan Liggitt 2022-02-01 12:00:01 -05:00
parent 5313a873f2
commit 111c3eaabe
2 changed files with 145 additions and 27 deletions

View File

@ -76,16 +76,11 @@ cat <<EOF | cfssl genkey - | cfssljson -bare server
"192.0.2.24",
"10.0.34.2"
],
"CN": "system:node:my-pod.my-namespace.pod.cluster.local",
"CN": "my-pod.my-namespace.pod.cluster.local",
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"O": "system:nodes"
}
]
}
}
EOF
```
@ -93,13 +88,13 @@ EOF
Where `192.0.2.24` is the service's cluster IP,
`my-svc.my-namespace.svc.cluster.local` is the service's DNS name,
`10.0.34.2` is the pod's IP and `my-pod.my-namespace.pod.cluster.local`
is the pod's DNS name. You should see the following output:
is the pod's DNS name. You should see the output similar to:
```
2017/03/21 06:48:17 [INFO] generate received request
2017/03/21 06:48:17 [INFO] received CSR
2017/03/21 06:48:17 [INFO] generating key: ecdsa-256
2017/03/21 06:48:17 [INFO] encoded CSR
2022/02/01 11:45:32 [INFO] generate received request
2022/02/01 11:45:32 [INFO] received CSR
2022/02/01 11:45:32 [INFO] generating key: ecdsa-256
2022/02/01 11:45:32 [INFO] encoded CSR
```
This command generates two files; it generates `server.csr` containing the PEM
@ -120,7 +115,7 @@ metadata:
name: my-svc.my-namespace
spec:
request: $(cat server.csr | base64 | tr -d '\n')
signerName: kubernetes.io/kubelet-serving
signerName: example.com/serving
usages:
- digital signature
- key encipherment
@ -131,7 +126,7 @@ EOF
Notice that the `server.csr` file created in step 1 is base64 encoded
and stashed in the `.spec.request` field. We are also requesting a
certificate with the "digital signature", "key encipherment", and "server
auth" key usages, signed by the `kubernetes.io/kubelet-serving` signer.
auth" key usages, signed by an example `example.com/serving` signer.
A specific `signerName` must be requested.
View documentation for [supported signer names](/docs/reference/access-authn-authz/certificate-signing-requests/#signers)
for more information.
@ -147,14 +142,16 @@ kubectl describe csr my-svc.my-namespace
Name: my-svc.my-namespace
Labels: <none>
Annotations: <none>
CreationTimestamp: Tue, 21 Mar 2017 07:03:51 -0700
CreationTimestamp: Tue, 01 Feb 2022 11:49:15 -0500
Requesting User: yourname@example.com
Signer: example.com/serving
Status: Pending
Subject:
Common Name: my-svc.my-namespace.svc.cluster.local
Common Name: my-pod.my-namespace.pod.cluster.local
Serial Number:
Subject Alternative Names:
DNS Names: my-svc.my-namespace.svc.cluster.local
DNS Names: my-pod.my-namespace.pod.cluster.local
my-svc.my-namespace.svc.cluster.local
IP Addresses: 192.0.2.24
10.0.34.2
Events: <none>
@ -175,30 +172,136 @@ kubectl certificate approve my-svc.my-namespace
certificatesigningrequest.certificates.k8s.io/my-svc.my-namespace approved
```
## Download the Certificate and Use It
Once the CSR is signed and approved you should see the following:
You should now see the following:
```shell
kubectl get csr
```
```none
NAME AGE REQUESTOR CONDITION
my-svc.my-namespace 10m yourname@example.com Approved,Issued
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
my-svc.my-namespace 10m example.com/serving yourname@example.com <none> Approved
```
You can download the issued certificate and save it to a `server.crt` file
by running the following:
This means the certificate request has been approved and is waiting for the
requested signer to sign it.
## Sign the Certificate Signing Request
Next, you'll play the part of a certificate signer, issue the certificate, and upload it to the API.
A signer would typically watch the Certificate Signing Request API for objects with its `signerName`,
check that they have been approved, sign certificates for those requests,
and update the API object status with the issued certificate.
### Create a Certificate Authority
First, create a signing certificate by running the following:
```shell
cat <<EOF | cfssl gencert -initca - | cfssljson -bare ca
{
"CN": "My Example Signer",
"key": {
"algo": "rsa",
"size": 2048
}
}
EOF
```
You should see the output similar to:
```none
2022/02/01 11:50:39 [INFO] generating a new CA key and certificate from CSR
2022/02/01 11:50:39 [INFO] generate received request
2022/02/01 11:50:39 [INFO] received CSR
2022/02/01 11:50:39 [INFO] generating key: rsa-2048
2022/02/01 11:50:39 [INFO] encoded CSR
2022/02/01 11:50:39 [INFO] signed certificate with serial number 263983151013686720899716354349605500797834580472
```
This produces a certificate authority key file (`ca-key.pem`) and certificate (`ca.pem`).
### Issue a Certificate
{{< codenew file="tls/server-signing-config.json" >}}
Use a `server-signing-config.json` signing configuration and the certificate authority key file
and certificate to sign the certificate request:
```shell
kubectl get csr my-svc.my-namespace -o jsonpath='{.spec.request}' | \
base64 --decode | \
cfssl sign -ca ca.pem -ca-key ca-key.pem -config server-signing-config.json - | \
cfssljson -bare ca-signed-server
```
You should see the output similar to:
```
2022/02/01 11:52:26 [INFO] signed certificate with serial number 576048928624926584381415936700914530534472870337
```
This produces a signed serving certificate file, `ca-signed-server.pem`.
### Upload the Signed Certificate
Finally, populate the signed certificate in the API object's status:
```shell
kubectl get csr my-svc.my-namespace -o json | \
jq '.status.certificate = "'$(base64 ca-signed-server.pem | tr -d '\n')'"' | \
kubectl replace --raw /apis/certificates.k8s.io/v1/certificatesigningrequests/my-svc.my-namespace/status -f -
```
{{< note >}}
This uses the command line tool [jq](https://stedolan.github.io/jq/) to populate the base64-encoded content in the `.status.certificate` field.
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.
{{< /note >}}
Once the CSR is approved and the signed certificate is uploaded you should see the following:
```shell
kubectl get csr
```
```none
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
my-svc.my-namespace 20m example.com/serving yourname@example.com <none> Approved,Issued
```
## Download the Certificate and Use It
Now, as the requesting user, you can download the issued certificate
and save it to a `server.crt` file by running the following:
```shell
kubectl get csr my-svc.my-namespace -o jsonpath='{.status.certificate}' \
| base64 --decode > server.crt
```
Now you can use `server.crt` and `server-key.pem` as the keypair to start
your HTTPS server.
Now you can populate `server.crt` and `server-key.pem` in a secret and mount
it into a pod to use as the keypair to start your HTTPS server:
```shell
kubectl create secret tls server --cert server.crt --key server-key.pem
```
```none
secret/server created
```
Finally, you can populate `ca.pem` in a configmap and use it as the trust root
to verify the serving certificate:
```shell
kubectl create configmap example-serving-ca --from-file ca.crt=ca.pem
```
```none
configmap/example-serving-ca created
```
## Approving Certificate Signing Requests

View File

@ -0,0 +1,15 @@
{
"signing": {
"default": {
"usages": [
"digital signature",
"key encipherment",
"server auth"
],
"expiry": "876000h",
"ca_constraint": {
"is_ca": false
}
}
}
}