carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package objstore
2
3import (
4 "context"
5 "errors"
6 "os"
7 "strings"
8 "testing"
9 "time"
10
11 "github.com/carlosframework/platform/internal/release"
12)
13
14// enableScanning marks a provisioned store as scanned, the way the operator
15// grant door does.
16func enableScanning(t *testing.T, s release.Store, acct, app string) {
17 t.Helper()
18 ctx := context.Background()
19 rec, etag, err := Get(ctx, s, acct, app)
20 if err != nil || rec == nil {
21 t.Fatalf("re-read %s/%s: %+v, %v", acct, app, rec, err)
22 }
23 rec.Scanning = &ScanBlock{
24 Requested: &ScanRequested{At: time.Now().UTC(), By: "m@example.com"},
25 Enabled: &ScanEnabled{Engine: "clamav", At: time.Now().UTC(), By: "op@example.com"},
26 }
27 if _, err := Put(ctx, s, acct, app, rec, etag); err != nil {
28 t.Fatal(err)
29 }
30 // The DEPLOYMENT switch too. Absent record = not enabled, and every
31 // fixture that arms a scanner and expects a sweep needs both halves.
32 if av, _, err := release.GetAntivirus(ctx, s); err != nil {
33 t.Fatal(err)
34 } else if av == nil {
35 if _, err := release.PutAntivirus(ctx, s, &release.AntivirusSettings{
36 Enabled: true, Engine: "clamav", At: time.Now().UTC(), By: "test",
37 }, ""); err != nil {
38 t.Fatal(err)
39 }
40 }
41}
42
43// The scanner is released BEFORE the bucket goes, while the record naming it
44// still exists. A plan that outlives its bucket counts against a
45// non-adjustable per-region quota with nothing left pointing at it.
46func TestTeardownDisablesScannerBeforeDeletingBucket(t *testing.T) {
47 ctx := context.Background()
48 s := release.NewDirStore(t.TempDir())
49 _, pub := testSealKeypair(t)
50 p := NewMemProvisioner("eu-west-1")
51 rec := teardownFixture(t, s, pub, p)
52 bucket := rec.Provisioned.Bucket
53
54 sc := NewMemScanner()
55 if err := sc.EnsureEnabled(ctx, bucket); err != nil {
56 t.Fatal(err)
57 }
58 enableScanning(t, s, "bab", "titogo")
59
60 if err := Teardown(ctx, s, p, sc, "bab", "titogo"); err != nil {
61 t.Fatal(err)
62 }
63 if sc.IsEnabled(bucket) {
64 t.Fatal("teardown left the scanning engine enabled on a destroyed bucket")
65 }
66}
67
68// A teardown that cannot reach the engine must NOT go on to delete the record
69// — the record is the only thing naming what it failed to release. Same
70// posture as the nil-provisioner refusal.
71func TestTeardownRefusesNilScannerWhenEnabled(t *testing.T) {
72 ctx := context.Background()
73 s := release.NewDirStore(t.TempDir())
74 _, pub := testSealKeypair(t)
75 p := NewMemProvisioner("eu-west-1")
76 teardownFixture(t, s, pub, p)
77 enableScanning(t, s, "bab", "titogo")
78
79 err := Teardown(ctx, s, p, nil, "bab", "titogo")
80 if err == nil {
81 t.Fatal("teardown with a nil scanner over an enabled record must refuse")
82 }
83 if !strings.Contains(err.Error(), "CARLOS_STORE_SCANNER") {
84 t.Fatalf("the refusal must name the variable an operator can act on: %v", err)
85 }
86 // The refusal owes the record intact.
87 if rec, _, gerr := Get(ctx, s, "bab", "titogo"); gerr != nil || rec == nil {
88 t.Fatalf("a refused teardown destroyed the record: %+v, %v", rec, gerr)
89 }
90}
91
92// A store that never used scanning tears down with no scanner at all — which
93// is every store on a deployment that has not opted in.
94func TestTeardownAllowsNilScannerWhenNotEnabled(t *testing.T) {
95 ctx := context.Background()
96 s := release.NewDirStore(t.TempDir())
97 _, pub := testSealKeypair(t)
98 p := NewMemProvisioner("eu-west-1")
99 teardownFixture(t, s, pub, p)
100
101 if err := Teardown(ctx, s, p, nil, "bab", "titogo"); err != nil {
102 t.Fatalf("teardown of an unscanned store: %v", err)
103 }
104}
105
106// The sidecar goes with everything else. An orphan under a purged app's prefix
107// makes the app NAME unusable: the claim gate refuses a name whose prefix still
108// holds any key, and the box-side auto-purge never reaches it because the
109// tombstone is written last.
110func TestTeardownDeletesScanSidecar(t *testing.T) {
111 ctx := context.Background()
112 s := release.NewDirStore(t.TempDir())
113 _, pub := testSealKeypair(t)
114 p := NewMemProvisioner("eu-west-1")
115 teardownFixture(t, s, pub, p)
116
117 if _, err := PutSidecar(ctx, s, "bab", "titogo",
118 &ScanSidecar{LastComplete: &Sweep{Objects: 3, Scanned: 3, Engine: "clamav"}}, ""); err != nil {
119 t.Fatal(err)
120 }
121 if err := Teardown(ctx, s, p, NewMemScanner(), "bab", "titogo"); err != nil {
122 t.Fatal(err)
123 }
124 if _, _, err := s.Get(ctx, ScanKey("bab", "titogo")); !errors.Is(err, os.ErrNotExist) {
125 t.Fatalf("scan.json survived teardown: %v", err)
126 }
127}
128