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
22
23 NoncePrefix string `validate:"excluded_with=UseDerivablePrefix,omitempty,len=4"`
24
25
26
27
28
29
30
31
32 UseDerivablePrefix bool `validate:"excluded_with=NoncePrefix"`
33
34
35
36
37
38
39
40
41
42
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
87 if c.NonceService.NoncePrefix != "" && c.NonceService.UseDerivablePrefix {
88 cmd.Fail("Cannot set both 'noncePrefix' and 'useDerivablePrefix'")
89 }
90
91
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