Skip to content

Support rotation of key used for encryption of secrets in connections. #2340

@alstanchev

Description

@alstanchev

The Ditto connectivity service encrypts sensitive connection fields (passwords, credentials, URIs) in MongoDB, but cannot rotate encryption keys safely. Changing the encryption key requires a long and cumbersome procedure.

Requirements

Must Have

  1. Dual-Key Configuration

    • Support current key (symmetrical-key) for encrypting new data
    • Support optional old key (old-symmetrical-key) for decrypting legacy data
    • Automatic fallback: try current key, then old key on decrypt
  2. DevOps Migration Commands

    • migrateEncryption - Start/resume batch re-encryption of persisted data
    • migrateEncryptionStatus - Query detailed migration progress
    • migrateEncryptionAbort - Stop migration with progress preservation
  3. Migration Features

    • Dry-run mode to preview impact
    • Resume capability for long-running migrations
    • Progress tracking (which connection, which document, timing)
    • Configurable throttling to control database load
  4. Encryption Disable Workflow

    • Support disabling encryption while preserving access to encrypted data
    • Migrate encrypted values back to plaintext

Non-Functional Requirements

  • Zero downtime (except for configuration restart)
  • No data loss during migration
  • Resumable after abort or failure

Proposed Solution

Configuration

ditto.connectivity.connection.encryption {
  encryption-enabled = true
  symmetrical-key = "current-key"      # Encrypts new data
  old-symmetrical-key = "legacy-key"   # Decrypts old data

  migration {
    batch-size = 100
    max-documents-per-minute = 100
  }
}

Encryption Logic

- Encrypt: Always use symmetrical-key
- Decrypt: Try symmetrical-key, fallback to old-symmetrical-key if decryption fails
- Migration: Explicit trigger by DevOps piggyback command

Migration API

Three piggyback commands:

1. Start/Resume Migration
{
  "targetActorSelection": "/user/connectivityRoot/encryptionMigration",
  "piggybackCommand": {
    "type": "connectivity.commands:migrateEncryption",
    "dryRun": false,
    "resume": false
  }
}

2. Query Status
{
  "targetActorSelection": "/user/connectivityRoot/encryptionMigration",
  "piggybackCommand": {
    "type": "connectivity.commands:migrateEncryptionStatus"
  }
}

Response includes:
- Current phase (snapshots, journal, completed, in_progress:*)
- Counters (processed, skipped, failed)
- Progress tracking (last processed pid, document ID)
- Timing (started, last updated)
- Active status

3. Abort Migration
{
  "targetActorSelection": "/user/connectivityRoot/encryptionMigration",
  "piggybackCommand": {
    "type": "connectivity.commands:migrateEncryptionAbort"
  }
}

Key Rotation Workflow

Standard Rotation

1. Generate new encryption key: openssl rand 32 | basenc --base64url
2. Update config: new key → symmetrical-key, old key → old-symmetrical-key
3. Restart connectivity service
4. Run dry-run: migrateEncryption with dryRun: true
5. Run migration: migrateEncryption with resume: false
6. Monitor: poll migrateEncryptionStatus
7. After completion, remove old-symmetrical-key
8. Restart service

Disable Encryption

1. Update config: encryption-enabled: false, current key → old-symmetrical-key
2. Restart service
3. Run migration (decrypts all values to plaintext)
4. Remove both keys from config
5. Restart service

Metadata

Metadata

Assignees

Projects

Status

No status

Relationships

None yet

Development

No branches or pull requests

Issue actions