carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "context"
5 "crypto/ed25519"
6 "crypto/sha256"
7 "debug/buildinfo"
8 "encoding/hex"
9 "io"
10 "os"
11 "time"
12
13 "github.com/carlosframework/platform/internal/registry"
14 "github.com/carlosframework/platform/internal/release"
15 "github.com/carlosframework/platform/internal/rootstate"
16)
17
18func openRootHistory(store release.Store, optDir string) (*release.RootHistoryPass, error) {
19 s, err := rootstate.Open(release.RootHistoryDir, true, false)
20 if err != nil {
21 return nil, err
22 }
23 source := productionProofBindingSource(store, systemdUnits{}, optDir)
24 h := boundRootHistory(&release.RootHistory{Store: s}, source.resolve, productionProofObserver(optDir))
25 h.Creation = rootHistoryCreation(store)
26 m := rootHistoryMaintenance{history: h.History, store: store, source: source,
27 checks: productionRootRestartChecks(systemdUnits{}, optDir), now: time.Now,
28 readback: func(ctx context.Context, b release.HistoryBinding, snapshot func(context.Context) (release.HistoryMigrationStatus, error)) error {
29 return publishRootHistoryReadback(ctx, store, b, snapshot)
30 },
31 pub: func() (ed25519.PublicKey, error) {
32 return release.ParsePublicKey(os.Getenv("CARLOS_RELEASE_PUBKEY"), "CARLOS_RELEASE_PUBKEY")
33 },
34 projection: func() (rootstate.Store, error) {
35 return rootstate.Open(release.RootHistoryStatusDir, true, true)
36 },
37 }
38 h.Reconstruct = m.run
39 return h, nil
40}
41
42func boundRootHistory(h *release.RootHistory, resolve proofBindingResolver, obs proofObserver) *release.RootHistoryPass {
43 return &release.RootHistoryPass{History: h,
44 Resolve: func(ctx context.Context, rt registry.Route) (release.HistoryBinding, string, error) {
45 if resolve == nil {
46 return release.HistoryBinding{}, "", os.ErrPermission
47 }
48 b, err := resolve(ctx, rt)
49 if err != nil {
50 return release.HistoryBinding{}, "", err
51 }
52 if rt.Channel != b.Route.Channel {
53 return release.HistoryBinding{}, "", os.ErrPermission
54 }
55 return release.HistoryBinding{Host: b.Route.Host, Account: b.Route.Account, App: b.Route.App}, b.Source, nil
56 },
57 Installed: func(ctx context.Context, rt registry.Route, version string) (string, error) {
58 if err := ctx.Err(); err != nil {
59 return "", err
60 }
61 b, err := obs.observe(rt, 0)
62 if err != nil {
63 return "", err
64 }
65 if b.Version != version || b.binding.Version != version || b.binding.Digest != b.SHA256 || obs.procExe == nil {
66 return "", os.ErrPermission
67 }
68 f, err := os.Open(obs.procExe(b.pid))
69 if err != nil {
70 return "", err
71 }
72 defer f.Close()
73 digest := sha256.New()
74 if _, err := io.Copy(digest, f); err != nil {
75 return "", err
76 }
77 if hex.EncodeToString(digest.Sum(nil)) != b.SHA256 {
78 return "", os.ErrPermission
79 }
80 program := ""
81 if info, err := buildinfo.Read(f); err == nil {
82 program = info.Path
83 }
84 again, err := obs.observe(rt, 0)
85 if err != nil || again.SHA256 != b.SHA256 || again.Version != b.Version || again.binding.Source != b.binding.Source || again.pid != b.pid || again.start != b.start || again.invocation != b.invocation {
86 return "", os.ErrPermission
87 }
88 return program, nil
89 },
90 }
91}
92
93func recordRootProgram(h *release.RootHistoryPass, b liveBuild) error {
94 ctx := context.Background()
95 binding, source, err := h.Resolve(ctx, b.binding.Route)
96 if err != nil {
97 return err
98 }
99 if source != b.binding.Source {
100 return os.ErrPermission
101 }
102 program, err := h.Installed(ctx, b.binding.Route, b.Version)
103 if err != nil {
104 return err
105 }
106 again, revision, err := h.Resolve(ctx, b.binding.Route)
107 if err != nil || again != binding || revision != source {
108 return os.ErrPermission
109 }
110 return h.History.RecordInstalledProgram(binding, program)
111}
112