Skip to content

Commit

Permalink
backupccl: allow user to run SHOW BACKUP on an encrypted incremental …
Browse files Browse the repository at this point in the history
…backup

Previously, SHOW BACKUP <incremental_location> WITH kms='blah' (or with
encryption_passphrase) failed because the ENCRYPTION-INFO file is stored in the
full backup directory, not in the incremental directory. This patch adds the
encryption_info_dir param to SHOW BACKUP, which the user must set to the full
backup directory in order to view an incremental backup created with kms or an
encryption passphrase.

Fixes #77984

Release note (sql change): when the user runs SHOW BACKUP
on an encrypted incremental backup, they must set the encyrption_info_dir dir
to the full backup directory in order for SHOW BACKUP to work.
  • Loading branch information
msbutler committed Mar 17, 2022
1 parent 2562bd5 commit 4be9122
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 5 deletions.
1 change: 1 addition & 0 deletions pkg/ccl/backupccl/backup_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const (
localityURLParam = "COCKROACH_LOCALITY"
defaultLocalityValue = "default"
backupOptDebugMetadataSST = "debug_dump_metadata_sst"
backupOptEncDir = "encryption_info_dir"
)

type tableAndIndex struct {
Expand Down
8 changes: 8 additions & 0 deletions pkg/ccl/backupccl/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4770,6 +4770,11 @@ func TestEncryptedBackup(t *testing.T) {

sqlDB.Exec(t, fmt.Sprintf(`SHOW BACKUP $1 WITH %s`, encryptionOption), backupLoc1)

sqlDB.Exec(t, fmt.Sprintf(`SHOW BACKUP $1 WITH %s,encryption_info_dir='%s'`,
encryptionOption,
backupLoc1),
backupLoc1inc)

var expectedShowError string
if tc.useKMS {
expectedShowError = `one of the provided URIs was not used when encrypting the base BACKUP`
Expand All @@ -4784,6 +4789,9 @@ func TestEncryptedBackup(t *testing.T) {
sqlDB.ExpectErr(t, `could not find or read encryption information`,
fmt.Sprintf(`SHOW BACKUP $1 WITH %s`, encryptionOption), plainBackupLoc1)

sqlDB.ExpectErr(t, `If you are running SHOW BACKUP exclusively on an incremental backup`,
fmt.Sprintf(`SHOW BACKUP $1 WITH %s`, encryptionOption), backupLoc1inc)

sqlDB.Exec(t, fmt.Sprintf(`RESTORE DATABASE neverappears FROM ($1, $2), ($3, $4) WITH %s`,
encryptionOption), backupLoc1, backupLoc2, backupLoc1inc, backupLoc2inc)

Expand Down
9 changes: 6 additions & 3 deletions pkg/ccl/backupccl/manifest_handling.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ var writeMetadataSST = settings.RegisterBoolSetting(
"write experimental new format BACKUP metadata file",
true,
)
var errEncryptionInfoRead = errors.New(`ENCRYPTION-INFO not found`)

// isGZipped detects whether the given bytes represent GZipped data. This check
// is used rather than a standard implementation such as http.DetectContentType
Expand Down Expand Up @@ -1097,9 +1098,11 @@ func sanitizeLocalityKV(kv string) string {
func readEncryptionOptions(
ctx context.Context, src cloud.ExternalStorage,
) ([]jobspb.EncryptionInfo, error) {
const encryptionReadErrorMsg = `could not find or read encryption information`

files, err := getEncryptionInfoFiles(ctx, src)
if err != nil {
return nil, errors.Wrap(err, "could not find or read encryption information")
return nil, errors.Mark(errors.Wrap(err, encryptionReadErrorMsg), errEncryptionInfoRead)
}
var encInfo []jobspb.EncryptionInfo
// The user is more likely to pass in a KMS URI that was used to
Expand All @@ -1108,13 +1111,13 @@ func readEncryptionOptions(
for i := len(files) - 1; i >= 0; i-- {
r, err := src.ReadFile(ctx, files[i])
if err != nil {
return nil, errors.Wrap(err, "could not find or read encryption information")
return nil, errors.Wrap(err, encryptionReadErrorMsg)
}
defer r.Close(ctx)

encInfoBytes, err := ioctx.ReadAll(ctx, r)
if err != nil {
return nil, errors.Wrap(err, "could not find or read encryption information")
return nil, errors.Wrap(err, encryptionReadErrorMsg)
}
var currentEncInfo jobspb.EncryptionInfo
if err := protoutil.Unmarshal(encInfoBytes, &currentEncInfo); err != nil {
Expand Down
25 changes: 23 additions & 2 deletions pkg/ccl/backupccl/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ func showBackupPlanHook(
backupOptWithDebugIDs: sql.KVStringOptRequireNoValue,
backupOptIncStorage: sql.KVStringOptRequireValue,
backupOptDebugMetadataSST: sql.KVStringOptRequireNoValue,
backupOptEncDir: sql.KVStringOptRequireValue,
}
optsFn, err := p.TypeAsStringOpts(ctx, backup.Options, expected)
if err != nil {
Expand Down Expand Up @@ -324,9 +325,26 @@ func showBackupPlanHook(
}
defer store.Close()

// A user that calls SHOW BACKUP <incremental_dir> on an encrypted incremental
// backup will need to pass their full backup's directory to the
// encryption_info_dir parameter because the `ENCRYPTION-INFO` file
// necessary to decode the incremental backup lives in the full backup dir.
encStore := store
if encDir, ok := opts[backupOptEncDir]; ok {
encStore, err = p.ExecCfg().DistSQLSrv.ExternalStorageFromURI(ctx, encDir, p.User())
if err != nil {
return errors.Wrap(err, "make storage")
}
defer encStore.Close()
}
var encryption *jobspb.BackupEncryptionOptions
showEncErr := `If you are running SHOW BACKUP exclusively on an incremental backup,
you must pass the 'encryption_info_dir' parameter that points to the directory of your full backup`
if passphrase, ok := opts[backupOptEncPassphrase]; ok {
opts, err := readEncryptionOptions(ctx, store)
opts, err := readEncryptionOptions(ctx, encStore)
if errors.Is(err, errEncryptionInfoRead) {
return errors.WithHint(err, showEncErr)
}
if err != nil {
return err
}
Expand All @@ -336,7 +354,10 @@ func showBackupPlanHook(
Key: encryptionKey,
}
} else if kms, ok := opts[backupOptEncKMS]; ok {
opts, err := readEncryptionOptions(ctx, store)
opts, err := readEncryptionOptions(ctx, encStore)
if errors.Is(err, errEncryptionInfoRead) {
return errors.WithHint(err, showEncErr)
}
if err != nil {
return err
}
Expand Down

0 comments on commit 4be9122

Please sign in to comment.