@@ -4,12 +4,16 @@ package notmain
44
55import (
66 "context"
7+ "database/sql"
8+ "errors"
79 "flag"
810 "os"
911
1012 "github.com/jmhodges/clock"
1113
14+ "github.com/letsencrypt/borp"
1215 "github.com/letsencrypt/boulder/cmd"
16+ "github.com/letsencrypt/boulder/config"
1317 bgrpc "github.com/letsencrypt/boulder/grpc"
1418 "github.com/letsencrypt/boulder/issuance"
1519 mtca "github.com/letsencrypt/boulder/mtca"
@@ -22,12 +26,17 @@ type Config struct {
2226
2327 GRPCMTCA * cmd.GRPCServerConfig
2428
29+ DB cmd.DBConfig
30+
2531 // Issuer holds the configuration for a single MTCA instance with a single mtcaID.
2632 // We run a separate process for each issuer.
2733 // TODO: the issuance package parses the CA certificate as a self-signed X.509
2834 // certificate, but per MTC draft, a CA SHOULD be represented by an RFC 9925
2935 // unsigned certificate: https://www.rfc-editor.org/rfc/rfc9925.html.
3036 Issuer issuance.IssuerConfig
37+
38+ // SequencingPeriod controls how frequently the MTCA sequences a batch and signs a checkpoint.
39+ SequencingPeriod config.Duration `validate:"required"`
3140 }
3241
3342 Syslog cmd.SyslogConfig
@@ -38,6 +47,9 @@ func main() {
3847 grpcAddr := flag .String ("addr" , "" , "gRPC listen address override" )
3948 debugAddr := flag .String ("debug-addr" , "" , "Debug server address override" )
4049 configFile := flag .String ("config" , "" , "File path to the configuration file for this service" )
50+ initLog := flag .Bool ("init-log" , false , "Initialize log metadata in the database and exit" )
51+ initLogForTest := flag .Bool ("init-log-for-test" , false , "For testing: initialize log metadata if not already initialized, then serve" )
52+
4153 flag .Parse ()
4254 if * configFile == "" {
4355 flag .Usage ()
@@ -67,14 +79,39 @@ func main() {
6779 issuer , err := issuance .LoadIssuer (c .MTCA .Issuer , clk )
6880 cmd .FailOnError (err , "Loading issuer" )
6981
70- mtcaImpl := mtca .New (issuer )
82+ url , err := c .MTCA .DB .URL ()
83+ cmd .FailOnError (err , "Reading DB URL" )
84+ db , err := sql .Open ("mysql" , url )
85+ cmd .FailOnError (err , "Opening DB" )
86+ dbMap := & borp.DbMap {Db : db , Dialect : borp.MySQLDialect {}}
87+
88+ mtcaImpl , err := mtca .New (issuer , dbMap , logger )
89+ cmd .FailOnError (err , "Building MTCA" )
90+
91+ if * initLog {
92+ err = mtcaImpl .InitLog (context .Background ())
93+ cmd .FailOnError (err , "Initializing log" )
94+ return
95+ }
96+ if * initLogForTest {
97+ err = mtcaImpl .InitLog (context .Background ())
98+ if err != nil && ! errors .Is (err , mtca .ErrIssuanceLogAlreadyInitialized ) {
99+ cmd .FailOnError (err , "Initializing MTC log DB for test" )
100+ }
101+ }
71102
72103 srv := bgrpc .NewServer (c .MTCA .GRPCMTCA , logger ).Add (
73104 & mtcapb .MTCA_ServiceDesc , mtcaImpl )
74105
75106 start , err := srv .Build (tlsConfig , scope , clk )
76107 cmd .FailOnError (err , "Unable to setup MTCA gRPC server" )
77108
109+ ctx , cancel := context .WithCancel (context .Background ())
110+ // Cancel will be called after start() returns, which happens after GracefulStop() returns.
111+ // That means all inflight RPCs will be done, which means the last of the pool has been sequenced.
112+ defer cancel ()
113+ go mtcaImpl .Loop (ctx , c .MTCA .SequencingPeriod .Duration )
114+
78115 cmd .FailOnError (start (), "MTCA gRPC service failed" )
79116}
80117
0 commit comments