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 "crypto/ed25519"
5 "crypto/rand"
6 "errors"
7 "reflect"
8 "testing"
9 "time"
10)
11
12func identityRelease(tag, router, console string) SystemRelease {
13 return SystemRelease{Version: tag, Source: "release:" + tag, ReleaseTag: tag, MovesProtocol: 1,
14 Artifacts: map[string]SystemArtifact{"linux-arm64": {Key: SystemArtifactKey(tag, "linux-arm64"), SHA256: router}},
15 ConsoleArtifacts: map[string]SystemArtifact{"linux-arm64": {Key: "bootstrap/console/" + tag + "/carlos-linux-arm64", SHA256: console}}}
16}
17
18// SignSystemIdentity is the trusted host's signer for a release identity.
19// Two signatures of one release are different bytes (promoted_at moves) but
20// the same Current, so PublishSystemIdentity takes the second as a no-op and
21// refuses a different release under the same tag.
22func TestSignSystemIdentityPublishesCreateOnly(t *testing.T) {
23 pub, key, _ := ed25519.GenerateKey(rand.Reader)
24 sg := RootSigner(key)
25 rel := identityRelease("v0.28.2", hexOf('a'), hexOf('b'))
26 first, err := SignSystemIdentity(sg, rel)
27 if err != nil {
28 t.Fatal(err)
29 }
30 p, err := VerifySystemIdentity(pub, first)
31 if err != nil {
32 t.Fatal(err)
33 }
34 if p.Component != SystemComponentRouter || p.Channel != "stable" || p.Spread != "0s" || len(p.History) != 0 || len(p.Audit) != 0 || !reflect.DeepEqual(p.Current, rel) {
35 t.Fatalf("identity %+v", p)
36 }
37 s := NewDirStore(t.TempDir())
38 ctx := t.Context()
39 if err = PublishSystemIdentity(ctx, s, pub, first); err != nil {
40 t.Fatal(err)
41 }
42 time.Sleep(1100 * time.Millisecond) // promoted_at has one-second resolution
43 second, err := SignSystemIdentity(sg, rel)
44 if err != nil {
45 t.Fatal(err)
46 }
47 if string(second) == string(first) {
48 t.Fatal("expected a fresh signature")
49 }
50 if err = PublishSystemIdentity(ctx, s, pub, second); err != nil {
51 t.Fatal("same release refused", err)
52 }
53 stored, _, err := s.Get(ctx, "control/system/router/releases/v0.28.2.json")
54 if err != nil || string(stored) != string(first) {
55 t.Fatal("create-only identity was replaced", err)
56 }
57 other, err := SignSystemIdentity(sg, identityRelease("v0.28.2", hexOf('a'), hexOf('c')))
58 if err != nil {
59 t.Fatal(err)
60 }
61 if err = PublishSystemIdentity(ctx, s, pub, other); !errors.Is(err, ErrCASConflict) {
62 t.Fatal("different release under the same tag accepted", err)
63 }
64}
65
66func TestSignSystemIdentityRefusesWhatGuardArmCannotUse(t *testing.T) {
67 _, key, _ := ed25519.GenerateKey(rand.Reader)
68 sg := RootSigner(key)
69 for name, mutate := range map[string]func(*SystemRelease){
70 "no tag": func(r *SystemRelease) { r.ReleaseTag = "" },
71 "build as tag": func(r *SystemRelease) { r.ReleaseTag = "26065378" },
72 "no protocol": func(r *SystemRelease) { r.MovesProtocol = 0 },
73 "bad router sha": func(r *SystemRelease) {
74 r.Artifacts["linux-arm64"] = SystemArtifact{Key: SystemArtifactKey(r.Version, "linux-arm64"), SHA256: "abc"}
75 },
76 "bad console key": func(r *SystemRelease) {
77 r.ConsoleArtifacts["linux-arm64"] = SystemArtifact{Key: "elsewhere", SHA256: hexOf('b')}
78 },
79 "no artifacts": func(r *SystemRelease) { r.Artifacts = nil },
80 } {
81 t.Run(name, func(t *testing.T) {
82 rel := identityRelease("v0.28.2", hexOf('a'), hexOf('b'))
83 mutate(&rel)
84 if _, err := SignSystemIdentity(sg, rel); err == nil {
85 t.Fatal("signed an identity guard-arm cannot use")
86 }
87 })
88 }
89 scoped := sg
90 scoped.scope = &Grant{}
91 if _, err := SignSystemIdentity(scoped, identityRelease("v0.28.2", hexOf('a'), hexOf('b'))); err == nil {
92 t.Fatal("scoped key signed an identity")
93 }
94}
95
96func hexOf(c byte) string {
97 b := make([]byte, 64)
98 for i := range b {
99 b[i] = c
100 }
101 return string(b)
102}
103