@@ -4,16 +4,21 @@ package notmain
44
55import (
66 "context"
7+ "database/sql"
8+ "errors"
79 "flag"
810 "os"
911
1012 "github.com/jmhodges/clock"
1113
1214 "github.com/letsencrypt/boulder/cmd"
15+ "github.com/letsencrypt/boulder/config"
1316 bgrpc "github.com/letsencrypt/boulder/grpc"
1417 "github.com/letsencrypt/boulder/issuance"
1518 mtca "github.com/letsencrypt/boulder/mtca"
1619 mtcapb "github.com/letsencrypt/boulder/mtca/proto"
20+
21+ "github.com/letsencrypt/borp"
1722)
1823
1924type Config struct {
@@ -22,12 +27,17 @@ type Config struct {
2227
2328 GRPCMTCA * cmd.GRPCServerConfig
2429
30+ DB cmd.DBConfig
31+
2532 // Issuer holds the configuration for a single MTCA instance with a single mtcaID.
2633 // We run a separate process for each issuer.
2734 // TODO: the issuance package parses the CA certificate as a self-signed X.509
2835 // certificate, but per MTC draft, a CA SHOULD be represented by an RFC 9925
2936 // unsigned certificate: https://www.rfc-editor.org/rfc/rfc9925.html.
3037 Issuer issuance.IssuerConfig
38+
39+ // SequencingPeriod controls how frequently the MTCA sequences a batch and signs a checkpoint.
40+ SequencingPeriod config.Duration
3141 }
3242
3343 Syslog cmd.SyslogConfig
@@ -38,6 +48,9 @@ func main() {
3848 grpcAddr := flag .String ("addr" , "" , "gRPC listen address override" )
3949 debugAddr := flag .String ("debug-addr" , "" , "Debug server address override" )
4050 configFile := flag .String ("config" , "" , "File path to the configuration file for this service" )
51+ initLog := flag .Bool ("init-log" , false , "Initialize log metadata in the database and exit" )
52+ initLogForTest := flag .Bool ("init-log-for-test" , false , "For testing: initialize log metadata if not already initialized, then serve" )
53+
4154 flag .Parse ()
4255 if * configFile == "" {
4356 flag .Usage ()
@@ -67,14 +80,39 @@ func main() {
6780 issuer , err := issuance .LoadIssuer (c .MTCA .Issuer , clk )
6881 cmd .FailOnError (err , "Loading issuer" )
6982
70- mtcaImpl := mtca .New (issuer )
83+ url , err := c .MTCA .DB .URL ()
84+ cmd .FailOnError (err , "Reading DB URL" )
85+ db , err := sql .Open ("mysql" , url )
86+ cmd .FailOnError (err , "Opening DB" )
87+ dbMap := & borp.DbMap {Db : db , Dialect : borp.MySQLDialect {}}
88+
89+ mtcaImpl , err := mtca .New (issuer , dbMap , logger )
90+ cmd .FailOnError (err , "Building MTCA" )
91+
92+ if * initLog {
93+ err = mtcaImpl .InitLog (context .Background ())
94+ cmd .FailOnError (err , "Initializing log" )
95+ return
96+ }
97+ if * initLogForTest {
98+ err = mtcaImpl .InitLog (context .Background ())
99+ if err != nil && ! errors .Is (err , mtca .ErrIssuanceLogAlreadyInitialized ) {
100+ cmd .FailOnError (err , "Initializing MTC log DB for test" )
101+ }
102+ }
71103
72104 srv := bgrpc .NewServer (c .MTCA .GRPCMTCA , logger ).Add (
73105 & mtcapb .MTCA_ServiceDesc , mtcaImpl )
74106
75107 start , err := srv .Build (tlsConfig , scope , clk )
76108 cmd .FailOnError (err , "Unable to setup MTCA gRPC server" )
77109
110+ ctx , cancel := context .WithCancel (context .Background ())
111+ // Cancel will be called after start() returns, which happens after GracefulStop() returns.
112+ // That means all inflight RPCs will be done, which means the last of the pool has been sequenced.
113+ defer cancel ()
114+ go mtcaImpl .Loop (ctx , c .MTCA .SequencingPeriod .Duration )
115+
78116 cmd .FailOnError (start (), "MTCA gRPC service failed" )
79117}
80118
0 commit comments