Files
heliosian/tools/startserver/main.go
T

78 lines
2.2 KiB
Go

// Command startserver launches the app, waits for it to listen, prints the pid and an auth header, and leaves it running.
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"flag"
"fmt"
"log"
"os"
"os/exec"
"strings"
"time"
)
func main() {
email := flag.String("email", "ian.gulliver@heliosschool.org", "session email for the minted cookie")
flag.Parse()
key := os.Getenv("SESSION_KEY")
if key == "" {
log.Fatal("[ERROR] SESSION_KEY is required (the server and the minted cookie must share it)")
}
if os.Getenv("DIRECTORY_SHEET") == "" {
log.Fatal("[ERROR] DIRECTORY_SHEET is required")
}
logFile, err := os.Create("/tmp/heliosian-server.log")
if err != nil {
log.Fatalf("[ERROR] create server log: %v", err)
}
cmd := exec.Command("go", "run", ".")
cmd.Stdout = logFile
cmd.Stderr = logFile
if err := cmd.Start(); err != nil {
log.Fatalf("[ERROR] start server: %v", err)
}
deadline := time.Now().Add(10 * time.Minute)
for {
if time.Now().After(deadline) {
cmd.Process.Kill()
log.Fatalf("[ERROR] server did not start within 10 minutes; log: /tmp/heliosian-server.log")
}
content, err := os.ReadFile("/tmp/heliosian-server.log")
if err != nil {
log.Fatalf("[ERROR] read server log: %v", err)
}
if strings.Contains(string(content), "listening on ") {
break
}
if cmd.ProcessState != nil || !processAlive(cmd.Process.Pid) {
fmt.Print(string(content))
log.Fatal("[ERROR] server exited before listening")
}
time.Sleep(time.Second)
}
payload := fmt.Sprintf("%s|%d", *email, time.Now().Add(24*time.Hour).Unix())
mac := hmac.New(sha256.New, []byte(key))
mac.Write([]byte(payload))
cookie := base64.RawURLEncoding.EncodeToString([]byte(payload)) + "." +
base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
content, _ := os.ReadFile("/tmp/heliosian-server.log")
for _, line := range strings.Split(strings.TrimSpace(string(content)), "\n") {
fmt.Println(line)
}
fmt.Printf("pid: %d\n", cmd.Process.Pid)
fmt.Println("log: /tmp/heliosian-server.log")
fmt.Printf("header: Cookie: session=%s\n", cookie)
cmd.Process.Release()
}
func processAlive(pid int) bool {
return exec.Command("kill", "-0", fmt.Sprint(pid)).Run() == nil
}