carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package release
2
3import (
4 "context"
5 "errors"
6 "strings"
7 "testing"
8 "time"
9)
10
11// Spec §8 "Evidence": a build promoted before the feature is accepted after
12// `carlos releases authorize`.
13func TestAuthorizeSignsTheShownDigest(t *testing.T) {
14 s := NewDirStore(t.TempDir())
15 ctx := context.Background()
16 priv, pub := testKeys(t)
17 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("one"))
18 plan, err := PlanAuthorize(ctx, s, "bab", "km", "v1")
19 if err != nil || plan.ManifestDigest != manifestDigestOf(t, s, "bab", "km", "v1") || plan.Artifacts[adoptPlatform].SHA256 == "" {
20 t.Fatalf("plan = %+v, %v", plan, err)
21 }
22 if _, err := ReadPromotionRecord(ctx, s, pub, "bab", "km", "v1"); !errors.Is(err, ErrNoPromotionRecord) {
23 t.Fatal("planning wrote a record")
24 }
25 already, err := RootSigner(priv).Authorize(ctx, s, plan, "ops@example.com")
26 if err != nil || already {
27 t.Fatalf("Authorize = %v, %v", already, err)
28 }
29 rec, err := ReadPromotionRecord(ctx, s, pub, "bab", "km", "v1")
30 if err != nil || !rec.Authorized || rec.Channel != "" {
31 t.Fatalf("record = %+v, %v", rec, err)
32 }
33 if _, err := AuthorizedManifest(ctx, s, pub, "bab", "km", "v1"); err != nil {
34 t.Fatal(err)
35 }
36}
37
38// Review Focus 3.
39func TestAuthorizeIsIdempotent(t *testing.T) {
40 s := NewDirStore(t.TempDir())
41 ctx := context.Background()
42 priv, _ := testKeys(t)
43 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("one"))
44 plan, _ := PlanAuthorize(ctx, s, "bab", "km", "v1")
45 if _, err := RootSigner(priv).Authorize(ctx, s, plan, "a"); err != nil {
46 t.Fatal(err)
47 }
48 already, err := RootSigner(priv).Authorize(ctx, s, plan, "a")
49 if err != nil || !already {
50 t.Fatalf("second authorize = %v, %v; want already", already, err)
51 }
52}
53
54func TestAuthorizeRefusesAManifestThatChanged(t *testing.T) {
55 s := NewDirStore(t.TempDir())
56 ctx := context.Background()
57 priv, _ := testKeys(t)
58 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("one"))
59 plan, _ := PlanAuthorize(ctx, s, "bab", "km", "v1")
60 if err := DeleteVersion(ctx, s, "bab", "km", "v1"); err != nil {
61 t.Fatal(err)
62 }
63 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("swapped"))
64 if _, err := RootSigner(priv).Authorize(ctx, s, plan, "a"); !errors.Is(err, ErrAuthorizeChanged) {
65 t.Fatalf("Authorize = %v; want ErrAuthorizeChanged", err)
66 }
67}
68
69func TestAuthorizeIsRootOnly(t *testing.T) {
70 s := NewDirStore(t.TempDir())
71 ctx := context.Background()
72 root, pub := testKeys(t)
73 seed, grant, _ := MintKeyGrant(root, "ci", []string{"canary"}, time.Hour)
74 key, _ := ParseSigningKey(seed, "test")
75 sg, err := ScopedSigner(key, grant, pub)
76 if err != nil {
77 t.Fatal(err)
78 }
79 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("one"))
80 plan, _ := PlanAuthorize(ctx, s, "bab", "km", "v1")
81 if _, err := sg.Authorize(ctx, s, plan, "ci"); !errors.Is(err, ErrAuthorizeRootOnly) {
82 t.Fatalf("scoped Authorize = %v; want ErrAuthorizeRootOnly", err)
83 }
84}
85
86func TestAuthorizeReportsAStoreFailureAsItself(t *testing.T) {
87 s := NewDirStore(t.TempDir())
88 ctx := context.Background()
89 priv, pub := testKeys(t)
90 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("one"))
91 plan, _ := PlanAuthorize(ctx, s, "bab", "km", "v1")
92
93 // Wrap the store to fail on manifest Get only
94 failStore := &failOnGetStore{Store: s, failKey: ManifestKey("bab", "km", "v1")}
95
96 // Authorize should report the failure, not ErrAuthorizeChanged
97 _, err := RootSigner(priv).Authorize(ctx, failStore, plan, "ops")
98 if err == nil {
99 t.Fatal("Authorize should fail when store Get fails")
100 }
101 if errors.Is(err, ErrAuthorizeChanged) {
102 t.Fatal("Authorize should NOT wrap store failure as ErrAuthorizeChanged")
103 }
104 if !strings.Contains(err.Error(), "bucket unreachable") {
105 t.Fatalf("error text should contain 'bucket unreachable', got: %v", err)
106 }
107
108 // Verify no record was written
109 _, err = ReadPromotionRecord(ctx, s, pub, "bab", "km", "v1")
110 if !errors.Is(err, ErrNoPromotionRecord) {
111 t.Fatalf("record should not exist, got: %v", err)
112 }
113}
114
115// failOnGetStore wraps a Store and returns an error for a specific key
116type failOnGetStore struct {
117 Store
118 failKey string
119}
120
121func (fs *failOnGetStore) Get(ctx context.Context, key string) ([]byte, string, error) {
122 if key == fs.failKey {
123 return nil, "", errors.New("bucket unreachable")
124 }
125 return fs.Store.Get(ctx, key)
126}
127