Skip to content

Conversation

@ns-janandaram
Copy link

@ns-janandaram ns-janandaram commented Jan 13, 2026

Summary

  • Add support for encrypting GCS backup data using customer-supplied encryption keys (CSEK)
  • This provides encryption at rest where the user controls the encryption key, not Google
  • Encryption is transparent and works with all existing backup/restore operations including partial restores

Changes:

  • Add encryption_key config field to GCSConfig (GCS_ENCRYPTION_KEY env var)
  • Validate and decode base64 encryption key on connect (must be 256-bit / 32 bytes)
  • Apply encryption to all object operations: read, write, stat, copy
  • Update documentation with usage instructions

Usage:

gcs:
  bucket: "my-bucket"
  encryption_key: ""  # base64-encoded 256-bit key, generate with: openssl rand -base64 32

Or via environment variable:

export GCS_ENCRYPTION_KEY=$(openssl rand -base64 32)

See: https://cloud.google.com/storage/docs/encryption/customer-supplied-keys

Test plan

  • Configure GCS_ENCRYPTION_KEY with a valid 256-bit base64 key
  • Verify invalid keys (wrong size, invalid base64) are rejected on connect
  • Test clickhouse-backup create + upload - verify objects are encrypted in GCS
  • Test clickhouse-backup download + restore - verify decryption works
  • Test clickhouse-backup list remote - verify metadata is accessible
  • Test partial restore with --tables flag - verify single table restore works
  • Test without encryption key - verify backward compatibility (no encryption)

🤖 Generated with Claude Code

Copy link
Collaborator

@Slach Slach left a comment

Choose a reason for hiding this comment

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

good example for vibe-coding, thanks, but this is useless because it can't allow partial upload/download and will work slow for multi-terabyte backups, better try to modify pkg/storage/gcs.go and pkg/config/config.go to add support for GCS encryption keys

Add support for encrypting GCS backup data using customer-supplied
encryption keys (CSEK). This provides client-side encryption where
the encryption key is controlled by the user, not Google.

Changes:
- Add `encryption_key` config field to GCSConfig (GCS_ENCRYPTION_KEY env var)
- Validate and decode base64 encryption key on connect (must be 256-bit)
- Apply encryption to all object operations: read, write, stat, copy
- Update documentation with usage instructions

Usage:
  gcs:
    encryption_key: ""  # base64-encoded 256-bit key
                        # Generate with: openssl rand -base64 32

See: https://cloud.google.com/storage/docs/encryption/customer-supplied-keys

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@ns-janandaram ns-janandaram force-pushed the master branch 5 times, most recently from b0bbde9 to 929adfc Compare January 13, 2026 16:06
@ns-janandaram ns-janandaram changed the title feat: add custom encrypted GCS backup scripts feat: add GCS customer-supplied encryption key (CSEK) support Jan 13, 2026
@Slach
Copy link
Collaborator

Slach commented Jan 14, 2026

Looks much better. Thanks for contribution. Could you add separate test case TestGCSEncryptionKey in tests/integration/integratoin_test.go similar with TestGCS but use custom config like test/integration/config-gcs-encrypted.yml ?

ns-janandaram and others added 2 commits January 14, 2026 08:15
Add tests for GCS Customer-Supplied Encryption Key (CSEK) validation:
- TestGCSEncryptionKeyValidation: validates key length and base64 encoding
- TestGCSApplyEncryption: tests encryption application to object handles
- TestGCSEncryptionKeyDecoding: tests base64 key decoding

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add TestGCSEncryptionKey integration test that validates the CSEK
(Customer-Supplied Encryption Key) feature works end-to-end with
backup and restore operations.

- Add config-gcs-encrypted.yml with encryption_key from GCS_ENCRYPTION_KEY env var
- Add TestGCSEncryptionKey test function that skips if env var not set

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@ns-janandaram
Copy link
Author

Added integration test as requested:

  • TestGCSEncryptionKey in test/integration/integration_test.go
  • test/integration/config-gcs-encrypted.yml with encryption_key: ${GCS_ENCRYPTION_KEY}

The test skips if GCS_ENCRYPTION_KEY env var is not set, and runs the full integration scenario with encryption enabled when it is.

@ns-janandaram
Copy link
Author

Analysis of CI Test Failures

I've investigated the failing integration tests and found that the failures are not caused by the GCS encryption feature.

Key Findings:

  1. GCS tests are being skipped in CI due to missing credentials:

    --- SKIP: TestGCS (0.00s)
        integration_test.go:841: Skipping GCS integration tests...
    --- SKIP: TestGCSEncryptionKey (0.00s)
        integration_test.go:851: Skipping GCS integration tests...
    
  2. The failing tests are inconsistent across runs (indicating flaky tests):

    • First commit (929adfcb): Failed on Testflows (1.25, 23.3) and Test (1.25, 21.8)
    • Current commit (945401bd): Failed on Testflows (1.25, 22.3) and Test (1.25, 25.3)

    Different ClickHouse versions fail each time, which is characteristic of flaky tests rather than a deterministic bug.

  3. Known flaky test issues exist in this repository:

  4. Code review confirms correctness:

    • The applyEncryption() method properly returns the original object when no encryption key is configured
    • Unit tests for the GCS encryption feature all pass
    • The encryption key validation only runs when a key is explicitly provided

Recommendation:

The CI failures appear to be pre-existing flaky tests unrelated to the GCS encryption changes. A re-run of the failed jobs may resolve the issue.

@Slach
Copy link
Collaborator

Slach commented Jan 15, 2026

--- SKIP: TestGCS (0.00s)
integration_test.go:841: Skipping GCS integration tests...
--- SKIP: TestGCSEncryptionKey (0.00s)
integration_test.go:851: Skipping GCS integration tests...

yep, i missed these tests requires some secrets to properly pass CI/CD

@coveralls
Copy link

Pull Request Test Coverage Report for Build 21044602531

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 3 of 28 (10.71%) changed or added relevant lines in 1 file are covered.
  • 530 unchanged lines in 10 files lost coverage.
  • Overall coverage decreased (-1.8%) to 66.783%

Changes Missing Coverage Covered Lines Changed/Added Lines %
pkg/storage/gcs.go 3 28 10.71%
Files with Coverage Reduction New Missed Lines %
pkg/backup/restore.go 1 71.75%
cmd/clickhouse-backup/main.go 2 75.21%
pkg/storage/object_disk/object_disk.go 5 66.3%
pkg/config/config.go 8 72.64%
pkg/status/status.go 9 67.43%
pkg/backup/backuper.go 17 70.95%
pkg/storage/general.go 22 61.02%
pkg/storage/s3.go 23 47.39%
pkg/storage/gcs.go 181 0.93%
pkg/server/server.go 262 58.48%
Totals Coverage Status
Change from base Build 20658396934: -1.8%
Covered Lines: 10947
Relevant Lines: 16392

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants