Skip to content

Commit

Permalink
rfc: add secure pv injection rfc
Browse files Browse the repository at this point in the history
  • Loading branch information
davidweisse committed Feb 3, 2025
1 parent 097a266 commit f104bd7
Showing 1 changed file with 82 additions and 0 deletions.
82 changes: 82 additions & 0 deletions rfc/009-secure-pv-injection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# RFC 009: Secure PV Injection

## Objective

Setting up an encrypted volume mount using the `cryptsetup` container should be
automated during `contrast generate`. This can be done similar to injecting the
Initializer and Service Mesh components.

## Problem Statement

Contrast provides deployments with a shared workload secret which can be used to
setup an encrypted volume mount. This is useful for storing persistent sensitive
data (see [RFC 007](007-shared-workload-secret.md)). Currently, the process of
setting up an encrypted volume mount is by manually setting up an additional
init container running the `cryptsetup` subcommand of the Initializer as
described in the
[docs](https://docs.edgeless.systems/contrast/next/architecture/secrets). This
can be automated and made more user-friendly by automatically generating the
necessary YAML for the encrypted volume mount during `contrast generate`. This
includes a Persistent Volume Claim, an `EmptyDir` volume used for the shared
state, and the necessary volume mounts in the Initializer init container.

## Proposal

A new annotation `contrast.edgeless.systems/secure-pv-name` will be introduced
which specifies the name of the shared `EmptyDir` volume which will be used to
provide the decrypted state of the PV. If the annotation is set, this PV will
be used by the Initializer to setup an encrypted mount. To use the encrypted
volume, it needs to be mounted in the workload containers manually. The
annotation `contrast.edgeless.systems/secure-pv-size` can be used to specify the
size of the PV. If the annotation isn't set, the default size of 1Gi will be
used.

Currently, the Initializer uses the `cryptsetup` subcommand to setup an
encrypted volume. The container running the `cryptsetup` subcommand is running
separately from the Initializer container which attest to the Coordinator and
writes the Contrast secrets. Injecting the `cryptsetup` logic into the YAML, we
can simplify the process by:
- Running the `cryptsetup` subcommand in the same container as the Initializer
container.
- Deciding whether to quit the container after writing the secrets or to
continue with the `cryptsetup` and keep running.

In case the Initializer keeps running, we need a startup probe to check if the
`cryptsetup` is done. If the Initializer quits after writing the secrets, we can
skip the startup probe. The Initializer will decide whether to quit or to keep
running based on the environment variable `CRYPTSETUP_DEVICE` which will be set
if the corresponding annotation is set. By default, this argument is then set to
`/dev/csi0` and the Initializer will mount the PV to this device. The `EmptyDir`
volume specified by the `contrast.edgeless.systems/secure-pv-name` annotation
will be mounted to `/state` to complete the setup.

To summarize: if the `contrast.edgeless.systems/secure-pv-name` annotation is
set, the following changes will be made to the YAML:
- A PVC with the name `state` will be added to the resource with size specified
by `contrast.edgeless.systems/secure-pv-size` or 1Gi by default.
- An `EmptyDir` volume will be added to the resource with the specified name
from the annotation.
- The Initializer `securityContext` will be updated to `privileged` to allow
mounting block devices.
- The Initializer container will mount the `EmptyDir` volume to `/state` and the
PV to `/dev/csi0`.
- The Initializer environment variables will be updated to include
`CRYPTSETUP_DEVICE=/dev/csi0`.
- The Initializer will have a startup probe to check if the `cryptsetup` is
done, new resource limits as well as a restart policy of `Always`.

Skipping the `cryptsetup` injection can be done by skipping the Initializer
injection altogether. In this case, if a user wants to manually configure the
encrypted PV, all resources and volume mounts need to be created manually,
including the environment variables for the Initializer. If the Initializer is
skipped using the `contrast.edgeless.systems/skip-initializer` annotation or the
`--skip-initializer` flag, the `contrast.edgeless.systems/secure-pv-name`
annotation will be ignored. Skipping the `cryptsetup` injection by simply not
providing a `contrast.edgeless.systems/secure-pv-name` annotation won't work,
since the Initializer will be replaced on `contrast generate` and the
`CRYPTSETUP_DEVICE` environment variable won't be set.

With this change, there is no longer any need for the `cryptsetup` subcommand to
be specified through the `cobra` library, as everything now happens in one
container. The `cryptsetup` subcommand can be removed and replaced by internal
decision making in the Initializer.

0 comments on commit f104bd7

Please sign in to comment.