package host import ( "context" "crypto/sha256" "encoding/hex" "encoding/json" "os" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/hostguard" "github.com/carlosframework/platform/internal/provision" "github.com/carlosframework/platform/internal/registry" "github.com/carlosframework/platform/internal/release" "github.com/carlosframework/platform/internal/rootparticipation" "github.com/carlosframework/platform/internal/rootstate" ) type rootHistoryAccess func(context.Context, func(*release.RootHistory) error) error func productionCreationHistory(ctx context.Context, effect func(*release.RootHistory) error) error { legacy, err := legacyRootRestart() if err != nil { return err } if legacy { return os.ErrPermission } return participationRelease.With(ctx, func(ctx context.Context) error { s, err := rootstate.Open(release.RootHistoryDir, true, false) if err != nil { return err } defer s.Close() return effect(&release.RootHistory{Store: s}) }) } // Inventory additions do not change the identity of the installation. func rootHistoryInstallation(in hostguard.RootInstallation) string { in.Artifacts = hostguard.InstallationArtifacts{} in.Empty = false in.InventoryRevision = 0 in.Registration = hostguard.InstallationRegistration{} raw, _ := json.Marshal(in) sum := sha256.Sum256(raw) return hex.EncodeToString(sum[:]) } func rootHistoryCreation(store release.Store) func(context.Context, registry.Route) (string, error) { return func(ctx context.Context, rt registry.Route) (string, error) { census, err := rootparticipation.Open() if err != nil { return "", err } defer census.State.Close() state, err := rootstate.Open("/var/lib/carlos-claims/authority/fences", false, false) if err != nil { return "", err } defer state.Close() return (rootRestartRequestSource{state: state, store: store, census: census.Census}).creation(ctx, rt) } } func (s rootRestartRequestSource) creation(ctx context.Context, rt registry.Route) (string, error) { in, err := s.installation(ctx, rt.Host) if err != nil { return "", err } if in.Host != rt.Host || in.Account != rt.Account || in.App != rt.App || in.Record != provision.RecordKey(in.Account, in.App, in.Host) { return "", os.ErrPermission } rec, _, err := provision.GetRecordETag(ctx, s.store, in.Account, in.App, in.Host) if err != nil { return "", err } inc, err := hostclaim.Incarnation(rec.Account, rec.App, rec.Host, rec.CreatedAt) if err != nil || inc != in.Incarnation { return "", os.ErrPermission } return rootHistoryInstallation(in), nil }