Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
578 changes: 578 additions & 0 deletions content/en/docs/concepts/security/certificates.md

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions content/en/docs/concepts/storage/projected-volumes.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Currently, the following types of volume sources can be projected:
* [`configMap`](/docs/concepts/storage/volumes/#configmap)
* [`serviceAccountToken`](#serviceaccounttoken)
* [`clusterTrustBundle`](#clustertrustbundle)
* [`podCertificate`](#podcertificate)

All sources are required to be in the same namespace as the Pod. For more details,
see the [all-in-one volume](https://git.k8s.io/design-proposals-archive/node/all-in-one-volume.md) design document.
Expand Down Expand Up @@ -96,6 +97,60 @@ By default, the kubelet will prevent the pod from starting if the named ClusterT

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

## podCertificate projected volumes {#podcertificate}

{{< feature-state feature_gate_name="PodCertificateRequest" >}}

{{< note >}}
In Kubernetes {{< skew currentVersion >}}, you must enable support for Pod
Certificates using the `PodCertificateRequest` [feature
gate](/docs/reference/command-line-tools-reference/feature-gates/) and the
`--runtime-config=certificates.k8s.io/v1alpha1/podcertificaterequests=true`
kube-apiserver flag.
{{< /note >}}

The `podCertificate` projected volumes source securely provisions a private key
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `podCertificate` projected volumes source securely provisions a private key
The `podCertificate` projected volume source securely provisions a private key

and X.509 certificate chain for pod to use as client or server credentials.
Kubelet will then handle refreshing the private key and certificate chain when
they get close to expiration. The application just has to make sure that it
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
they get close to expiration. The application just has to make sure that it
they get close to expiration. The application needs to be able to react to these file changes

reloads the file promptly when it changes, with a mechanism like `inotify` or
polling.

Each `podCertificate` projection supports the following configuration fields:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using a Markdown description list here.

* `signerName`: The
[signer](/docs/reference/access-authn-authz/certificate-signing-requests#signers)
you want to issue the certificate. Note that signers may have their own
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
you want to issue the certificate. Note that signers may have their own
that you want to issue the certificate. Kubernetes signers may have their own
issuing conditions or

access requirements, and may refuse to issue certificates to your pod.
* `keyType`: The type of private key that should be generated. Valid values are
`ED25519`, `ECDSAP256`, `ECDSAP384`, `ECDSAP521`, `RSA3072`, and `RSA4096`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For beta, we should hyperlink to a reference doc that explains what each of these means. It's fairly obvious if you know X.509 and its evolution, but many people won't.

It'll get even more complex if we support post-quantum / hybrid post-quantum keying.

* `maxExpirationSeconds`: The maximum lifetime you will accept for the
certificate issued to the pod. If not set, will be defaulted to `86400` (24
hours). Must be at least `3600` (1 hour), and at most `7862400` (91 days).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention that the reserved Kubernetes signers have a max of 1 day?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (this was picked into the narrow-focused PR).

The signer is allowed to issue a certificate with a lifetime shorter than what
Copy link
Member

@lmktfy lmktfy Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) make "shorter" boldface


edited

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your comment is cut off

you've specified.
* `credentialBundlePath`: Relative path within the projection where the
credential bundle should be written. The credential bundle is a PEM-formatted
file, where the first block is a "PRIVATE KEY" block that contains a
PKCS#8-serialized private key, and the remaining blocks are "CERTIFICATE"
blocks that comprise the certificate chain (leaf certificate and any
intermediates).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Do we specify an order for the certs or expect the Pod to figure out the correct chain?
  • We should perhaps be explicit that the chain doesn't include its trust anchor cert.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's technically up to the signer, but we recommend that the certificates appear in leaf-to-root order. I can make this clear.

Comment on lines +132 to +136
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
credential bundle should be written. The credential bundle is a PEM-formatted
file, where the first block is a "PRIVATE KEY" block that contains a
PKCS#8-serialized private key, and the remaining blocks are "CERTIFICATE"
blocks that comprise the certificate chain (leaf certificate and any
intermediates).
_credential bundle_ should be written. The credential bundle is formatted as
PEM (as defined in IETC [RFC 7468](https://www.rfc-editor.org/rfc/rfc7468))
file, where the first block is a `PRIVATE KEY` block that contains a
[PKCS#8](https://www.rfc-editor.org/rfc/rfc5208)-serialized private key,
and the remaining blocks are `CERTIFICATE` blocks that comprise the certificate
chain (leaf certificate, and any intermediates).

* `keyPath` and `certificateChainPath`: Separate paths where Kubelet should
write *just* the private key or certificate chain.
Comment on lines +137 to +138
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `keyPath` and `certificateChainPath`: Separate paths where Kubelet should
write *just* the private key or certificate chain.
* `certificateChainPath`: Path, within the volume, where the kubelet should write
the certificate chain. The chain is written in PEM (RFC 7468) format.
* `keyPath`: Path, within the volume, where the kubelet should write the private key.
The private key is written in PEM (RFC 7468) format.


{{< note >}}

Most applications should prefer using `credentialBundlePath` unless they need
the key and certificates in separate files for compatibility reasons. Kubelet
uses an atomic writing strategy based on symlinks to make sure that when you
open the files it projects, you read either the old content or the new content.
However, if you read the key and certificate chain from separate files, Kubelet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit)

Suggested change
However, if you read the key and certificate chain from separate files, Kubelet
However, if any container in the Pod tries to reads the key and certificate chain from separate files, the kubelet

may rotate the credentials after your first read and before your second read,
resulting in your application loading a mismatched key and certificate.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
resulting in your application loading a mismatched key and certificate.
potentially resulting in your application loading a mismatched key and certificate.


{{< /note >}}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Introduce this code sample if feasible (explain what people are about to see).

{{% code_sample file="pods/storage/projected-podcertificate.yaml" %}}

## SecurityContext interactions

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.
Expand Down
10 changes: 5 additions & 5 deletions content/en/docs/reference/access-authn-authz/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ command line arguments, and use the configuration file instead.
# CAUTION: this is an example configuration.
# Do not use this for your own cluster!
#
apiVersion: apiserver.config.k8s.io/v1beta1
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
# list of authenticators to authenticate Kubernetes users using JWT compliant tokens.
# the maximum number of allowed authenticators is 64.
Expand Down Expand Up @@ -513,7 +513,7 @@ jwt:
{{< tabs name="example_configuration" >}}
{{% tab name="Valid token" %}}
```yaml
apiVersion: apiserver.config.k8s.io/v1beta1
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
jwt:
- issuer:
Expand Down Expand Up @@ -574,7 +574,7 @@ jwt:
{{% /tab %}}
{{% tab name="Fails claim validation" %}}
```yaml
apiVersion: apiserver.config.k8s.io/v1beta1
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
jwt:
- issuer:
Expand Down Expand Up @@ -625,7 +625,7 @@ jwt:
{{% /tab %}}
{{% tab name="Fails user validation" %}}
```yaml
apiVersion: apiserver.config.k8s.io/v1beta1
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
jwt:
- issuer:
Expand Down Expand Up @@ -1095,7 +1095,7 @@ A sample authentication configuration file is below:
# CAUTION: this is an example configuration.
# Do not use this for your own cluster!
#
apiVersion: apiserver.config.k8s.io/v1beta1
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
anonymous:
enabled: true
Expand Down
12 changes: 12 additions & 0 deletions content/en/docs/reference/access-authn-authz/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,23 @@ authorizers:
# Same as setting `--authorization-webhook-cache-authorized-ttl` flag
# Default: 5m0s
authorizedTTL: 30s
# If set to false, 'authorized' responses from the webhook are not cached
# and the specified authorizedTTL is ignored/has no effect.
# Same as setting `--authorization-webhook-cache-authorized-ttl` flag to `0`.
# Note: Setting authorizedTTL to `0` results in its default value being used.
# Default: true
cacheAuthorizedRequests: true
# The duration to cache 'unauthorized' responses from the webhook
# authorizer.
# Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
# Default: 30s
unauthorizedTTL: 30s
# If set to false, 'unauthorized' responses from the webhook are not cached
# and the specified unauthorizedTTL is ignored/has no effect.
# Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag to `0`.
# Note: Setting unauthorizedTTL to `0` results in its default value being used.
# Default: true
cacheUnauthorizedRequests: true
# Timeout for the webhook request
# Maximum allowed is 30s.
# Required, with no default.
Expand Down
Loading