mirror of
https://github.com/cloudflare/redoctober.git
synced 2025-12-23 06:15:45 +00:00
156 lines
4.4 KiB
Go
156 lines
4.4 KiB
Go
// Copyright (c) 2013 CloudFlare, Inc.
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/cloudflare/redoctober/config"
|
|
"github.com/cloudflare/redoctober/core"
|
|
"github.com/cloudflare/redoctober/report"
|
|
"github.com/cloudflare/redoctober/server"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
)
|
|
|
|
// initPrometheus starts a goroutine with a Prometheus listener that
|
|
// listens on localhost:metricsPort. If the Prometheus handler can't
|
|
// be started, a log.Fatal call is made.
|
|
func initPrometheus() {
|
|
srv := &http.Server{
|
|
Addr: net.JoinHostPort(cfg.Metrics.Host, cfg.Metrics.Port),
|
|
Handler: promhttp.Handler(),
|
|
}
|
|
|
|
log.Printf("metrics.init start: addr=%s", srv.Addr)
|
|
go func() {
|
|
err := srv.ListenAndServe()
|
|
report.Check(err, nil)
|
|
log.Fatal(err.Error())
|
|
}()
|
|
}
|
|
|
|
const usage = `Usage:
|
|
|
|
redoctober -static <path> -vaultpath <path> -addr <addr> -certs <path1>[,<path2>,...] -keys <path1>[,<path2>,...] [-ca <path>]
|
|
|
|
single-cert example:
|
|
redoctober -vaultpath diskrecord.json -addr localhost:8080 -certs cert.pem -keys cert.key
|
|
multi-cert example:
|
|
redoctober -vaultpath diskrecord.json -addr localhost:8080 -certs cert1.pem,cert2.pem -keys cert1.key,cert2.key
|
|
`
|
|
|
|
var (
|
|
cfg, cli *config.Config
|
|
confFile string
|
|
vaultPath string
|
|
)
|
|
|
|
const (
|
|
defaultAddr = "localhost:8080"
|
|
defaultMetricsHost = "localhost"
|
|
defaultMetricsPort = "8081"
|
|
)
|
|
|
|
func registerCli() {
|
|
// cli contains the configuration set by the command line
|
|
// options, and cfg is the actual Red October config.
|
|
cli = config.New()
|
|
cfg = config.New()
|
|
|
|
// customized the default index html with auto generated content
|
|
server.DefaultIndexHTML = indexHTML
|
|
|
|
cli.Server.Addr = defaultAddr
|
|
cli.Metrics.Host = defaultMetricsHost
|
|
cli.Metrics.Port = defaultMetricsPort
|
|
|
|
flag.Usage = func() {
|
|
fmt.Fprint(os.Stderr, "main usage dump\n")
|
|
fmt.Fprint(os.Stderr, usage)
|
|
flag.PrintDefaults()
|
|
os.Exit(2)
|
|
}
|
|
|
|
flag.StringVar(&confFile, "f", "", "path to config file")
|
|
flag.StringVar(&cli.Server.Addr, "addr", cli.Server.Addr,
|
|
"Server and port separated by :")
|
|
flag.StringVar(&cli.Server.CAPath, "ca", cli.Server.CAPath,
|
|
"Path of TLS CA for client authentication (optional)")
|
|
flag.StringVar(&cli.Server.CertPaths, "certs", cli.Server.CertPaths,
|
|
"Path(s) of TLS certificate in PEM format, comma-separated")
|
|
flag.StringVar(&cli.HipChat.Host, "hchost", cli.HipChat.Host,
|
|
"Hipchat Url Base (ex: hipchat.com)")
|
|
flag.StringVar(&cli.HipChat.APIKey, "hckey", cli.HipChat.APIKey,
|
|
"Hipchat API Key")
|
|
flag.StringVar(&cli.HipChat.Room, "hcroom", cli.HipChat.Room,
|
|
"Hipchat Room ID")
|
|
flag.StringVar(&cli.Server.KeyPaths, "keys", cli.Server.KeyPaths,
|
|
"Comma-separated list of PEM-encoded TLS private keys in the same order as certs")
|
|
flag.StringVar(&cli.Metrics.Host, "metrics-host", cli.Metrics.Host,
|
|
"The `host` the metrics endpoint should listen on.")
|
|
flag.StringVar(&cli.Metrics.Port, "metrics-port", cli.Metrics.Port,
|
|
"The `port` the metrics endpoint should listen on.")
|
|
flag.StringVar(&cli.UI.Root, "rohost", cli.UI.Root, "RedOctober URL Base (ex: localhost:8080)")
|
|
flag.StringVar(&cli.UI.Static, "static", cli.UI.Static,
|
|
"Path to override built-in index.html")
|
|
flag.BoolVar(&cli.Server.Systemd, "systemdfds", cli.Server.Systemd,
|
|
"Use systemd socket activation to listen on a file. Useful for binding privileged sockets.")
|
|
flag.StringVar(&vaultPath, "vaultpath", "diskrecord.json", "Path to the the disk vault")
|
|
|
|
flag.Parse()
|
|
}
|
|
|
|
//go:generate go run generate.go
|
|
|
|
func main() {
|
|
registerCli()
|
|
var err error
|
|
if confFile != "" {
|
|
cfg, err = config.Load(confFile)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
} else {
|
|
cfg = cli
|
|
}
|
|
|
|
report.Init(cfg)
|
|
|
|
if vaultPath == "" || !cfg.Valid() {
|
|
if !cfg.Valid() {
|
|
fmt.Fprintf(os.Stderr, "Invalid config.\n")
|
|
}
|
|
fmt.Fprint(os.Stderr, usage)
|
|
flag.PrintDefaults()
|
|
os.Exit(2)
|
|
}
|
|
|
|
if err := core.Init(vaultPath, cfg); err != nil {
|
|
report.Check(err, nil)
|
|
log.Fatal(err)
|
|
}
|
|
|
|
initPrometheus()
|
|
cpaths := strings.Split(cfg.Server.CertPaths, ",")
|
|
kpaths := strings.Split(cfg.Server.KeyPaths, ",")
|
|
s, l, err := server.NewServer(cfg.UI.Static, cfg.Server.Addr, cfg.Server.CAPath,
|
|
cpaths, kpaths, cfg.Server.Systemd)
|
|
if err != nil {
|
|
report.Check(err, nil)
|
|
log.Fatalf("Error starting redoctober server: %s\n", err)
|
|
}
|
|
|
|
log.Printf("http.serve start: addr=%s", cfg.Server.Addr)
|
|
report.Recover(func() {
|
|
err := s.Serve(l)
|
|
report.Check(err, nil)
|
|
log.Fatal(err.Error())
|
|
})
|
|
}
|