From f104bd7d6bada668b4fbb95dacd415b108ee51c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Wei=C3=9Fe?= Date: Mon, 3 Feb 2025 13:42:54 +0100 Subject: [PATCH] rfc: add secure pv injection rfc --- rfc/009-secure-pv-injection.md | 82 ++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 rfc/009-secure-pv-injection.md diff --git a/rfc/009-secure-pv-injection.md b/rfc/009-secure-pv-injection.md new file mode 100644 index 0000000000..333fa5d48e --- /dev/null +++ b/rfc/009-secure-pv-injection.md @@ -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.