github.com/letsencrypt/boulder@v0.20251208.0/cmd/boulder-publisher/main.go (about) 1 package notmain 2 3 import ( 4 "context" 5 "flag" 6 "fmt" 7 "os" 8 "runtime" 9 10 ct "github.com/google/certificate-transparency-go" 11 "github.com/jmhodges/clock" 12 13 "github.com/letsencrypt/boulder/cmd" 14 "github.com/letsencrypt/boulder/features" 15 bgrpc "github.com/letsencrypt/boulder/grpc" 16 "github.com/letsencrypt/boulder/issuance" 17 "github.com/letsencrypt/boulder/publisher" 18 pubpb "github.com/letsencrypt/boulder/publisher/proto" 19 ) 20 21 type Config struct { 22 Publisher struct { 23 cmd.ServiceConfig 24 Features features.Config 25 26 // If this is non-zero, profile blocking events such that one even is 27 // sampled every N nanoseconds. 28 // https://golang.org/pkg/runtime/#SetBlockProfileRate 29 BlockProfileRate int 30 UserAgent string 31 32 // Chains is a list of lists of certificate filenames. Each inner list is 33 // a chain, starting with the issuing intermediate, followed by one or 34 // more additional certificates, up to and including a root. 35 Chains [][]string `validate:"min=1,dive,min=2,dive,required"` 36 } 37 38 Syslog cmd.SyslogConfig 39 OpenTelemetry cmd.OpenTelemetryConfig 40 } 41 42 func main() { 43 grpcAddr := flag.String("addr", "", "gRPC listen address override") 44 debugAddr := flag.String("debug-addr", "", "Debug server address override") 45 configFile := flag.String("config", "", "File path to the configuration file for this service") 46 flag.Parse() 47 if *configFile == "" { 48 flag.Usage() 49 os.Exit(1) 50 } 51 52 var c Config 53 err := cmd.ReadConfigFile(*configFile, &c) 54 cmd.FailOnError(err, "Reading JSON config file into config structure") 55 features.Set(c.Publisher.Features) 56 57 runtime.SetBlockProfileRate(c.Publisher.BlockProfileRate) 58 59 if *grpcAddr != "" { 60 c.Publisher.GRPC.Address = *grpcAddr 61 } 62 if *debugAddr != "" { 63 c.Publisher.DebugAddr = *debugAddr 64 } 65 if c.Publisher.UserAgent == "" { 66 c.Publisher.UserAgent = "certificate-transparency-go/1.0" 67 } 68 scope, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.Publisher.DebugAddr) 69 defer oTelShutdown(context.Background()) 70 logger.Info(cmd.VersionString()) 71 72 if c.Publisher.Chains == nil { 73 logger.AuditErr("No chain files provided") 74 os.Exit(1) 75 } 76 77 bundles := make(map[issuance.NameID][]ct.ASN1Cert) 78 for _, files := range c.Publisher.Chains { 79 chain, err := issuance.LoadChain(files) 80 cmd.FailOnError(err, "failed to load chain.") 81 issuer := chain[0] 82 id := issuer.NameID() 83 if _, exists := bundles[id]; exists { 84 cmd.Fail(fmt.Sprintf("Got multiple chains configured for issuer %q", issuer.Subject.CommonName)) 85 } 86 bundles[id] = publisher.GetCTBundleForChain(chain) 87 } 88 89 tlsConfig, err := c.Publisher.TLS.Load(scope) 90 cmd.FailOnError(err, "TLS config") 91 92 clk := clock.New() 93 94 pubi := publisher.New(bundles, c.Publisher.UserAgent, logger, scope) 95 96 start, err := bgrpc.NewServer(c.Publisher.GRPC, logger).Add( 97 &pubpb.Publisher_ServiceDesc, pubi).Build(tlsConfig, scope, clk) 98 cmd.FailOnError(err, "Unable to setup Publisher gRPC server") 99 100 cmd.FailOnError(start(), "Publisher gRPC service failed") 101 } 102 103 func init() { 104 cmd.RegisterCommand("boulder-publisher", main, &cmd.ConfigValidator{Config: &Config{}}) 105 }