Repository navigation
feat(s3): support SSE-C customer-provided keys - #284
Conversation
76e12b2 to
a300841
Compare
Surface the new `sseCustomerKey` field on `s3Credentials` through the ObjectStore CRD so users can enable Server-Side Encryption with Customer-provided keys (SSE-C). This is required by S3-compatible providers that only support SSE-C for encryption at rest, such as Hetzner Object Storage. The field flows through the embedded BarmanObjectStoreConfiguration from the barman-cloud library, so this change is limited to bumping the dependency, regenerating the CRD and the consolidated manifest, and documenting usage in the object stores guide. Depends on cloudnative-pg/barman-cloud#284 (temporarily pinned via a replace directive until that change is released). Closes cloudnative-pg#646 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Florian Schauer <florian@schauer.to>
|
FYI: barman release is out: https://github.com/EnterpriseDB/barman/releases/tag/release%2F3.20.0 |
|
Tested at
|
d097344 to
14f89b6
Compare
Surface the new `sseCustomerKey` field on `s3Credentials` through the ObjectStore CRD so users can enable Server-Side Encryption with Customer-provided keys (SSE-C). This is required by S3-compatible providers that only support SSE-C for encryption at rest, such as Hetzner Object Storage. The field flows through the embedded BarmanObjectStoreConfiguration from the barman-cloud library, so this change is limited to bumping the dependency, regenerating the CRD and the consolidated manifest, and documenting usage in the object stores guide. Depends on cloudnative-pg/barman-cloud#284 (temporarily pinned via a replace directive until that change is released). Closes cloudnative-pg#646 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Florian Schauer <florian@schauer.to>
|
Thanks for the test run and the validation change, @andrein — merged schaurian#1 into this branch. Updated the branch (
Full For the record, Barman 3.20.0 with |
Point the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that keeps each SSE-C key in its own file. A replica cluster archives WAL to its own object store while restoring it from the source one in the same sidecar, and with a single shared file each operation could run with the key of the other object store. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Also points the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that serializes the writes of the SSE-C key files. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Point the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that stops passing --sse-customer-key to barman-cloud-check-wal-archive. That command rejects the option, and it runs before the first WAL file is archived, so an object store with an SSE-C key could never start archiving. The SSE-C e2e test caught it. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
|
I pushed a few commits on top.
The same shared-file problem exists for the Google credentials, fixed separately in #309. |
ac9c5a9 to
c6e4b16
Compare
7b0cad0 to
9ee8eac
Compare
|
@schaurian @armru I also tested this PR locally and everything went fine. I would just like to ask if you guys see any security concern in not deleting the secret key files. As I understand, if sseCustomerKey is removed, points to another Secret, or the Secret is deleted, the old file remains there forever. |
|
@schaurian @gustabowill Any chance to merge this PR this week? Happy to be helping test this. |
A process can run barman-cloud commands for different object stores at the same time. For example, a replica cluster archives WAL to its own store and restores from the source one. All Google credentials went to one shared file, so a command could run with the identity of another store. A store using the GKE environment also emptied the file while other commands read it. Each secret key now has its own file, `/controller/.google-credentials/<secret>/<key>`, and `GOOGLE_APPLICATION_CREDENTIALS` points to it. The GKE environment no longer writes any file. Writes are serialized because `WriteFileAtomic` names its temporary file after the current second. Same problem as #284, for SSE-C keys. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com> Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com> Co-authored-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
|
Any updates here? Happy to help with testing as well if it helps speed this up. |
Add an `sseCustomerKey` field to the S3 credentials that references a secret holding a base64-encoded 256-bit AES key. When set, the key is materialized to a file and passed to every barman-cloud command through the `--sse-customer-key file://` option, enabling Server-Side Encryption with Customer-provided keys (SSE-C). This is required by S3-compatible providers that only support SSE-C for encryption at rest (e.g. Hetzner Object Storage). The option is injected in the shared `appendCloudProviderOptions` chokepoint, so it applies to all barman-cloud-* commands (backup, wal-archive, wal-restore, restore, backup-list, backup-delete, check-wal-archive), and is orthogonal to the existing bucket-managed `encryption` (SSE-S3/SSE-KMS) option. The key is materialized before the auth-method branching so it works with every authentication method, including inheritFromIAMRole. Requires a barman release that ships the `--sse-customer-key` option (EnterpriseDB/barman#973). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Florian Schauer <florian@schauer.to>
The barman-cloud commands refuse --sse-customer-key together with --encryption, so a configuration setting both fails on the first backup. Reject it at validation time instead, on the data and wal encryption fields. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Andrei Nistor <andrei@nistor.tech>
A single process can run barman-cloud commands for different object stores at the same time. A replica cluster, for instance, archives WAL to its own object store while restoring it from the source one. With one shared key file, each command overwrote or removed the key of the other: a missing file made the command fail, and a different key made barman-cloud upload objects encrypted with the key of another object store, which the configured key can no longer decrypt. Materialize each key in a file whose path depends on the referenced secret and key, and point the barman-cloud commands at that same path. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
The object stores sharing a key secret share its file, and a replica cluster can archive and restore WAL at the same time. WriteFileAtomic names its temporary file after the current second, so two concurrent writes of the same key could use the same temporary file: one of them could then fail its rename, or truncate the key file the other had just moved into place, making barman-cloud read an invalid key. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
The barman-cloud-check-wal-archive command is the only one without the --sse-customer-key option, and it rejects it. Since the check runs before the first WAL file is archived, an object store with an SSE-C key could never start archiving. The command only lists the objects in the bucket, so it does not need the key. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
The declaration of the mutex had split it from the function, so it documented the mutex instead. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
7f0d7a6 to
a1c4489
Compare
WriteFileAtomic uses a random temporary file name since machinery v0.6.1, so concurrent writes of the same key no longer collide. The mutex and its comment are obsolete. Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
@gustabowill We don't prune on purpose: a replica cluster uses two object stores in one process, and removing a file that looks unreferenced can delete the key another command is about to read. |
Surface the new `sseCustomerKey` field on `s3Credentials` through the ObjectStore CRD so users can enable Server-Side Encryption with Customer-provided keys (SSE-C). This is required by S3-compatible providers that only support SSE-C for encryption at rest, such as Hetzner Object Storage. The field flows through the embedded BarmanObjectStoreConfiguration from the barman-cloud library, so this change is limited to bumping the dependency, regenerating the CRD and the consolidated manifest, and documenting usage in the object stores guide. Depends on cloudnative-pg/barman-cloud#284 (temporarily pinned via a replace directive until that change is released). Closes cloudnative-pg#646 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Florian Schauer <florian@schauer.to>
Point the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that keeps each SSE-C key in its own file. A replica cluster archives WAL to its own object store while restoring it from the source one in the same sidecar, and with a single shared file each operation could run with the key of the other object store. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Point the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that stops passing --sse-customer-key to barman-cloud-check-wal-archive. That command rejects the option, and it runs before the first WAL file is archived, so an object store with an SSE-C key could never start archiving. The SSE-C e2e test caught it. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
d452ffb to
7e0a00e
Compare
Make the key directory a variable, as done for the Google credentials, so that tests can write the files to a temporary directory. Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
The description said every object is encrypted on upload and download, which is wrong for barman-cloud-check-wal-archive and reads as if downloads encrypt. Say what the key is for, and warn that changing it makes existing objects unreadable. Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
The operator and the plugin keep their own list of the secrets an instance can read, so a new credential field is silently left out and fails at run time with a forbidden error. Own the list next to the types, and fail the tests when a field is not listed. Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
7e0a00e to
dd2190d
Compare
The skip for UseDefaultAzureCredentials had no test, so dropping that operand from the condition went unnoticed. Also check that unset references are skipped when others are set. Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Point the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that stops passing --sse-customer-key to barman-cloud-check-wal-archive. That command rejects the option, and it runs before the first WAL file is archived, so an object store with an SSE-C key could never start archiving. The SSE-C e2e test caught it. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Rename reconcileAWSSSECustomerKey to writeAWSSSECustomerKey, as it only writes the file. Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Surface the new `sseCustomerKey` field on `s3Credentials` through the ObjectStore CRD so users can enable Server-Side Encryption with Customer-provided keys (SSE-C). This is required by S3-compatible providers that only support SSE-C for encryption at rest, such as Hetzner Object Storage. The field flows through the embedded BarmanObjectStoreConfiguration from the barman-cloud library, so this change is limited to bumping the dependency, regenerating the CRD and the consolidated manifest, and documenting usage in the object stores guide. Depends on cloudnative-pg/barman-cloud#284 (temporarily pinned via a replace directive until that change is released). Closes cloudnative-pg#646 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Florian Schauer <florian@schauer.to>
Point the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that keeps each SSE-C key in its own file. A replica cluster archives WAL to its own object store while restoring it from the source one in the same sidecar, and with a single shared file each operation could run with the key of the other object store. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Point the temporary barman-cloud replace at the head of cloudnative-pg/barman-cloud#284 that stops passing --sse-customer-key to barman-cloud-check-wal-archive. That command rejects the option, and it runs before the first WAL file is archived, so an object store with an SSE-C key could never start archiving. The SSE-C e2e test caught it. Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Add an optional
sseCustomerKeyfield toS3Credentials. It references a secret with a base64-encoded 256-bit AES key. S3-compatible stores such as Hetzner Object Storage and some Ceph setups only offer SSE-C, so the existing bucket-managedencryptionfield cannot be used there.The key is written to
/controller/.sse-customer-keys/<secret>/<key>before the auth method is handled, so it works with every auth method, includinginheritFromIAMRole. The path depends on the secret and key because one process can serve several object stores at once, for example a replica cluster archiving to its own store while restoring from the source one. A shared file would let a command pick up the wrong key. Key files are not removed when the field or the secret goes away. Changing the key makes existing objects unreadable, so a new key needs a newdestinationPathorserverName.The key is passed as
--sse-customer-key file://<path>to every barman-cloud command exceptbarman-cloud-check-wal-archive, which only lists objects and rejects the option.ValidateBackupConfigurationrejectssseCustomerKeytogether withdata.encryptionorwal.encryption, which barman-cloud refuses at run time.The credentials types now list the secrets they reference through
SecretNames(), with a test that fails when a new secret field is not listed. Consumers can use it to grant access to those secrets instead of keeping their own list.Requires Barman 3.20.0 or later. The plugin side is cloudnative-pg/plugin-barman-cloud#1017.
Refs cloudnative-pg/plugin-barman-cloud#646