github.com/letsencrypt/boulder@v0.20251208.0/cmd/boulder-sa/main.go (about) 1 package notmain 2 3 import ( 4 "context" 5 "flag" 6 "os" 7 8 "github.com/jmhodges/clock" 9 10 "github.com/letsencrypt/boulder/cmd" 11 "github.com/letsencrypt/boulder/config" 12 "github.com/letsencrypt/boulder/features" 13 bgrpc "github.com/letsencrypt/boulder/grpc" 14 "github.com/letsencrypt/boulder/sa" 15 sapb "github.com/letsencrypt/boulder/sa/proto" 16 ) 17 18 type Config struct { 19 SA struct { 20 cmd.ServiceConfig 21 DB cmd.DBConfig 22 ReadOnlyDB cmd.DBConfig `validate:"-"` 23 IncidentsDB cmd.DBConfig `validate:"-"` 24 25 Features features.Config 26 27 // Max simultaneous SQL queries caused by a single RPC. 28 ParallelismPerRPC int `validate:"omitempty,min=1"` 29 // LagFactor is how long to sleep before retrying a read request that may 30 // have failed solely due to replication lag. 31 LagFactor config.Duration `validate:"-"` 32 } 33 34 Syslog cmd.SyslogConfig 35 OpenTelemetry cmd.OpenTelemetryConfig 36 } 37 38 func main() { 39 grpcAddr := flag.String("addr", "", "gRPC listen address override") 40 debugAddr := flag.String("debug-addr", "", "Debug server address override") 41 configFile := flag.String("config", "", "File path to the configuration file for this service") 42 flag.Parse() 43 if *configFile == "" { 44 flag.Usage() 45 os.Exit(1) 46 } 47 48 var c Config 49 err := cmd.ReadConfigFile(*configFile, &c) 50 cmd.FailOnError(err, "Reading JSON config file into config structure") 51 52 features.Set(c.SA.Features) 53 54 if *grpcAddr != "" { 55 c.SA.GRPC.Address = *grpcAddr 56 } 57 if *debugAddr != "" { 58 c.SA.DebugAddr = *debugAddr 59 } 60 61 scope, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.SA.DebugAddr) 62 defer oTelShutdown(context.Background()) 63 logger.Info(cmd.VersionString()) 64 65 dbMap, err := sa.InitWrappedDb(c.SA.DB, scope, logger) 66 cmd.FailOnError(err, "While initializing dbMap") 67 68 dbReadOnlyMap := dbMap 69 if c.SA.ReadOnlyDB != (cmd.DBConfig{}) { 70 dbReadOnlyMap, err = sa.InitWrappedDb(c.SA.ReadOnlyDB, scope, logger) 71 cmd.FailOnError(err, "While initializing dbReadOnlyMap") 72 } 73 74 dbIncidentsMap := dbMap 75 if c.SA.IncidentsDB != (cmd.DBConfig{}) { 76 dbIncidentsMap, err = sa.InitWrappedDb(c.SA.IncidentsDB, scope, logger) 77 cmd.FailOnError(err, "While initializing dbIncidentsMap") 78 } 79 80 clk := clock.New() 81 82 parallel := max(c.SA.ParallelismPerRPC, 1) 83 84 tls, err := c.SA.TLS.Load(scope) 85 cmd.FailOnError(err, "TLS config") 86 87 saroi, err := sa.NewSQLStorageAuthorityRO( 88 dbReadOnlyMap, dbIncidentsMap, scope, parallel, c.SA.LagFactor.Duration, clk, logger) 89 cmd.FailOnError(err, "Failed to create read-only SA impl") 90 91 sai, err := sa.NewSQLStorageAuthorityWrapping(saroi, dbMap, scope) 92 cmd.FailOnError(err, "Failed to create SA impl") 93 94 start, err := bgrpc.NewServer(c.SA.GRPC, logger).WithCheckInterval(c.SA.HealthCheckInterval.Duration).Add( 95 &sapb.StorageAuthorityReadOnly_ServiceDesc, saroi).Add( 96 &sapb.StorageAuthority_ServiceDesc, sai).Build( 97 tls, scope, clk) 98 cmd.FailOnError(err, "Unable to setup SA gRPC server") 99 100 cmd.FailOnError(start(), "SA gRPC service failed") 101 } 102 103 func init() { 104 cmd.RegisterCommand("boulder-sa", main, &cmd.ConfigValidator{Config: &Config{}}) 105 }