package backup import ( "context" "testing" "gitea.hostxtra.co.uk/vantage/vantage-shared/cryptobox" "go.mongodb.org/mongo-driver/v2/bson" ) func TestVerifyMatchingKey(t *testing.T) { client, _ := testDB(t) archive := archiveOf(t, client, validKeyHex, false) rep, err := Verify(context.Background(), VerifyOptions{Archive: archive, KeyHex: validKeyHex}) if err != nil { t.Fatalf("Verify: %v", err) } if !rep.KeyMatchesArchive { t.Fatal("matching key reported as a mismatch") } if rep.ProbeAttempted { t.Fatal("probe ran with no client supplied") } if !rep.OK() { t.Fatalf("report not OK: %v", rep.Problems) } } func TestVerifyMismatchedKeyIsNotOK(t *testing.T) { client, _ := testDB(t) archive := archiveOf(t, client, validKeyHex, false) other := "0000000000000000000000000000000000000000000000000000000000000002" rep, err := Verify(context.Background(), VerifyOptions{Archive: archive, KeyHex: other}) if err != nil { t.Fatalf("Verify: %v", err) } if rep.KeyMatchesArchive { t.Fatal("mismatched key reported as matching") } if rep.OK() { t.Fatal("a mismatch must not report OK") } } func TestVerifyProbeDecryptsLiveCiphertext(t *testing.T) { client, dbName := testDB(t) ctx := context.Background() key, err := ParseKey(validKeyHex) if err != nil { t.Fatalf("ParseKey: %v", err) } sealed, err := cryptobox.Seal(key, "s3cret") if err != nil { t.Fatalf("Seal: %v", err) } if _, err := client.Database(dbName).Collection("secrets").InsertOne(ctx, bson.M{ "instance_id": "i1", "values": bson.M{"TOKEN": sealed}, }); err != nil { t.Fatalf("insert: %v", err) } path, _ := dumpToFile(t, DumpOptions{Client: client, Database: dbName, KeyHex: validKeyHex}) archive, err := Open(path) if err != nil { t.Fatalf("Open: %v", err) } defer archive.Close() rep, err := Verify(ctx, VerifyOptions{ Archive: archive, KeyHex: validKeyHex, Client: client, Database: dbName, }) if err != nil { t.Fatalf("Verify: %v", err) } if !rep.ProbeAttempted { t.Fatal("probe did not run with a client supplied") } if !rep.ProbeDecrypted { t.Fatalf("probe failed to decrypt live ciphertext: %v", rep.Problems) } if rep.ProbeCollection != "secrets" { t.Fatalf("probe collection %q, want secrets", rep.ProbeCollection) } if !rep.OK() { t.Fatalf("report not OK: %v", rep.Problems) } } func TestVerifyProbeFailsWithWrongKey(t *testing.T) { client, dbName := testDB(t) ctx := context.Background() key, err := ParseKey(validKeyHex) if err != nil { t.Fatalf("ParseKey: %v", err) } sealed, err := cryptobox.Seal(key, "s3cret") if err != nil { t.Fatalf("Seal: %v", err) } if _, err := client.Database(dbName).Collection("secrets").InsertOne(ctx, bson.M{ "values": bson.M{"TOKEN": sealed}, }); err != nil { t.Fatalf("insert: %v", err) } other := "0000000000000000000000000000000000000000000000000000000000000002" path, _ := dumpToFile(t, DumpOptions{Client: client, Database: dbName, KeyHex: other}) archive, err := Open(path) if err != nil { t.Fatalf("Open: %v", err) } defer archive.Close() rep, err := Verify(ctx, VerifyOptions{ Archive: archive, KeyHex: other, Client: client, Database: dbName, }) if err != nil { t.Fatalf("Verify: %v", err) } if rep.ProbeDecrypted { t.Fatal("probe decrypted with the wrong key") } if rep.OK() { t.Fatal("a failed probe must not report OK") } } func TestVerifyProbeAbsentCiphertextIsNotAFailure(t *testing.T) { client, dbName := testDB(t) seed(t, client, dbName) path, _ := dumpToFile(t, DumpOptions{Client: client, Database: dbName, KeyHex: validKeyHex}) archive, err := Open(path) if err != nil { t.Fatalf("Open: %v", err) } defer archive.Close() rep, err := Verify(context.Background(), VerifyOptions{ Archive: archive, KeyHex: validKeyHex, Client: client, Database: dbName, }) if err != nil { t.Fatalf("Verify: %v", err) } if rep.ProbeAttempted { t.Fatal("probe claims to have run against a database with no ciphertext") } if !rep.OK() { t.Fatalf("a database storing no secrets must still verify: %v", rep.Problems) } }