github.com/letsencrypt/boulder@v0.20251208.0/cmd/remoteva/main.go (about)

     1  package notmain
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"flag"
     7  	"os"
     8  	"time"
     9  
    10  	"github.com/jmhodges/clock"
    11  
    12  	"github.com/letsencrypt/boulder/bdns"
    13  	"github.com/letsencrypt/boulder/cmd"
    14  	"github.com/letsencrypt/boulder/features"
    15  	bgrpc "github.com/letsencrypt/boulder/grpc"
    16  	"github.com/letsencrypt/boulder/iana"
    17  	"github.com/letsencrypt/boulder/va"
    18  	vaConfig "github.com/letsencrypt/boulder/va/config"
    19  	vapb "github.com/letsencrypt/boulder/va/proto"
    20  )
    21  
    22  type Config struct {
    23  	RVA struct {
    24  		vaConfig.Common
    25  
    26  		// Perspective uniquely identifies the Network Perspective used to
    27  		// perform the validation, as specified in BRs Section 5.4.1,
    28  		// Requirement 2.7 ("Multi-Perspective Issuance Corroboration attempts
    29  		// from each Network Perspective"). It should uniquely identify a group
    30  		// of RVAs deployed in the same datacenter.
    31  		Perspective string `omitempty:"required"`
    32  
    33  		// RIR indicates the Regional Internet Registry where this RVA is
    34  		// located. This field is used to identify the RIR region from which a
    35  		// given validation was performed, as specified in the "Phased
    36  		// Implementation Timeline" in BRs Section 3.2.2.9. It must be one of
    37  		// the following values:
    38  		//   - ARIN
    39  		//   - RIPE
    40  		//   - APNIC
    41  		//   - LACNIC
    42  		//   - AFRINIC
    43  		RIR string `validate:"required,oneof=ARIN RIPE APNIC LACNIC AFRINIC"`
    44  
    45  		// SkipGRPCClientCertVerification, when disabled as it should typically
    46  		// be, will cause the remoteva server (which receives gRPCs from a
    47  		// boulder-va client) to use our default RequireAndVerifyClientCert
    48  		// policy. When enabled, the remoteva server will instead use the less
    49  		// secure VerifyClientCertIfGiven policy. It should typically be used in
    50  		// conjunction with the boulder-va "RVATLSClient" configuration object.
    51  		//
    52  		// An operator may choose to enable this if the remoteva server is
    53  		// logically behind an OSI layer-7 loadbalancer/reverse proxy which
    54  		// decrypts traffic and does not/cannot re-encrypt it's own client
    55  		// connection to the remoteva server.
    56  		//
    57  		// Use with caution.
    58  		//
    59  		// For more information, see: https://pkg.go.dev/crypto/tls#ClientAuthType
    60  		SkipGRPCClientCertVerification bool
    61  
    62  		Features features.Config
    63  	}
    64  
    65  	Syslog        cmd.SyslogConfig
    66  	OpenTelemetry cmd.OpenTelemetryConfig
    67  }
    68  
    69  func main() {
    70  	grpcAddr := flag.String("addr", "", "gRPC listen address override")
    71  	debugAddr := flag.String("debug-addr", "", "Debug server address override")
    72  	configFile := flag.String("config", "", "File path to the configuration file for this service")
    73  	flag.Parse()
    74  	if *configFile == "" {
    75  		flag.Usage()
    76  		os.Exit(1)
    77  	}
    78  
    79  	var c Config
    80  	err := cmd.ReadConfigFile(*configFile, &c)
    81  	cmd.FailOnError(err, "Reading JSON config file into config structure")
    82  	err = c.RVA.SetDefaultsAndValidate(grpcAddr, debugAddr)
    83  	cmd.FailOnError(err, "Setting and validating default config values")
    84  	features.Set(c.RVA.Features)
    85  
    86  	scope, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.RVA.DebugAddr)
    87  	defer oTelShutdown(context.Background())
    88  	logger.Info(cmd.VersionString())
    89  	clk := clock.New()
    90  
    91  	var servers bdns.ServerProvider
    92  
    93  	if len(c.RVA.DNSStaticResolvers) != 0 {
    94  		servers, err = bdns.NewStaticProvider(c.RVA.DNSStaticResolvers)
    95  		cmd.FailOnError(err, "Couldn't start static DNS server resolver")
    96  	} else {
    97  		servers, err = bdns.StartDynamicProvider(c.RVA.DNSProvider, 60*time.Second, "tcp")
    98  		cmd.FailOnError(err, "Couldn't start dynamic DNS server resolver")
    99  	}
   100  	defer servers.Stop()
   101  
   102  	tlsConfig, err := c.RVA.TLS.Load(scope)
   103  	cmd.FailOnError(err, "tlsConfig config")
   104  
   105  	if c.RVA.SkipGRPCClientCertVerification {
   106  		tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven
   107  	}
   108  
   109  	var resolver bdns.Client
   110  	if !c.RVA.DNSAllowLoopbackAddresses {
   111  		resolver = bdns.New(
   112  			c.RVA.DNSTimeout.Duration,
   113  			servers,
   114  			scope,
   115  			clk,
   116  			c.RVA.DNSTries,
   117  			c.RVA.UserAgent,
   118  			logger,
   119  			tlsConfig)
   120  	} else {
   121  		resolver = bdns.NewTest(
   122  			c.RVA.DNSTimeout.Duration,
   123  			servers,
   124  			scope,
   125  			clk,
   126  			c.RVA.DNSTries,
   127  			c.RVA.UserAgent,
   128  			logger,
   129  			tlsConfig)
   130  	}
   131  
   132  	vai, err := va.NewValidationAuthorityImpl(
   133  		resolver,
   134  		nil, // Our RVAs will never have RVAs of their own.
   135  		c.RVA.UserAgent,
   136  		c.RVA.IssuerDomain,
   137  		scope,
   138  		clk,
   139  		logger,
   140  		c.RVA.AccountURIPrefixes,
   141  		c.RVA.Perspective,
   142  		c.RVA.RIR,
   143  		iana.IsReservedAddr,
   144  		0,
   145  	)
   146  	cmd.FailOnError(err, "Unable to create Remote-VA server")
   147  
   148  	start, err := bgrpc.NewServer(c.RVA.GRPC, logger).Add(
   149  		&vapb.VA_ServiceDesc, vai).Add(
   150  		&vapb.CAA_ServiceDesc, vai).Build(tlsConfig, scope, clk)
   151  	cmd.FailOnError(err, "Unable to setup Remote-VA gRPC server")
   152  	cmd.FailOnError(start(), "Remote-VA gRPC service failed")
   153  }
   154  
   155  func init() {
   156  	cmd.RegisterCommand("remoteva", main, &cmd.ConfigValidator{Config: &Config{}})
   157  }