diff --git a/README.md b/README.md index 6907898..327cbc6 100644 --- a/README.md +++ b/README.md @@ -386,19 +386,14 @@ authentication path This is indeed the root of the `0`th batch, and so this certificate is valid. -### Spin up an HTTP server with `mtcd` +### Run CA server -Run an HTTP server in the background to serve static files, accept queue -requests, periodically issue new batches of certificate, and serve issued -certificates. - -``` -$ go install github.com/bwesterb/mtc/cmd/mtcd@v0.1.2 -``` +Run an HTTP server to serve static files, accept queue requests, periodically +issue new batches of certificate, and serve issued certificates. Start the server. ``` -$ mtcd --listen-addr 8080 --ca-path . +$ mtc ca --ca-path . serve --listen-addr localhost:8080 ``` Get and inspect CA parameters. diff --git a/ca/ca.go b/ca/ca.go index e0e7b88..7df4d1f 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -648,7 +648,7 @@ func (h *Handle) Issue() error { } func (h *Handle) issue(dt time.Time) error { - slog.Info("Starting issuance", "time", dt) + slog.Info("Starting issuance", "time", dt.UTC()) expectedStored := h.params.StoredBatches(dt) expectedActive := h.params.ActiveBatches(dt) diff --git a/cmd/mtc/main.go b/cmd/mtc/main.go index 28f4138..a4b8974 100644 --- a/cmd/mtc/main.go +++ b/cmd/mtc/main.go @@ -395,6 +395,21 @@ func handleCaShowQueue(cc *cli.Context) error { return nil } +func handleCaServe(cc *cli.Context) error { + path := cc.String("ca-path") + listenAddr := cc.String("listen-addr") + if listenAddr == "" { + h, err := ca.Open(path) + if err != nil { + return err + } + listenAddr = h.Params().HttpServer + h.Close() + } + s := NewServer(path, listenAddr) + return s.Serve() +} + func handleCaNew(cc *cli.Context) error { if cc.Args().Len() != 2 { err := cli.ShowSubcommandHelp(cc) @@ -839,6 +854,17 @@ func main() { }, ), }, + { + Name: "serve", + Usage: "start CA server", + Action: handleCaServe, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "listen-addr", + Usage: "Address for the server to listen on, in the form 'host:port'", + }, + }, + }, }, }, { diff --git a/cmd/mtcd/main.go b/cmd/mtc/server.go similarity index 54% rename from cmd/mtcd/main.go rename to cmd/mtc/server.go index efdeacd..60a4679 100644 --- a/cmd/mtcd/main.go +++ b/cmd/mtc/server.go @@ -2,48 +2,37 @@ package main import ( "context" - "flag" "fmt" "log/slog" "os" "os/signal" - gopath "path" "syscall" "time" - "github.com/bwesterb/mtc" "github.com/bwesterb/mtc/ca" "github.com/bwesterb/mtc/http" "golang.org/x/sync/errgroup" ) -func main() { - var path, listenAddr string - - flag.StringVar(&path, "ca-path", ".", "the path to the CA state. Defaults to the current directory.") - flag.StringVar(&listenAddr, "listen-addr", "", "the TCP address for the server to listen on, in the form 'host:port'.") - flag.Parse() +type Server struct { + path string + listenAddr string +} - if listenAddr == "" { - var p mtc.CAParams - buf, err := os.ReadFile(gopath.Join(path, "www", "mtc", "v1", "ca-params")) - if err != nil { - slog.Error("failed to read ca-params", slog.Any("err", err)) - os.Exit(1) - } - if err := p.UnmarshalBinary(buf); err != nil { - slog.Error("failed to unmarshal ca-params", slog.Any("err", err)) - os.Exit(1) - } - listenAddr = p.HttpServer +func NewServer(path, listenAddr string) *Server { + return &Server{ + path: path, + listenAddr: listenAddr, } +} +func (s *Server) Serve() error { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill, syscall.SIGQUIT, syscall.SIGTERM) defer cancel() - srv := http.NewServer(path, listenAddr) + slog.Info("Starting server", slog.Any("listenAddr", s.listenAddr)) - slog.Info("starting mtcd") + srv := http.NewServer(s.path, s.listenAddr) g, ctx := errgroup.WithContext(ctx) @@ -64,25 +53,20 @@ func main() { }) g.Go(func() error { - h, err := ca.Open(path) - if err != nil { - slog.Error("could not start issuance loop", slog.Any("err", err)) - return nil - } - h.Close() - if err := issue(path, ctx); err != nil { + if err := issuanceLoop(s.path, ctx); err != nil { return fmt.Errorf("could not start issuance loop: %w", err) } return nil }) if err := g.Wait(); err != nil { - slog.Info("unexpected errgroup error, exiting", slog.Any("err", err)) - os.Exit(1) + return fmt.Errorf("unexpected errgroup error: %w", err) } + + return nil } -func issue(path string, ctx context.Context) error { +func issuanceLoop(path string, ctx context.Context) error { h, err := ca.Open(path) if err != nil { return err @@ -97,7 +81,7 @@ func issue(path string, ctx context.Context) error { batchTime := params.NextBatchAt(time.Now()) now := time.Now() if batchTime.After(now) { - slog.Info("Sleeping until next batch", slog.Any("at", batchTime.UTC())) + slog.Info("Sleeping until next batch is ready to issue", slog.Any("at", batchTime.UTC())) select { case <-ctx.Done(): return nil