Skip to content

Commit 61de463

Browse files
committed
Pod Certificates: User documentation
1 parent 48f8ce3 commit 61de463

File tree

2 files changed

+177
-1
lines changed

2 files changed

+177
-1
lines changed

content/en/docs/concepts/storage/projected-volumes.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,131 @@ By default, the kubelet will prevent the pod from starting if the named ClusterT
9696

9797
{{% code_sample file="pods/storage/projected-clustertrustbundle.yaml" %}}
9898

99+
## podCertificate projected volumes {#podcertificate}
100+
101+
{{< feature-state feature_gate_name="PodCertificateRequest" >}}
102+
103+
{{< note >}}
104+
In Kubernetes {{< skew currentVersion >}}, you must enable the
105+
`PodCertificateRequest` [feature
106+
gate](/docs/reference/command-line-tools-reference/feature-gates/) _and_ the
107+
`certificates.k8s.io/v1alpha1` {{< glossary_tooltip text="API group"
108+
term_id="api-group" >}} in order to use this API.
109+
{{< /note >}}
110+
111+
The `podCertificate` projected volumes source securely provisions a private key
112+
and X.509 certificate chain for pod to use as client or server credentials.
113+
Kubelet will then handle refreshing the private key and certificate chain when
114+
they get close to expiration. The application just has to make sure that it
115+
reloads the file promptly when it changes, with a mechanism like `inotify` or
116+
polling.
117+
118+
Each `podCertificate` projection supports the following configuration fields:
119+
* `signerName`: Which
120+
[signer](/docs/reference/access-authn-authz/certificate-signing-requests#ctb-signer-unlinked#signers)
121+
you want to issue the certificate. Note that signers may have their own
122+
access requirements, and may refuse to issue certificates to your pod.
123+
* `keyType`: The type of private key that should be generated. Valid values are
124+
`ED25519`, `ECDSAP256`, `ECDSAP384`, `ECDSAP521`, `RSA3072`, and `RSA4096`.
125+
* `maxExpirationSeconds`: What's the maximum lifetime you want for the
126+
certificate issued to the pod? If not set, will be defaulted to `86400` (24
127+
hours). Must be at least `3600` (1 hour), and at most `7862400` (91 days).
128+
* `credentialBundlePath`: Relative path within the projection where the
129+
credential bundle should be written. The credential bundle is a PEM-formatted
130+
file, where the first block is a "PRIVATE KEY" block that contains a
131+
PKCS#8-serialized private key, and the remaining blocks are "CERTIFICATE"
132+
blocks that comprise the certificate chain (leaf certificate and any
133+
intermediates).
134+
* `keyPath` and `certificateChainPath`: Separate paths where Kubelet should
135+
write *just* the private key or certificate chain.
136+
137+
{{< note >}}
138+
139+
Most applications should prefer using `credentialBundlePath` unless they need
140+
the key and certificates in separate files for compatibility reasons. Kubelet
141+
uses an atomic writing strategy based on symlinks to make sure that when you
142+
open the files it projects, you read either the old content or the new content.
143+
However, if you read the key and certificate chain from separate files, Kubelet
144+
may rotate the credentials after your first read and before your second read,
145+
resulting in your application loading a mismatched key and certificate.
146+
147+
{{< /note >}}
148+
149+
Under the hood, Kubelet will run the following state machine for each
150+
`podCertificate` projection:
151+
1. The projection starts out in `Initial` state.
152+
2. Kubelet generates a private key and holds it in memory.
153+
3. Kubelet creates a
154+
[PodCertificateRequest](/docs/reference/access-authn-authz/certificate-signing-requests#ctb-signer-unlinked#pod-certificate-requests)
155+
addressed to the requested signer. Kubelet then moves the projection into
156+
the `Wait` state.
157+
4. If the PodCertificateRequest is marked "Denied", move to the `Denied` state. This is
158+
a permanent error state, and the container(s) that mount this projection will
159+
fail to start.
160+
5. If the PodCertificateRequest is marked "Failed", move to the `Failed` state.
161+
This is a permanent error state, and the container(s) that mount this
162+
projection will fail to start.
163+
6. If the PodCertificate is marked "Issued", move to the `Fresh` state. Kubelet
164+
holds the private key and certificate chain in memory, and will periodically
165+
write them to the filesystem at the requested location. The container that
166+
mounts this projection will start up and run (assuming nothing else blocks
167+
its execution).
168+
7. The signer indicated an appropriate time to begin refreshing the certificate
169+
when it issued the PodCertificateRequest. Once that time has passed Kubelet
170+
will generate a new private key, create a new PodCertificateRequest, and move
171+
the projection into `WaitRefresh` state.
172+
8. If the PodCertificateRequest is marked "Denied", move to the `Denied` state.
173+
This is a permanent error state, and the container(s) will begin to get
174+
Kubelet volume remount errors.
175+
9. If the PodCertificateRequest is marked "Failed", move to the `Failed` state.
176+
This is a permanent error state, and the container(s) will begin to get
177+
Kubelet volume remount errors.
178+
10. If the PodCertificate is marked "Issued", move back to the `Fresh` state. The
179+
container(s) will continue to run, with the new private key and certificate
180+
chain written to the filesystem.
181+
182+
{{< mermaid >}}
183+
graph TB
184+
Initial --> Wait
185+
Wait --> Fresh
186+
Wait --> Failed
187+
Wait --> Denied
188+
Fresh --> WaitRefresh
189+
WaitRefresh --> Failed
190+
WaitRefresh --> Denied
191+
{{< /mermaid >}}
192+
Figure 1: Kubelet podCertificate lifecycle
193+
194+
Example Pod spec that generates an ED25519 private key, requests a certificate
195+
from the `coolcert.example.com/foo` signer, and writes the results to
196+
`/var/run/my-x509-credentials/coolcert.example.com/foo`:
197+
```yaml
198+
apiVersion: v1
199+
kind: Pod
200+
metadata:
201+
namespace: default
202+
name: podcertificate-pod
203+
spec:
204+
serviceAccountName: default
205+
containers:
206+
- image: debian
207+
name: main
208+
command: ["sleep", "infinity"]
209+
volumeMounts:
210+
- name: my-x509-credentials
211+
mountPath: /var/run/my-x509-credentials
212+
volumes:
213+
- name: my-x509-credentials
214+
projected:
215+
defaultMode: 420
216+
sources:
217+
- podCertificate:
218+
keyType: ED25519
219+
signerName: coolcert.example.com/foo
220+
credentialBundlePath: credentialbundle.pem
221+
```
222+
223+
99224
## SecurityContext interactions
100225
101226
The [proposal](https://git.k8s.io/enhancements/keps/sig-storage/2451-service-account-token-volumes#proposal) for file permission handling in projected service account volume enhancement introduced the projected files having the correct owner permissions set.

content/en/docs/reference/access-authn-authz/certificate-signing-requests.md

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,59 @@ To allow signing a CertificateSigningRequest:
105105

106106
{{% code_sample file="access/certificate-signing-request/clusterrole-sign.yaml" %}}
107107

108+
## PodCertificateRequests {#pod-certificate-requests}
108109

109-
## Signers
110+
{{< feature-state feature_gate_name="PodCertificateRequest" >}}
111+
112+
{{< note >}}
113+
In Kubernetes {{< skew currentVersion >}}, you must enable the `PodCertificateRequest`
114+
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
115+
_and_ the `certificates.k8s.io/v1alpha1`
116+
{{< glossary_tooltip text="API group" term_id="api-group" >}} in order to use
117+
this API.
118+
{{< /note >}}
119+
120+
Pod Certificates are a new mechanism to securely provision X.509 certificates
121+
into pods, with secure key generation, certificate provisioning, and certificate
122+
rotation handled by Kubelet. The application inside the pod only needs to know
123+
how to read the certificates from the filesystem.
124+
125+
### PodCertificate Projected Volume Sources {#pod-certificate-projection}
126+
127+
The main interface for using pod certificates is via the `podCertificate`
128+
projected volume source.
129+
130+
```yaml
131+
apiVersion: v1
132+
kind: Pod
133+
metadata:
134+
namespace: default
135+
name: podcertificate-pod
136+
spec:
137+
serviceAccountName: default
138+
containers:
139+
- image: debian
140+
name: main
141+
command: ["sleep", "infinity"]
142+
volumeMounts:
143+
- name: my-x509-credentials
144+
mountPath: /var/run/secrets/my-x509-credentials
145+
volumes:
146+
- name: my-x509-credentials
147+
projected:
148+
defaultMode: 420
149+
sources:
150+
- podCertificate:
151+
keyType: ECDSAP256
152+
signerName: coolcert.example.com/foo
153+
credentialBundlePath: credentialbundle.pem
154+
```
155+
156+
157+
158+
159+
160+
## Signers {#signers}
110161
111162
Signers abstractly represent the entity or entities that might sign, or have
112163
signed, a security certificate.

0 commit comments

Comments
 (0)