func TestDecrypt(t *testing.T) { tempdir, err := ioutil.TempDir("", "rafttool") require.NoError(t, err) defer os.RemoveAll(tempdir) kek := []byte("kek") dek := []byte("dek") unlockKey := encryption.HumanReadableKey(kek) // write a key to disk, else we won't be able to decrypt anything paths := certPaths(tempdir) krw := ca.NewKeyReadWriter(paths.Node, kek, manager.RaftDEKData{EncryptionKeys: raft.EncryptionKeys{CurrentDEK: dek}}) cert, key, err := testutils.CreateRootCertAndKey("not really a root, just need cert and key") require.NoError(t, err) require.NoError(t, krw.Write(cert, key, nil)) // create the encrypted v3 directory origSnapshot := raftpb.Snapshot{ Data: []byte("snapshot"), Metadata: raftpb.SnapshotMetadata{ Index: 1, Term: 1, }, } e, d := encryption.Defaults(dek) writeFakeRaftData(t, tempdir, &origSnapshot, storage.NewWALFactory(e, d), storage.NewSnapFactory(e, d)) outdir := filepath.Join(tempdir, "outdir") // if we use the wrong unlock key, we can't actually decrypt anything. The output directory won't get created. err = decryptRaftData(tempdir, outdir, "") require.IsType(t, ca.ErrInvalidKEK{}, err) require.False(t, fileutil.Exist(outdir)) // Using the right unlock key, we produce data that is unencrypted require.NoError(t, decryptRaftData(tempdir, outdir, unlockKey)) require.True(t, fileutil.Exist(outdir)) // The snapshot directory is readable by the regular snapshotter snapshot, err := storage.OriginalSnap.New(filepath.Join(outdir, "snap-decrypted")).Load() require.NoError(t, err) require.NotNil(t, snapshot) require.Equal(t, origSnapshot, *snapshot) // The wals are readable by the regular wal walreader, err := storage.OriginalWAL.Open(filepath.Join(outdir, "wal-decrypted"), walpb.Snapshot{Index: 1, Term: 1}) require.NoError(t, err) metadata, _, entries, err := walreader.ReadAll() require.NoError(t, err) require.Equal(t, []byte("v3metadata"), metadata) require.Len(t, entries, 5) }
func decryptRaftData(swarmdir, outdir, unlockKey string) error { krw, err := getKRW(swarmdir, unlockKey) if err != nil { return err } deks, err := getDEKData(krw) if err != nil { return err } _, d := encryption.Defaults(deks.CurrentDEK) if deks.PendingDEK == nil { _, d2 := encryption.Defaults(deks.PendingDEK) d = storage.MultiDecrypter{d, d2} } snapDir := filepath.Join(outdir, "snap-decrypted") if err := moveDirAside(snapDir); err != nil { return err } if err := storage.MigrateSnapshot( filepath.Join(swarmdir, "raft", "snap-v3-encrypted"), snapDir, storage.NewSnapFactory(encryption.NoopCrypter, d), storage.OriginalSnap); err != nil { return err } var walsnap walpb.Snapshot snap, err := storage.OriginalSnap.New(snapDir).Load() if err != nil && !os.IsNotExist(err) { return err } if snap != nil { walsnap.Index = snap.Metadata.Index walsnap.Term = snap.Metadata.Term } walDir := filepath.Join(outdir, "wal-decrypted") if err := moveDirAside(walDir); err != nil { return err } return storage.MigrateWALs(context.Background(), filepath.Join(swarmdir, "raft", "wal-v3-encrypted"), walDir, storage.NewWALFactory(encryption.NoopCrypter, d), storage.OriginalWAL, walsnap) }