authentricity/internal/webui/main.go

97 lines
2.9 KiB
Go

package webui
import (
"log"
"net"
"net/http"
"os"
"github.com/coreos/go-systemd/v22/activation"
"github.com/google/uuid"
"github.com/kelseyhightower/envconfig"
"go.e43.eu/authentricity/internal/store"
"go.uber.org/zap"
)
type Config struct {
Debug bool `default:"false" description:"Enable debug logging"`
ListenType string `envconfig:"listen_type" default:"tcp" description:"Type of socket to listen on (Go 'net.Listen()' network)"`
ListenAddress string `envconfig:"listen_address" default:":8700" description:"Address to listen on (Go 'net.Listen()' address)"`
SecretsDir string `envconfig:"secrets_dir" default:"/var/lib/authentricity/webui/secrets" description:"Directory in which to store secrets"`
TokenCookie string `envconfig:"token_cookie" default:"authentricity_token" description:"Cookie in which to store authentication token"`
AdminGroupID uuid.UUID `envconfig:"admin_group_id" required:"true" description:"UUID of administrator group"`
CookieDomain string `envconfig:"cookie_domain" default:"" description:"Domain to use when setting token cookie - customize to do cross-domain cookie based SSO"`
NoHTTPS bool `envconfig:"no_https" default:"false" description:"Allow access over insecure HTTP. For development only"`
WebAuthnOrigin string `envconfig:"webauthn_origin" default:"" description:"WebAuthn Origin"`
}
func Main() {
var (
cfg Config
L *zap.Logger
)
err := envconfig.Process("authentricity_webui", &cfg)
if err != nil {
envconfig.Usage("authentricity_webui", &cfg)
log.Fatalf("Parsing settings: %v", err)
}
if cfg.Debug {
L, err = zap.NewDevelopment()
} else {
L, err = zap.NewProduction()
}
if err != nil {
log.Fatal("Initializing logger", err)
}
defer zap.ReplaceGlobals(L)()
defer zap.RedirectStdLog(L)()
S := L.Sugar()
if err := os.MkdirAll(cfg.SecretsDir, 0700); err != nil {
S.Fatalf("Error creating secrets directory '%s': %v", cfg.SecretsDir, err)
}
cst, err := store.NewConsulStore(L.Named("consul_store"))
if err != nil {
S.Fatalf("Error creating Consul store: %v", err)
}
l := listener(cfg)
service := buildService(cfg, cst)
err = http.Serve(l, service)
if err != nil {
S.Fatalf("Error serving requests: %v", err)
}
}
func listener(cfg Config) net.Listener {
S := zap.S()
listeners, err := activation.Listeners()
if err != nil {
S.Fatalf("Error checking for socket-activation sockets: %v", err)
}
switch len(listeners) {
case 0:
S.Infof("Listening on %s:%s", cfg.ListenType, cfg.ListenAddress)
l, err := net.Listen(cfg.ListenType, cfg.ListenAddress)
if err != nil {
S.Fatalf("Error creating listener: %v", err)
}
return l
case 1:
l := listeners[0]
S.Infof("Listening on socket passed by init system with address %s:%s",
l.Addr().Network(), l.Addr().String())
return l
default:
S.Fatalf("Socket activated with more than one socket - only one expected")
return nil
}
}