oficina / home Public

Clone
git clone https://amadan.net/oficina/home

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package provisioner
4
5import (
6 "archive/tar"
7 "bytes"
8 "context"
9 "filippo.io/age"
10 "os"
11 "path/filepath"
12 "testing"
13)
14
15func TestEncryptedBackupRestoreAndSurvivingFloor(t *testing.T) {
16 state, floor, backups := persistentDirectory(t), persistentDirectory(t), persistentDirectory(t)
17 password := []byte("synthetic backup password")
18 initial, e := Initialize(state, floor, password)
19 if e != nil {
20 t.Fatal(e)
21 }
22 j, e := existingJournal(state, floor, password)
23 if e != nil {
24 t.Fatal(e)
25 }
26 payload := []byte("PRIVATE-BACKUP-OWNER@example.invalid")
27 if _, e = j.append(context.Background(), testToken(5), testToken(6), "directory.seed-team", "empty", payload); e != nil {
28 t.Fatal(e)
29 }
30 closeExisting(j)
31 path := filepath.Join(backups, "current.age")
32 info, e := Backup(state, floor, path, password)
33 if e != nil || info.Sequence != 1 || len(info.Digest) != 64 {
34 t.Fatal("backup", e)
35 }
36 data, e := os.ReadFile(path)
37 if e != nil {
38 t.Fatal(e)
39 }
40 if bytes.Contains(data, payload) || bytes.Contains(data, []byte(initial.Registry)) {
41 t.Fatal("plaintext archive")
42 }
43 restored := persistentDirectory(t)
44 got, e := Restore(restored, floor, path, password)
45 if e != nil || got.Registry != initial.Registry || got.Sequence != 1 {
46 t.Fatal("restore", e)
47 }
48 j, e = existingJournal(restored, floor, password)
49 if e != nil {
50 t.Fatal(e)
51 }
52 if _, e = j.append(context.Background(), testToken(5), testToken(6), "directory.seed-team", "empty", payload); e != nil {
53 t.Fatal("restored private replay", e)
54 }
55 if _, e = j.append(context.Background(), testToken(5), testToken(7), "directory.activate-consumer", "pending", []byte("next private record")); e != nil {
56 t.Fatal(e)
57 }
58 closeExisting(j)
59 stale := persistentDirectory(t)
60 if _, e = Restore(stale, floor, path, password); e != ErrRefused {
61 t.Fatal("old archive accepted", e)
62 }
63 if _, e = Restore(persistentDirectory(t), floor, path, []byte("wrong")); e != ErrRefused {
64 t.Fatal("wrong archive password", e)
65 }
66 if _, e = Backup(restored, floor, path, password); e != ErrRefused {
67 t.Fatal("exclusive archive replaced", e)
68 }
69}
70
71func TestRestoreRefusesUnauthenticatedCompletionAndLinks(t *testing.T) {
72 state, floor, backups := persistentDirectory(t), persistentDirectory(t), persistentDirectory(t)
73 password := []byte("synthetic malformed archive")
74 if _, e := Initialize(state, floor, password); e != nil {
75 t.Fatal(e)
76 }
77 path := filepath.Join(backups, "good.age")
78 if _, e := Backup(state, floor, path, password); e != nil {
79 t.Fatal(e)
80 }
81 data, e := os.ReadFile(path)
82 if e != nil {
83 t.Fatal(e)
84 }
85 damaged := filepath.Join(backups, "truncated.age")
86 if e = os.WriteFile(damaged, data[:len(data)-10], 0600); e != nil {
87 t.Fatal(e)
88 }
89 target := persistentDirectory(t)
90 if _, e = Restore(target, floor, damaged, password); e != ErrRefused {
91 t.Fatal("truncated encrypted stream accepted", e)
92 }
93 if _, e = os.Stat(filepath.Join(target, "credential.age")); !os.IsNotExist(e) {
94 t.Fatal("unauthenticated archive published credentials")
95 }
96 recipient, e := age.NewScryptRecipient(string(password))
97 if e != nil {
98 t.Fatal(e)
99 }
100 var ciphertext bytes.Buffer
101 encrypted, e := age.Encrypt(&ciphertext, recipient)
102 if e != nil {
103 t.Fatal(e)
104 }
105 archive := tar.NewWriter(encrypted)
106 if e = archive.WriteHeader(&tar.Header{Name: "registry.db", Mode: 0600, Typeflag: tar.TypeSymlink, Linkname: "outside"}); e != nil {
107 t.Fatal(e)
108 }
109 if archive.Close() != nil || encrypted.Close() != nil {
110 t.Fatal("synthetic archive")
111 }
112 link := filepath.Join(backups, "link.age")
113 if e = os.WriteFile(link, ciphertext.Bytes(), 0600); e != nil {
114 t.Fatal(e)
115 }
116 if _, e = Restore(persistentDirectory(t), floor, link, password); e != ErrRefused {
117 t.Fatal("archive link accepted", e)
118 }
119}
120