Description / Requirements
Dgraph has the capability to perform binary backups. This is an Enterprise feature. This specification describes the feature to encrypt the backups and restore them. From a security perspective, this is a must-have feature for customers and will make Dgraph more appealing to them.
The requirements are:
- Support encryption on full and incremental backups.
- Support backups on Filesystem, Minio and AWS just as before.
- Use the encryption key configured with alpha for encrypting backups as well.
- Support AES-128, AES-192 and AES-256 which is driven by key with sizes 16, 24, or 32 bytes respectively. Use CTR mode.
- Enterprise feature.
- Continue to be supported from the same /admin HTTP and GraphQL endpoints
As of today, the backups/restores are in a Dgraph binary format but not encrypted. The backups can be stored in a filesystem, Minio or AWS bucket. See https://dgraph.io/docs/enterprise-features/#binary-backups
Building Blocks (Implementation Details)
New flag “Encrypted” in manifest.json
A new flag “Encrypted” is added to the manifest.json. This flag indicates if the corresponding binary backup is encrypted or not. To be backward compatible, if this flag is absent, it is presumed that the corresponding backup is not encrypted.
For a series of full and incremental backups, per the current design, we don’t allow mixing of encrypted and unencrypted backups. As a result, all the full and incremental backups must be all encrypted or not. This flag helps with checking this restriction.
NOTE: If a mismatch is found (e.g. latest backup is encrypted but current alpha is not configured with encryption or vice-versa), an error is thrown. The user must then force a full backup using the “forcefull” flag in the backup API to force a backup.
AES And Chaining with Gzip
If encryption is turned on an alpha, then we use the configured encryption key. The key size (16, 24, 32 bytes) determines AES-128/192/256 cipher chosen. We use the AES CTR mode. Currently, the binary backup is already gzipped. With encryption, we will encrypt the gzipped data.
The AES Cipher should use a random Initialization Vector (IV). This is a random sequence of 16 bytes. It must be unique but not a secret to obtain desirable security properties (See https://en.wikipedia.org/wiki/Initialization_vector ) . As a convention, the IV is inserted alongside the cipher text.
During backup, the 16 bytes IV is prepended to the Cipher-text data after encryption.
During restore, the first 16 bytes is read as the IV before decrypting the rest of the data.
Backup is an online tool, meaning it is available when alpha is running. For encrypted backups, the alpha must be configured with the “encryption-key-file”.
Note: encryption-key-file was used for encryption-at-rest and will now also be used for encrypted backups.
For encryption during backup, we chain writers as follows:
Plaintext Data → Gzip → AES Encryption → Handler to FileSystem/Minio/AWS → encrypted backup
Restore and New flag “keyfile” on the restore tool
The restore utility is a standalone tool today. Hence, a new flag “keyfile” is added to the restore utility so it can decrypt the backup. This keyfile must be the same key that was used for encryption during backup.
For decryption during restore, we chain readers as follows:
encrypted-backup → handler to FileSystem/Minio/AWS → AES Decryption → GUnzip → Plaintext Data
- Test with alpha with no encryption. Add some data. Create full and incremental backups. Verify restores work fine.
- Test with alpha with encryption turned on. Add some data. Create full and incremental backups. Verify restore works fine.
- Test backup with encryption and restore without key-file. This should fail.
- Test backup without encryption and restore with keyfile. This should fail.
- Test multiple groups and replicas in each group.
- Test with encrypted backup. Then try unencrypted “incremental” backup. This should fail.
- Same as above but this time try unencrypted “forcefull” full backup. This should pass.
- Test with unencrypted backup. Then try encrypted “incremental” backup. This should fail.
- Same as above but this time try encrypted “forcefull” full backup. This should pass.
- Try with 1M and 21M data set backup and restore with encryption
- Try backups on AWS, Minio and Filesystem
- Try with HTTP and GraphQL clients.