140 lines
4.1 KiB
Go
140 lines
4.1 KiB
Go
package notmain
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/letsencrypt/boulder/cmd"
|
|
"github.com/letsencrypt/boulder/config"
|
|
"github.com/letsencrypt/boulder/features"
|
|
bgrpc "github.com/letsencrypt/boulder/grpc"
|
|
rapb "github.com/letsencrypt/boulder/ra/proto"
|
|
sapb "github.com/letsencrypt/boulder/sa/proto"
|
|
"github.com/letsencrypt/boulder/sfe"
|
|
"github.com/letsencrypt/boulder/web"
|
|
)
|
|
|
|
type Config struct {
|
|
SFE struct {
|
|
DebugAddr string `validate:"omitempty,hostname_port"`
|
|
|
|
// ListenAddress is the address:port on which to listen for incoming
|
|
// HTTP requests. Defaults to ":80".
|
|
ListenAddress string `validate:"omitempty,hostname_port"`
|
|
|
|
// Timeout is the per-request overall timeout. This should be slightly
|
|
// lower than the upstream's timeout when making requests to this service.
|
|
Timeout config.Duration `validate:"-"`
|
|
|
|
// ShutdownStopTimeout determines the maximum amount of time to wait
|
|
// for extant request handlers to complete before exiting. It should be
|
|
// greater than Timeout.
|
|
ShutdownStopTimeout config.Duration
|
|
|
|
TLS cmd.TLSConfig
|
|
|
|
RAService *cmd.GRPCClientConfig
|
|
SAService *cmd.GRPCClientConfig
|
|
|
|
// UnpauseHMACKey validates incoming JWT signatures at the unpause
|
|
// endpoint. This key must be the same as the one configured for all
|
|
// WFEs. This field is required to enable the pausing feature.
|
|
UnpauseHMACKey cmd.HMACKeyConfig
|
|
|
|
Features features.Config
|
|
}
|
|
|
|
Syslog cmd.SyslogConfig
|
|
OpenTelemetry cmd.OpenTelemetryConfig
|
|
|
|
// OpenTelemetryHTTPConfig configures tracing on incoming HTTP requests
|
|
OpenTelemetryHTTPConfig cmd.OpenTelemetryHTTPConfig
|
|
}
|
|
|
|
func main() {
|
|
listenAddr := flag.String("addr", "", "HTTP listen address override")
|
|
debugAddr := flag.String("debug-addr", "", "Debug server address override")
|
|
configFile := flag.String("config", "", "File path to the configuration file for this service")
|
|
flag.Parse()
|
|
if *configFile == "" {
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
var c Config
|
|
err := cmd.ReadConfigFile(*configFile, &c)
|
|
cmd.FailOnError(err, "Reading JSON config file into config structure")
|
|
|
|
features.Set(c.SFE.Features)
|
|
|
|
if *listenAddr != "" {
|
|
c.SFE.ListenAddress = *listenAddr
|
|
}
|
|
if c.SFE.ListenAddress == "" {
|
|
cmd.Fail("HTTP listen address is not configured")
|
|
}
|
|
if *debugAddr != "" {
|
|
c.SFE.DebugAddr = *debugAddr
|
|
}
|
|
|
|
stats, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.SFE.DebugAddr)
|
|
logger.Info(cmd.VersionString())
|
|
|
|
clk := cmd.Clock()
|
|
|
|
unpauseHMACKey, err := c.SFE.UnpauseHMACKey.Load()
|
|
cmd.FailOnError(err, "Failed to load unpauseHMACKey")
|
|
|
|
tlsConfig, err := c.SFE.TLS.Load(stats)
|
|
cmd.FailOnError(err, "TLS config")
|
|
|
|
raConn, err := bgrpc.ClientSetup(c.SFE.RAService, tlsConfig, stats, clk)
|
|
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to RA")
|
|
rac := rapb.NewRegistrationAuthorityClient(raConn)
|
|
|
|
saConn, err := bgrpc.ClientSetup(c.SFE.SAService, tlsConfig, stats, clk)
|
|
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA")
|
|
sac := sapb.NewStorageAuthorityReadOnlyClient(saConn)
|
|
|
|
sfei, err := sfe.NewSelfServiceFrontEndImpl(
|
|
stats,
|
|
clk,
|
|
logger,
|
|
c.SFE.Timeout.Duration,
|
|
rac,
|
|
sac,
|
|
unpauseHMACKey,
|
|
)
|
|
cmd.FailOnError(err, "Unable to create SFE")
|
|
|
|
logger.Infof("Server running, listening on %s....", c.SFE.ListenAddress)
|
|
handler := sfei.Handler(stats, c.OpenTelemetryHTTPConfig.Options()...)
|
|
|
|
srv := web.NewServer(c.SFE.ListenAddress, handler, logger)
|
|
go func() {
|
|
err := srv.ListenAndServe()
|
|
if err != nil && err != http.ErrServerClosed {
|
|
cmd.FailOnError(err, "Running HTTP server")
|
|
}
|
|
}()
|
|
|
|
// When main is ready to exit (because it has received a shutdown signal),
|
|
// gracefully shutdown the servers. Calling these shutdown functions causes
|
|
// ListenAndServe() and ListenAndServeTLS() to immediately return, then waits
|
|
// for any lingering connection-handling goroutines to finish their work.
|
|
defer func() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), c.SFE.ShutdownStopTimeout.Duration)
|
|
defer cancel()
|
|
_ = srv.Shutdown(ctx)
|
|
oTelShutdown(ctx)
|
|
}()
|
|
|
|
cmd.WaitForSignal()
|
|
}
|
|
|
|
func init() {
|
|
cmd.RegisterCommand("sfe", main, &cmd.ConfigValidator{Config: &Config{}})
|
|
}
|