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/sha256"
6 "encoding/hex"
7 "encoding/json"
8 "os"
9
10 "github.com/carlosframework/platform/internal/hostclaim"
11 "github.com/carlosframework/platform/internal/hostguard"
12 "github.com/carlosframework/platform/internal/provision"
13 "github.com/carlosframework/platform/internal/registry"
14 "github.com/carlosframework/platform/internal/release"
15 "github.com/carlosframework/platform/internal/rootparticipation"
16 "github.com/carlosframework/platform/internal/rootstate"
17)
18
19type rootHistoryAccess func(context.Context, func(*release.RootHistory) error) error
20
21func productionCreationHistory(ctx context.Context, effect func(*release.RootHistory) error) error {
22 legacy, err := legacyRootRestart()
23 if err != nil {
24 return err
25 }
26 if legacy {
27 return os.ErrPermission
28 }
29 return participationRelease.With(ctx, func(ctx context.Context) error {
30 s, err := rootstate.Open(release.RootHistoryDir, true, false)
31 if err != nil {
32 return err
33 }
34 defer s.Close()
35 return effect(&release.RootHistory{Store: s})
36 })
37}
38
39// Inventory additions do not change the identity of the installation.
40func rootHistoryInstallation(in hostguard.RootInstallation) string {
41 in.Artifacts = hostguard.InstallationArtifacts{}
42 in.Empty = false
43 in.InventoryRevision = 0
44 in.Registration = hostguard.InstallationRegistration{}
45 raw, _ := json.Marshal(in)
46 sum := sha256.Sum256(raw)
47 return hex.EncodeToString(sum[:])
48}
49
50func rootHistoryCreation(store release.Store) func(context.Context, registry.Route) (string, error) {
51 return func(ctx context.Context, rt registry.Route) (string, error) {
52 census, err := rootparticipation.Open()
53 if err != nil {
54 return "", err
55 }
56 defer census.State.Close()
57 state, err := rootstate.Open("/var/lib/carlos-claims/authority/fences", false, false)
58 if err != nil {
59 return "", err
60 }
61 defer state.Close()
62 return (rootRestartRequestSource{state: state, store: store, census: census.Census}).creation(ctx, rt)
63 }
64}
65
66func (s rootRestartRequestSource) creation(ctx context.Context, rt registry.Route) (string, error) {
67 in, err := s.installation(ctx, rt.Host)
68 if err != nil {
69 return "", err
70 }
71 if in.Host != rt.Host || in.Account != rt.Account || in.App != rt.App || in.Record != provision.RecordKey(in.Account, in.App, in.Host) {
72 return "", os.ErrPermission
73 }
74 rec, _, err := provision.GetRecordETag(ctx, s.store, in.Account, in.App, in.Host)
75 if err != nil {
76 return "", err
77 }
78 inc, err := hostclaim.Incarnation(rec.Account, rec.App, rec.Host, rec.CreatedAt)
79 if err != nil || inc != in.Incarnation {
80 return "", os.ErrPermission
81 }
82 return rootHistoryInstallation(in), nil
83}
84