boulder/cmd/boulder-va/main.go

169 lines
4.2 KiB
Go

package main
import (
"flag"
"os"
"time"
"github.com/letsencrypt/boulder/bdns"
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/features"
bgrpc "github.com/letsencrypt/boulder/grpc"
"github.com/letsencrypt/boulder/va"
vaPB "github.com/letsencrypt/boulder/va/proto"
)
type config struct {
VA struct {
cmd.ServiceConfig
UserAgent string
IssuerDomain string
PortConfig cmd.PortConfig
// CAADistributedResolverConfig specifies the HTTP client setup and interfaces
// needed to resolve CAA addresses over multiple paths
CAADistributedResolver struct {
Timeout cmd.ConfigDuration
MaxFailures int
Proxies []string
}
// The number of times to try a DNS query (that has a temporary error)
// before giving up. May be short-circuited by deadlines. A zero value
// will be turned into 1.
DNSTries int
DNSResolvers []string
RemoteVAs []cmd.GRPCClientConfig
MaxRemoteValidationFailures int
Features map[string]bool
AccountURIPrefixes []string
}
Syslog cmd.SyslogConfig
Common struct {
DNSResolver string
DNSTimeout string
DNSAllowLoopbackAddresses bool
}
}
func main() {
grpcAddr := flag.String("addr", "", "gRPC 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")
err = features.Set(c.VA.Features)
cmd.FailOnError(err, "Failed to set feature flags")
if *grpcAddr != "" {
c.VA.GRPC.Address = *grpcAddr
}
if *debugAddr != "" {
c.VA.DebugAddr = *debugAddr
}
scope, logger := cmd.StatsAndLogging(c.Syslog, c.VA.DebugAddr)
defer logger.AuditPanic()
logger.Info(cmd.VersionString())
pc := &cmd.PortConfig{
HTTPPort: 80,
HTTPSPort: 443,
TLSPort: 443,
}
if c.VA.PortConfig.HTTPPort != 0 {
pc.HTTPPort = c.VA.PortConfig.HTTPPort
}
if c.VA.PortConfig.HTTPSPort != 0 {
pc.HTTPSPort = c.VA.PortConfig.HTTPSPort
}
if c.VA.PortConfig.TLSPort != 0 {
pc.TLSPort = c.VA.PortConfig.TLSPort
}
dnsTimeout, err := time.ParseDuration(c.Common.DNSTimeout)
cmd.FailOnError(err, "Couldn't parse DNS timeout")
dnsTries := c.VA.DNSTries
if dnsTries < 1 {
dnsTries = 1
}
clk := cmd.Clock()
var resolver bdns.DNSClient
if len(c.Common.DNSResolver) != 0 {
c.VA.DNSResolvers = append(c.VA.DNSResolvers, c.Common.DNSResolver)
}
if !c.Common.DNSAllowLoopbackAddresses {
r := bdns.NewDNSClientImpl(
dnsTimeout,
c.VA.DNSResolvers,
scope,
clk,
dnsTries)
resolver = r
} else {
r := bdns.NewTestDNSClientImpl(dnsTimeout, c.VA.DNSResolvers, scope, clk, dnsTries)
resolver = r
}
tlsConfig, err := c.VA.TLS.Load()
cmd.FailOnError(err, "tlsConfig config")
clientMetrics := bgrpc.NewClientMetrics(scope)
var remotes []va.RemoteVA
if len(c.VA.RemoteVAs) > 0 {
for _, rva := range c.VA.RemoteVAs {
vaConn, err := bgrpc.ClientSetup(&rva, tlsConfig, clientMetrics, clk)
cmd.FailOnError(err, "Unable to create remote VA client")
remotes = append(
remotes,
va.RemoteVA{
ValidationAuthority: bgrpc.NewValidationAuthorityGRPCClient(vaConn),
Address: rva.ServerAddress,
},
)
}
}
vai, err := va.NewValidationAuthorityImpl(
pc,
resolver,
remotes,
c.VA.MaxRemoteValidationFailures,
c.VA.UserAgent,
c.VA.IssuerDomain,
scope,
clk,
logger,
c.VA.AccountURIPrefixes)
cmd.FailOnError(err, "Unable to create VA server")
serverMetrics := bgrpc.NewServerMetrics(scope)
grpcSrv, l, err := bgrpc.NewServer(c.VA.GRPC, tlsConfig, serverMetrics, clk)
cmd.FailOnError(err, "Unable to setup VA gRPC server")
err = bgrpc.RegisterValidationAuthorityGRPCServer(grpcSrv, vai)
cmd.FailOnError(err, "Unable to register VA gRPC server")
vaPB.RegisterCAAServer(grpcSrv, vai)
cmd.FailOnError(err, "Unable to register CAA gRPC server")
go cmd.CatchSignals(logger, grpcSrv.GracefulStop)
err = cmd.FilterShutdownErrors(grpcSrv.Serve(l))
cmd.FailOnError(err, "VA gRPC service failed")
}