...

Source file src/github.com/letsencrypt/boulder/cmd/nonce-service/main.go

Documentation: github.com/letsencrypt/boulder/cmd/nonce-service

     1  package notmain
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"fmt"
     7  	"net"
     8  	"os"
     9  
    10  	"github.com/letsencrypt/boulder/cmd"
    11  	bgrpc "github.com/letsencrypt/boulder/grpc"
    12  	"github.com/letsencrypt/boulder/nonce"
    13  	noncepb "github.com/letsencrypt/boulder/nonce/proto"
    14  )
    15  
    16  type Config struct {
    17  	NonceService struct {
    18  		cmd.ServiceConfig
    19  
    20  		MaxUsed int
    21  		// TODO(#6610): Remove once we've moved to derivable prefixes by
    22  		// default.
    23  		NoncePrefix string `validate:"excluded_with=UseDerivablePrefix,omitempty,len=4"`
    24  
    25  		// UseDerivablePrefix indicates whether to use a nonce prefix derived
    26  		// from the gRPC listening address. If this is false, the nonce prefix
    27  		// will be the value of the NoncePrefix field. If this is true, the
    28  		// NoncePrefixKey field is required.
    29  		//
    30  		// TODO(#6610): Remove once we've moved to derivable prefixes by
    31  		// default.
    32  		UseDerivablePrefix bool `validate:"excluded_with=NoncePrefix"`
    33  
    34  		// NoncePrefixKey is a secret used for deriving the prefix of each nonce
    35  		// instance. It should contain 256 bits (32 bytes) of random data to be
    36  		// suitable as an HMAC-SHA256 key (e.g. the output of `openssl rand -hex
    37  		// 32`). In a multi-DC deployment this value should be the same across
    38  		// all boulder-wfe and nonce-service instances. This is only used if
    39  		// UseDerivablePrefix is true.
    40  		//
    41  		// TODO(#6610): Edit this comment once we've moved to derivable prefixes
    42  		// by default.
    43  		NoncePrefixKey cmd.PasswordConfig `validate:"excluded_with=NoncePrefix,structonly"`
    44  
    45  		Syslog        cmd.SyslogConfig
    46  		OpenTelemetry cmd.OpenTelemetryConfig
    47  	}
    48  }
    49  
    50  func derivePrefix(key string, grpcAddr string) (string, error) {
    51  	host, port, err := net.SplitHostPort(grpcAddr)
    52  	if err != nil {
    53  		return "", fmt.Errorf("parsing gRPC listen address: %w", err)
    54  	}
    55  	if host != "" && port != "" {
    56  		hostIP := net.ParseIP(host)
    57  		if hostIP == nil {
    58  			return "", fmt.Errorf("parsing IP from gRPC listen address: %w", err)
    59  		}
    60  	}
    61  	return nonce.DerivePrefix(grpcAddr, key), nil
    62  }
    63  
    64  func main() {
    65  	grpcAddr := flag.String("addr", "", "gRPC listen address override")
    66  	debugAddr := flag.String("debug-addr", "", "Debug server address override")
    67  	configFile := flag.String("config", "", "File path to the configuration file for this service")
    68  	flag.Parse()
    69  
    70  	if *configFile == "" {
    71  		flag.Usage()
    72  		os.Exit(1)
    73  	}
    74  
    75  	var c Config
    76  	err := cmd.ReadConfigFile(*configFile, &c)
    77  	cmd.FailOnError(err, "Reading JSON config file into config structure")
    78  
    79  	if *grpcAddr != "" {
    80  		c.NonceService.GRPC.Address = *grpcAddr
    81  	}
    82  	if *debugAddr != "" {
    83  		c.NonceService.DebugAddr = *debugAddr
    84  	}
    85  
    86  	// TODO(#6610): Remove once we've moved to derivable prefixes by default.
    87  	if c.NonceService.NoncePrefix != "" && c.NonceService.UseDerivablePrefix {
    88  		cmd.Fail("Cannot set both 'noncePrefix' and 'useDerivablePrefix'")
    89  	}
    90  
    91  	// TODO(#6610): Remove once we've moved to derivable prefixes by default.
    92  	if c.NonceService.UseDerivablePrefix && c.NonceService.NoncePrefixKey.PasswordFile == "" {
    93  		cmd.Fail("Cannot set 'noncePrefixKey' without 'useDerivablePrefix'")
    94  	}
    95  
    96  	if c.NonceService.UseDerivablePrefix && c.NonceService.NoncePrefixKey.PasswordFile != "" {
    97  		key, err := c.NonceService.NoncePrefixKey.Pass()
    98  		cmd.FailOnError(err, "Failed to load 'noncePrefixKey' file.")
    99  		c.NonceService.NoncePrefix, err = derivePrefix(key, c.NonceService.GRPC.Address)
   100  		cmd.FailOnError(err, "Failed to derive nonce prefix")
   101  	}
   102  
   103  	scope, logger, oTelShutdown := cmd.StatsAndLogging(c.NonceService.Syslog, c.NonceService.OpenTelemetry, c.NonceService.DebugAddr)
   104  	defer oTelShutdown(context.Background())
   105  	logger.Info(cmd.VersionString())
   106  
   107  	ns, err := nonce.NewNonceService(scope, c.NonceService.MaxUsed, c.NonceService.NoncePrefix)
   108  	cmd.FailOnError(err, "Failed to initialize nonce service")
   109  
   110  	tlsConfig, err := c.NonceService.TLS.Load(scope)
   111  	cmd.FailOnError(err, "tlsConfig config")
   112  
   113  	nonceServer := nonce.NewServer(ns)
   114  	start, err := bgrpc.NewServer(c.NonceService.GRPC, logger).Add(
   115  		&noncepb.NonceService_ServiceDesc, nonceServer).Build(tlsConfig, scope, cmd.Clock())
   116  	cmd.FailOnError(err, "Unable to setup nonce service gRPC server")
   117  
   118  	cmd.FailOnError(start(), "Nonce service gRPC server failed")
   119  }
   120  
   121  func init() {
   122  	cmd.RegisterCommand("nonce-service", main, &cmd.ConfigValidator{Config: &Config{}})
   123  }
   124  

View as plain text