package host import ( "context" "crypto/ed25519" "crypto/rand" "encoding/hex" "net" "net/http" "os/exec" "os/user" "strconv" "strings" "time" "github.com/carlosframework/platform/internal/hostbox" "github.com/carlosframework/platform/internal/instancectl" ) type StopControllerReader interface { VerifiedController(context.Context, int) (string, error) } func NewProductionClaimStopHandler(c ClaimStopCoordinator, j hostbox.StopKernelJournalReader, controllers StopControllerReader, roots ...map[string]string) (http.Handler, error) { if len(roots) != 1 || len(roots[0]) == 0 { return nil, ErrClaimStopUnavailable } if len(c.EvidenceSigner) != ed25519.PrivateKeySize || c.RequestLimit != hostbox.RequestLimit || c.Claims == nil || c.Inventory == nil || c.Evidence == nil || j == nil || controllers == nil { return nil, ErrClaimStopUnavailable } u, err := user.Lookup("carlos") if err != nil { return nil, err } uid, err := strconv.ParseUint(u.Uid, 10, 32) if err != nil || uid == 0 { return nil, ErrClaimStopIdentity } c.CarlosUID = uint32(uid) c.Now = time.Now c.NewID = func() string { var b [16]byte if _, err := rand.Read(b[:]); err != nil { return "" } return hex.EncodeToString(b[:]) } c.Kernel = newProductionStopKernel(j, roots[0], c.Guard.Root != nil) authenticate := func(ctx context.Context, conn net.Conn) (StopPeer, error) { ctx, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() out, err := exec.CommandContext(ctx, "systemctl", "show", "-p", "MainPID", "--value", "carlos-edge.service").Output() if err != nil { return StopPeer{}, err } pid, err := strconv.Atoi(strings.TrimSpace(string(out))) if err != nil || pid <= 0 { return StopPeer{}, ErrClaimStopIdentity } controller, err := controllers.VerifiedController(ctx, pid) if err != nil || controller == "" { return StopPeer{}, ErrClaimStopIdentity } peer, err := instancectl.AuthenticatePeerTuple(conn, uint32(uid), pid, controller) if err != nil { return StopPeer{}, err } return StopPeer{UID: peer.UID, PID: peer.PID, ProcessStart: peer.ProcessStart, BootID: peer.BootID, ControllerID: peer.ControllerID}, nil } return ClaimStopHTTP{Coordinator: c, Authenticate: authenticate}, nil }