func main() { app := cmd.NewAppShell("activity-monitor", "RPC activity monitor") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { go cmd.DebugServer(c.ActivityMonitor.DebugAddr) amqpConf := c.ActivityMonitor.AMQP server, err := rpc.NewMonitorServer(amqpConf, 0, stats) cmd.FailOnError(err, "Could not connect to AMQP") ae := analysisengine.NewLoggingAnalysisEngine() messages := expvar.NewInt("messages") server.HandleDeliveries(rpc.DeliveryHandler(func(d amqp.Delivery) { messages.Add(1) ae.ProcessMessage(d) })) go cmd.ProfileCmd("AM", stats) err = server.Start(amqpConf) cmd.FailOnError(err, "Unable to run Activity Monitor") } app.Run() }
func main() { app := cmd.NewAppShell("activity-monitor") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Could not connect to statsd") auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.ActivityMonitor.DebugAddr) ch, err := rpc.AmqpChannel(c) cmd.FailOnError(err, "Could not connect to AMQP") go cmd.ProfileCmd("AM", stats) auditlogger.Info(app.VersionString()) startMonitor(ch, auditlogger, stats) } app.Run() }
func main() { app := cmd.NewAppShell("boulder-sa", "Handles SQL operations") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { saConf := c.SA go cmd.DebugServer(saConf.DebugAddr) dbMap, err := sa.NewDbMap(saConf.DBConnect) cmd.FailOnError(err, "Couldn't connect to SA database") sai, err := sa.NewSQLStorageAuthority(dbMap, clock.Default()) cmd.FailOnError(err, "Failed to create SA impl") sai.SetSQLDebug(c.SQL.SQLDebug) go cmd.ProfileCmd("SA", stats) amqpConf := saConf.AMQP sas, err := rpc.NewAmqpRPCServer(amqpConf, c.SA.MaxConcurrentRPCServerRequests, stats) cmd.FailOnError(err, "Unable to create SA RPC server") rpc.NewStorageAuthorityServer(sas, sai) err = sas.Start(amqpConf) cmd.FailOnError(err, "Unable to run SA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("ocsp-updater", "Generates and updates OCSP responses") app.Action = func(c cmd.Config) { // Set up logging stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") auditlogger.Info(app.VersionString()) blog.SetAuditLogger(auditlogger) // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() go cmd.DebugServer(c.OCSPUpdater.DebugAddr) go cmd.ProfileCmd("OCSP-Updater", stats) // Configure DB dbMap, err := sa.NewDbMap(c.OCSPUpdater.DBConnect) cmd.FailOnError(err, "Could not connect to database") cac, pubc, sac, closeChan := setupClients(c, stats) updater, err := newUpdater( stats, clock.Default(), dbMap, cac, pubc, sac, // Necessary evil for now c.OCSPUpdater, len(c.Common.CT.Logs), ) for _, l := range updater.loops { go func(loop *looper) { err = loop.loop() if err != nil { auditlogger.AuditErr(err) } }(l) } cmd.FailOnError(err, "Failed to create updater") // TODO(): When the channel falls over so do we for now, if the AMQP channel // has already closed there is no real cleanup we can do. This is due to // really needing to change the underlying AMQP Server/Client reconnection // logic. err = <-closeChan auditlogger.AuditErr(fmt.Errorf(" [!] AMQP Channel closed, exiting: [%s]", err)) os.Exit(1) } app.Run() }
func main() { app := cmd.NewAppShell("boulder-sa", "Handles SQL operations") app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) { saConf := c.SA go cmd.DebugServer(saConf.DebugAddr) dbURL, err := saConf.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, saConf.DBConfig.MaxDBConns) cmd.FailOnError(err, "Couldn't connect to SA database") go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "SA")) sai, err := sa.NewSQLStorageAuthority(dbMap, clock.Default(), logger) cmd.FailOnError(err, "Failed to create SA impl") go cmd.ProfileCmd("SA", stats) amqpConf := saConf.AMQP sas, err := rpc.NewAmqpRPCServer(amqpConf, c.SA.MaxConcurrentRPCServerRequests, stats, logger) cmd.FailOnError(err, "Unable to create SA RPC server") err = rpc.NewStorageAuthorityServer(sas, sai) cmd.FailOnError(err, "Unable to setup SA RPC server") err = sas.Start(amqpConf) cmd.FailOnError(err, "Unable to run SA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ocsp-responder", "Handles OCSP requests") app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) { go cmd.DebugServer(c.OCSPResponder.DebugAddr) go cmd.ProfileCmd("OCSP", stats) config := c.OCSPResponder var source cfocsp.Source // DBConfig takes precedence over Source, if present. dbConnect, err := config.DBConfig.URL() cmd.FailOnError(err, "Reading DB config") if dbConnect == "" { dbConnect = config.Source } url, err := url.Parse(dbConnect) cmd.FailOnError(err, fmt.Sprintf("Source was not a URL: %s", config.Source)) if url.Scheme == "mysql+tcp" { logger.Info(fmt.Sprintf("Loading OCSP Database for CA Cert: %s", c.Common.IssuerCert)) dbMap, err := sa.NewDbMap(config.Source) cmd.FailOnError(err, "Could not connect to database") sa.SetSQLDebug(dbMap, logger) source, err = makeDBSource(dbMap, c.Common.IssuerCert, logger) cmd.FailOnError(err, "Couldn't load OCSP DB") } else if url.Scheme == "file" { filename := url.Path // Go interprets cwd-relative file urls (file:test/foo.txt) as having the // relative part of the path in the 'Opaque' field. if filename == "" { filename = url.Opaque } source, err = cfocsp.NewSourceFromFile(filename) cmd.FailOnError(err, fmt.Sprintf("Couldn't read file: %s", url.Path)) } else { cmd.FailOnError(errors.New(`"source" parameter not found in JSON config`), "unable to start ocsp-responder") } stopTimeout, err := time.ParseDuration(c.OCSPResponder.ShutdownStopTimeout) cmd.FailOnError(err, "Couldn't parse shutdown stop timeout") killTimeout, err := time.ParseDuration(c.OCSPResponder.ShutdownKillTimeout) cmd.FailOnError(err, "Couldn't parse shutdown kill timeout") m := mux(stats, c.OCSPResponder.Path, source) srv := &http.Server{ Addr: c.OCSPResponder.ListenAddress, Handler: m, } hd := &httpdown.HTTP{ StopTimeout: stopTimeout, KillTimeout: killTimeout, Stats: metrics.NewFBAdapter(stats, "OCSP", clock.Default()), } err = httpdown.ListenAndServe(srv, hd) cmd.FailOnError(err, "Error starting HTTP server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-sa") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) sai, err := sa.NewSQLStorageAuthority(c.SA.DBDriver, c.SA.DBName) cmd.FailOnError(err, "Failed to create SA impl") go cmd.ProfileCmd("SA", stats) for { ch := cmd.AmqpChannel(c.AMQP.Server) closeChan := ch.NotifyClose(make(chan *amqp.Error, 1)) sas := rpc.NewStorageAuthorityServer(c.AMQP.SA.Server, ch, sai) cmd.RunUntilSignaled(auditlogger, sas, closeChan) } } app.Run() }
func main() { app := cmd.NewAppShell("boulder-publisher", "Submits issued certificates to CT logs") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { pubi, err := publisher.NewPublisherImpl(c.Common.CT) cmd.FailOnError(err, "Could not setup Publisher") go cmd.DebugServer(c.Publisher.DebugAddr) go cmd.ProfileCmd("Publisher", stats) saRPC, err := rpc.NewAmqpRPCClient("Publisher->SA", c.AMQP.SA.Server, c, stats) cmd.FailOnError(err, "Unable to create SA RPC client") sac, err := rpc.NewStorageAuthorityClient(saRPC) cmd.FailOnError(err, "Unable to create SA client") pubi.SA = &sac pubs, err := rpc.NewAmqpRPCServer(c.AMQP.Publisher.Server, c.Publisher.MaxConcurrentRPCServerRequests, c) cmd.FailOnError(err, "Unable to create Publisher RPC server") rpc.NewPublisherServer(pubs, &pubi) err = pubs.Start(c) cmd.FailOnError(err, "Unable to run Publisher RPC server") } app.Run() }
func main() { configFile := flag.String("config", "", "File path to the configuration file for this service") flag.Parse() if *configFile == "" { flag.Usage() os.Exit(1) } var c config err := cmd.ReadConfigFile(*configFile, &c) cmd.FailOnError(err, "Reading JSON config file into config structure") conf := c.OCSPUpdater stats, auditlogger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "OCSPUpdater") defer auditlogger.AuditPanic() auditlogger.Info(cmd.VersionString(clientName)) // Configure DB dbURL, err := conf.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, conf.DBConfig.MaxDBConns) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(dbMap, scope) cac, pubc, sac := setupClients(conf, scope) updater, err := newUpdater( scope, clock.Default(), dbMap, cac, pubc, sac, // Necessary evil for now conf, c.Common.CT.Logs, c.Common.IssuerCert, auditlogger, ) cmd.FailOnError(err, "Failed to create updater") for _, l := range updater.loops { go func(loop *looper) { err = loop.loop() if err != nil { auditlogger.AuditErr(err.Error()) } }(l) } go cmd.DebugServer(conf.DebugAddr) go cmd.ProfileCmd(scope) // Sleep forever (until signaled) select {} }
func main() { app := cmd.NewAppShell("boulder-ra", "Handles service orchestration") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { // Validate PA config and set defaults if needed cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration") c.PA.SetDefaultChallengesIfEmpty() go cmd.DebugServer(c.RA.DebugAddr) paDbMap, err := sa.NewDbMap(c.PA.DBConnect) cmd.FailOnError(err, "Couldn't connect to policy database") pa, err := policy.NewPolicyAuthorityImpl(paDbMap, c.PA.EnforcePolicyWhitelist, c.PA.Challenges) cmd.FailOnError(err, "Couldn't create PA") rateLimitPolicies, err := cmd.LoadRateLimitPolicies(c.RA.RateLimitPoliciesFilename) cmd.FailOnError(err, "Couldn't load rate limit policies file") go cmd.ProfileCmd("RA", stats) amqpConf := c.RA.AMQP vac, err := rpc.NewValidationAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Unable to create VA client") cac, err := rpc.NewCertificateAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Unable to create CA client") sac, err := rpc.NewStorageAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Unable to create SA client") var dc *ra.DomainCheck if c.RA.UseIsSafeDomain { dc = &ra.DomainCheck{VA: vac} } rai := ra.NewRegistrationAuthorityImpl(clock.Default(), auditlogger, stats, dc, rateLimitPolicies, c.RA.MaxContactsPerRegistration) rai.PA = pa raDNSTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse RA DNS timeout") if !c.Common.DNSAllowLoopbackAddresses { rai.DNSResolver = core.NewDNSResolverImpl(raDNSTimeout, []string{c.Common.DNSResolver}) } else { rai.DNSResolver = core.NewTestDNSResolverImpl(raDNSTimeout, []string{c.Common.DNSResolver}) } rai.VA = vac rai.CA = cac rai.SA = sac ras, err := rpc.NewAmqpRPCServer(amqpConf, c.RA.MaxConcurrentRPCServerRequests, stats) cmd.FailOnError(err, "Unable to create RA RPC server") rpc.NewRegistrationAuthorityServer(ras, rai) err = ras.Start(amqpConf) cmd.FailOnError(err, "Unable to run RA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ca") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.CA.DebugAddr) cadb, err := ca.NewCertificateAuthorityDatabaseImpl(c.CA.DBDriver, c.CA.DBConnect) cmd.FailOnError(err, "Failed to create CA database") if c.SQL.CreateTables { err = cadb.CreateTablesIfNotExists() cmd.FailOnError(err, "Failed to create CA tables") } cai, err := ca.NewCertificateAuthorityImpl(cadb, c.CA, c.Common.IssuerCert) cmd.FailOnError(err, "Failed to create CA impl") cai.MaxKeySize = c.Common.MaxKeySize go cmd.ProfileCmd("CA", stats) for { ch, err := cmd.AmqpChannel(c) cmd.FailOnError(err, "Could not connect to AMQP") closeChan := ch.NotifyClose(make(chan *amqp.Error, 1)) saRPC, err := rpc.NewAmqpRPCClient("CA->SA", c.AMQP.SA.Server, ch) cmd.FailOnError(err, "Unable to create RPC client") sac, err := rpc.NewStorageAuthorityClient(saRPC) cmd.FailOnError(err, "Failed to create SA client") cai.SA = &sac cas := rpc.NewAmqpRPCServer(c.AMQP.CA.Server, ch) err = rpc.NewCertificateAuthorityServer(cas, cai) cmd.FailOnError(err, "Unable to create CA server") auditlogger.Info(app.VersionString()) cmd.RunUntilSignaled(auditlogger, cas, closeChan) } } app.Run() }
func main() { app := cmd.NewAppShell("boulder-wfe") app.Action = func(c cmd.Config) { // Set up logging stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) wfe, err := wfe.NewWebFrontEndImpl() cmd.FailOnError(err, "Unable to create WFE") rac, sac, closeChan := setupWFE(c) wfe.RA = &rac wfe.SA = &sac wfe.Stats = stats wfe.SubscriberAgreementURL = c.SubscriberAgreementURL wfe.IssuerCert, err = cmd.LoadCert(c.Common.IssuerCert) cmd.FailOnError(err, fmt.Sprintf("Couldn't read issuer cert [%s]", c.Common.IssuerCert)) go cmd.ProfileCmd("WFE", stats) go func() { // sit around and reconnect to AMQP if the channel // drops for some reason and repopulate the wfe object // with new RA and SA rpc clients. for { for err := range closeChan { auditlogger.Warning(fmt.Sprintf("AMQP Channel closed, will reconnect in 5 seconds: [%s]", err)) time.Sleep(time.Second * 5) rac, sac, closeChan = setupWFE(c) wfe.RA = &rac wfe.SA = &sac auditlogger.Warning("Reconnected to AMQP") } } }() // Set up paths wfe.BaseURL = c.Common.BaseURL wfe.HandlePaths() auditlogger.Info(app.VersionString()) // Add HandlerTimer to output resp time + success/failure stats to statsd auditlogger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.WFE.ListenAddress)) err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(http.DefaultServeMux, stats)) cmd.FailOnError(err, "Error starting HTTP server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ca", "Handles issuance operations") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.CA.DebugAddr) dbMap, err := sa.NewDbMap(c.CA.DBConnect) cmd.FailOnError(err, "Couldn't connect to CA database") cadb, err := ca.NewCertificateAuthorityDatabaseImpl(dbMap) cmd.FailOnError(err, "Failed to create CA database") paDbMap, err := sa.NewDbMap(c.PA.DBConnect) cmd.FailOnError(err, "Couldn't connect to policy database") pa, err := policy.NewPolicyAuthorityImpl(paDbMap, c.PA.EnforcePolicyWhitelist) cmd.FailOnError(err, "Couldn't create PA") cai, err := ca.NewCertificateAuthorityImpl(cadb, c.CA, clock.Default(), c.Common.IssuerCert) cmd.FailOnError(err, "Failed to create CA impl") cai.MaxKeySize = c.Common.MaxKeySize cai.PA = pa go cmd.ProfileCmd("CA", stats) connectionHandler := func(srv *rpc.AmqpRPCServer) { saRPC, err := rpc.NewAmqpRPCClient("CA->SA", c.AMQP.SA.Server, srv.Channel) cmd.FailOnError(err, "Unable to create RPC client") sac, err := rpc.NewStorageAuthorityClient(saRPC) cmd.FailOnError(err, "Failed to create SA client") cai.SA = &sac } cas, err := rpc.NewAmqpRPCServer(c.AMQP.CA.Server, connectionHandler) cmd.FailOnError(err, "Unable to create CA RPC server") rpc.NewCertificateAuthorityServer(cas, cai) auditlogger.Info(app.VersionString()) err = cas.Start(c) cmd.FailOnError(err, "Unable to run CA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("ocsp-updater", "Generates and updates OCSP responses") app.Action = func(c cmd.Config) { // Set up logging stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") auditlogger.Info(app.VersionString()) blog.SetAuditLogger(auditlogger) // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() go cmd.DebugServer(c.OCSPUpdater.DebugAddr) go cmd.ProfileCmd("OCSP-Updater", stats) // Configure DB dbMap, err := sa.NewDbMap(c.OCSPUpdater.DBConnect) cmd.FailOnError(err, "Could not connect to database") cac, pubc, sac := setupClients(c, stats) updater, err := newUpdater( stats, clock.Default(), dbMap, cac, pubc, sac, // Necessary evil for now c.OCSPUpdater, len(c.Common.CT.Logs), c.Common.IssuerCert, ) cmd.FailOnError(err, "Failed to create updater") for _, l := range updater.loops { go func(loop *looper) { err = loop.loop() if err != nil { auditlogger.AuditErr(err) } }(l) } // Sleep forever (until signaled) select {} } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ca", "Handles issuance operations") app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) { // Validate PA config and set defaults if needed cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration") go cmd.DebugServer(c.CA.DebugAddr) pa, err := policy.New(c.PA.Challenges) cmd.FailOnError(err, "Couldn't create PA") if c.CA.HostnamePolicyFile == "" { cmd.FailOnError(fmt.Errorf("HostnamePolicyFile was empty."), "") } err = pa.SetHostnamePolicyFile(c.CA.HostnamePolicyFile) cmd.FailOnError(err, "Couldn't load hostname policy file") issuers, err := loadIssuers(c) cmd.FailOnError(err, "Couldn't load issuers") cai, err := ca.NewCertificateAuthorityImpl( c.CA, clock.Default(), stats, issuers, c.KeyPolicy(), logger) cmd.FailOnError(err, "Failed to create CA impl") cai.PA = pa go cmd.ProfileCmd("CA", stats) amqpConf := c.CA.AMQP cai.SA, err = rpc.NewStorageAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Failed to create SA client") if c.CA.PublisherService != nil { conn, err := bgrpc.ClientSetup(c.CA.PublisherService) cmd.FailOnError(err, "Failed to load credentials and create connection to service") cai.Publisher = bgrpc.NewPublisherClientWrapper(pubPB.NewPublisherClient(conn), c.CA.PublisherService.Timeout.Duration) } else { cai.Publisher, err = rpc.NewPublisherClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Failed to create Publisher client") } cas, err := rpc.NewAmqpRPCServer(amqpConf, c.CA.MaxConcurrentRPCServerRequests, stats, logger) cmd.FailOnError(err, "Unable to create CA RPC server") err = rpc.NewCertificateAuthorityServer(cas, cai) cmd.FailOnError(err, "Failed to create Certificate Authority RPC server") err = cas.Start(amqpConf) cmd.FailOnError(err, "Unable to run CA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ca", "Handles issuance operations") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { // Validate PA config and set defaults if needed cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.CA.DebugAddr) dbURL, err := c.PA.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") paDbMap, err := sa.NewDbMap(dbURL) cmd.FailOnError(err, "Couldn't connect to policy database") pa, err := policy.NewPolicyAuthorityImpl(paDbMap, c.PA.EnforcePolicyWhitelist, c.PA.Challenges) cmd.FailOnError(err, "Couldn't create PA") priv, err := loadPrivateKey(c.CA.Key) cmd.FailOnError(err, "Couldn't load private key") issuer, err := core.LoadCert(c.Common.IssuerCert) cmd.FailOnError(err, "Couldn't load issuer cert") cai, err := ca.NewCertificateAuthorityImpl( c.CA, clock.Default(), stats, issuer, priv, c.KeyPolicy()) cmd.FailOnError(err, "Failed to create CA impl") cai.PA = pa go cmd.ProfileCmd("CA", stats) amqpConf := c.CA.AMQP cai.SA, err = rpc.NewStorageAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Failed to create SA client") cai.Publisher, err = rpc.NewPublisherClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Failed to create Publisher client") cas, err := rpc.NewAmqpRPCServer(amqpConf, c.CA.MaxConcurrentRPCServerRequests, stats) cmd.FailOnError(err, "Unable to create CA RPC server") rpc.NewCertificateAuthorityServer(cas, cai) err = cas.Start(amqpConf) cmd.FailOnError(err, "Unable to run CA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-va", "Handles challenge validation") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { go cmd.DebugServer(c.VA.DebugAddr) go cmd.ProfileCmd("VA", stats) pc := &va.PortConfig{ HTTPPort: 80, HTTPSPort: 443, TLSPort: 443, } if c.VA.PortConfig.HTTPPort != 0 { pc.HTTPPort = c.VA.PortConfig.HTTPPort } if c.VA.PortConfig.HTTPSPort != 0 { pc.HTTPSPort = c.VA.PortConfig.HTTPSPort } if c.VA.PortConfig.TLSPort != 0 { pc.TLSPort = c.VA.PortConfig.TLSPort } clk := clock.Default() sbc := newGoogleSafeBrowsing(c.VA.GoogleSafeBrowsing) vai := va.NewValidationAuthorityImpl(pc, sbc, stats, clk) dnsTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse DNS timeout") scoped := metrics.NewStatsdScope(stats, "VA", "DNS") dnsTries := c.VA.DNSTries if dnsTries < 1 { dnsTries = 1 } if !c.Common.DNSAllowLoopbackAddresses { vai.DNSResolver = bdns.NewDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}, scoped, clk, dnsTries) } else { vai.DNSResolver = bdns.NewTestDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}, scoped, clk, dnsTries) } vai.UserAgent = c.VA.UserAgent vai.IssuerDomain = c.VA.IssuerDomain amqpConf := c.VA.AMQP rac, err := rpc.NewRegistrationAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Unable to create RA client") vai.RA = rac vas, err := rpc.NewAmqpRPCServer(amqpConf, c.VA.MaxConcurrentRPCServerRequests, stats) cmd.FailOnError(err, "Unable to create VA RPC server") rpc.NewValidationAuthorityServer(vas, vai) err = vas.Start(amqpConf) cmd.FailOnError(err, "Unable to run VA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-va") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.VA.DebugAddr) go cmd.ProfileCmd("VA", stats) vai := va.NewValidationAuthorityImpl(c.CA.TestMode) dnsTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse DNS timeout") vai.DNSResolver = core.NewDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}) vai.UserAgent = c.VA.UserAgent for { ch, err := cmd.AmqpChannel(c) cmd.FailOnError(err, "Could not connect to AMQP") closeChan := ch.NotifyClose(make(chan *amqp.Error, 1)) raRPC, err := rpc.NewAmqpRPCClient("VA->RA", c.AMQP.RA.Server, ch) cmd.FailOnError(err, "Unable to create RPC client") rac, err := rpc.NewRegistrationAuthorityClient(raRPC) cmd.FailOnError(err, "Unable to create RA client") vai.RA = &rac vas := rpc.NewAmqpRPCServer(c.AMQP.VA.Server, ch) err = rpc.NewValidationAuthorityServer(vas, &vai) cmd.FailOnError(err, "Unable to create VA server") auditlogger.Info(app.VersionString()) cmd.RunUntilSignaled(auditlogger, vas, closeChan) } } app.Run() }
func main() { app := cmd.NewAppShell("boulder-publisher", "Submits issued certificates to CT logs") app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) { logs := make([]*publisher.Log, len(c.Common.CT.Logs)) var err error for i, ld := range c.Common.CT.Logs { logs[i], err = publisher.NewLog(ld.URI, ld.Key) cmd.FailOnError(err, "Unable to parse CT log description") } if c.Common.CT.IntermediateBundleFilename == "" { logger.AuditErr("No CT submission bundle provided") os.Exit(1) } pemBundle, err := core.LoadCertBundle(c.Common.CT.IntermediateBundleFilename) cmd.FailOnError(err, "Failed to load CT submission bundle") bundle := []ct.ASN1Cert{} for _, cert := range pemBundle { bundle = append(bundle, ct.ASN1Cert(cert.Raw)) } pubi := publisher.New(bundle, logs, c.Publisher.SubmissionTimeout.Duration, logger) go cmd.DebugServer(c.Publisher.DebugAddr) go cmd.ProfileCmd("Publisher", stats) amqpConf := c.Publisher.AMQP pubi.SA, err = rpc.NewStorageAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Unable to create SA client") if c.Publisher.GRPC != nil { s, l, err := bgrpc.NewServer(c.Publisher.GRPC) cmd.FailOnError(err, "Failed to setup gRPC server") gw := bgrpc.NewPublisherServerWrapper(pubi) pubPB.RegisterPublisherServer(s, gw) go func() { err = s.Serve(l) cmd.FailOnError(err, "gRPC service failed") }() } pubs, err := rpc.NewAmqpRPCServer(amqpConf, c.Publisher.MaxConcurrentRPCServerRequests, stats, logger) cmd.FailOnError(err, "Unable to create Publisher RPC server") err = rpc.NewPublisherServer(pubs, pubi) cmd.FailOnError(err, "Unable to setup Publisher RPC server") err = pubs.Start(amqpConf) cmd.FailOnError(err, "Unable to run Publisher RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ocsp-responder", "Handles OCSP requests") app.Action = func(c cmd.Config) { // Set up logging stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.OCSPResponder.DebugAddr) go cmd.ProfileCmd("OCSP", stats) auditlogger.Info(app.VersionString()) // Configure DB dbMap, err := sa.NewDbMap(c.OCSPResponder.DBConnect) cmd.FailOnError(err, "Could not connect to database") sa.SetSQLDebug(dbMap, c.SQL.SQLDebug) // Load the CA's key so we can store its SubjectKey in the DB caCertDER, err := cmd.LoadCert(c.Common.IssuerCert) cmd.FailOnError(err, fmt.Sprintf("Couldn't read issuer cert [%s]", c.Common.IssuerCert)) caCert, err := x509.ParseCertificate(caCertDER) cmd.FailOnError(err, fmt.Sprintf("Couldn't parse cert read from [%s]", c.Common.IssuerCert)) if len(caCert.SubjectKeyId) == 0 { cmd.FailOnError(fmt.Errorf("Empty subjectKeyID"), "Unable to use CA certificate") } // Construct source from DB auditlogger.Info(fmt.Sprintf("Loading OCSP Database for CA Cert ID: %s", hex.EncodeToString(caCert.SubjectKeyId))) src, err := NewSourceFromDatabase(dbMap, caCert.SubjectKeyId) cmd.FailOnError(err, "Could not connect to OCSP database") // Configure HTTP m := http.NewServeMux() m.Handle(c.OCSPResponder.Path, cfocsp.Responder{Source: src}) // Add HandlerTimer to output resp time + success/failure stats to statsd auditlogger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.OCSPResponder.ListenAddress)) err = http.ListenAndServe(c.OCSPResponder.ListenAddress, HandlerTimer(m, stats)) cmd.FailOnError(err, "Error starting HTTP server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ca", "Handles issuance operations") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { // Validate PA config and set defaults if needed cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration") c.PA.SetDefaultChallengesIfEmpty() // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.CA.DebugAddr) paDbMap, err := sa.NewDbMap(c.PA.DBConnect) cmd.FailOnError(err, "Couldn't connect to policy database") pa, err := policy.NewPolicyAuthorityImpl(paDbMap, c.PA.EnforcePolicyWhitelist, c.PA.Challenges) cmd.FailOnError(err, "Couldn't create PA") cai, err := ca.NewCertificateAuthorityImpl(c.CA, clock.Default(), stats, c.Common.IssuerCert) cmd.FailOnError(err, "Failed to create CA impl") cai.PA = pa go cmd.ProfileCmd("CA", stats) saRPC, err := rpc.NewAmqpRPCClient("CA->SA", c.AMQP.SA.Server, c, stats) cmd.FailOnError(err, "Unable to create RPC client") sac, err := rpc.NewStorageAuthorityClient(saRPC) cmd.FailOnError(err, "Failed to create SA client") pubRPC, err := rpc.NewAmqpRPCClient("CA->Publisher", c.AMQP.Publisher.Server, c, stats) cmd.FailOnError(err, "Unable to create RPC client") pubc, err := rpc.NewPublisherClient(pubRPC) cmd.FailOnError(err, "Failed to create Publisher client") cai.Publisher = &pubc cai.SA = &sac cas, err := rpc.NewAmqpRPCServer(c.AMQP.CA.Server, c.CA.MaxConcurrentRPCServerRequests, c) cmd.FailOnError(err, "Unable to create CA RPC server") rpc.NewCertificateAuthorityServer(cas, cai) err = cas.Start(c) cmd.FailOnError(err, "Unable to run CA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-va", "Handles challenge validation") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { go cmd.DebugServer(c.VA.DebugAddr) go cmd.ProfileCmd("VA", stats) pc := &va.PortConfig{ HTTPPort: 80, HTTPSPort: 443, TLSPort: 443, } if c.VA.PortConfig.HTTPPort != 0 { pc.HTTPPort = c.VA.PortConfig.HTTPPort } if c.VA.PortConfig.HTTPSPort != 0 { pc.HTTPSPort = c.VA.PortConfig.HTTPSPort } if c.VA.PortConfig.TLSPort != 0 { pc.TLSPort = c.VA.PortConfig.TLSPort } sbc := newGoogleSafeBrowsing(c.VA.GoogleSafeBrowsing) vai := va.NewValidationAuthorityImpl(pc, sbc, stats, clock.Default()) dnsTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse DNS timeout") if !c.Common.DNSAllowLoopbackAddresses { vai.DNSResolver = core.NewDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}) } else { vai.DNSResolver = core.NewTestDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}) } vai.UserAgent = c.VA.UserAgent raRPC, err := rpc.NewAmqpRPCClient("VA->RA", c.AMQP.RA.Server, c, stats) cmd.FailOnError(err, "Unable to create RPC client") rac, err := rpc.NewRegistrationAuthorityClient(raRPC) cmd.FailOnError(err, "Unable to create RA client") vai.RA = &rac vas, err := rpc.NewAmqpRPCServer(c.AMQP.VA.Server, c.VA.MaxConcurrentRPCServerRequests, c) cmd.FailOnError(err, "Unable to create VA RPC server") rpc.NewValidationAuthorityServer(vas, vai) err = vas.Start(c) cmd.FailOnError(err, "Unable to run VA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("boulder-sa") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.SA.DebugAddr) sai, err := sa.NewSQLStorageAuthority(c.SA.DBDriver, c.SA.DBConnect) cmd.FailOnError(err, "Failed to create SA impl") sai.SetSQLDebug(c.SQL.SQLDebug) if c.SQL.CreateTables { err = sai.CreateTablesIfNotExists() cmd.FailOnError(err, "Failed to create tables") } go cmd.ProfileCmd("SA", stats) for { ch, err := cmd.AmqpChannel(c) cmd.FailOnError(err, "Could not connect to AMQP") closeChan := ch.NotifyClose(make(chan *amqp.Error, 1)) sas := rpc.NewAmqpRPCServer(c.AMQP.SA.Server, ch) err = rpc.NewStorageAuthorityServer(sas, sai) cmd.FailOnError(err, "Could create SA RPC server") auditlogger.Info(app.VersionString()) cmd.RunUntilSignaled(auditlogger, sas, closeChan) } } app.Run() }
func main() { app := cmd.NewAppShell("ocsp-updater", "Generates and updates OCSP responses") app.Action = func(c cmd.Config, stats metrics.Statter, auditlogger blog.Logger) { conf := c.OCSPUpdater go cmd.DebugServer(conf.DebugAddr) go cmd.ProfileCmd("OCSP-Updater", stats) // Configure DB dbURL, err := conf.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, conf.DBConfig.MaxDBConns) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "OCSPUpdater")) cac, pubc, sac := setupClients(conf, stats) updater, err := newUpdater( stats, clock.Default(), dbMap, cac, pubc, sac, // Necessary evil for now conf, len(c.Common.CT.Logs), c.Common.IssuerCert, auditlogger, ) cmd.FailOnError(err, "Failed to create updater") for _, l := range updater.loops { go func(loop *looper) { err = loop.loop() if err != nil { auditlogger.AuditErr(err.Error()) } }(l) } // Sleep forever (until signaled) select {} } app.Run() }
func main() { app := cmd.NewAppShell("activity-monitor", "RPC activity monitor") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { go cmd.DebugServer(c.ActivityMonitor.DebugAddr) ch, err := rpc.AmqpChannel(c.ActivityMonitor.AMQP) cmd.FailOnError(err, "Could not connect to AMQP") go cmd.ProfileCmd("AM", stats) startMonitor(ch, auditlogger, stats) } app.Run() }
func main() { app := cmd.NewAppShell("boulder-ra") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) rai := ra.NewRegistrationAuthorityImpl() go cmd.ProfileCmd("RA", stats) for { ch := cmd.AmqpChannel(c.AMQP.Server) closeChan := ch.NotifyClose(make(chan *amqp.Error, 1)) vac, err := rpc.NewValidationAuthorityClient(c.AMQP.VA.Client, c.AMQP.VA.Server, ch) cmd.FailOnError(err, "Unable to create VA client") cac, err := rpc.NewCertificateAuthorityClient(c.AMQP.CA.Client, c.AMQP.CA.Server, ch) cmd.FailOnError(err, "Unable to create CA client") sac, err := rpc.NewStorageAuthorityClient(c.AMQP.SA.Client, c.AMQP.SA.Server, ch) cmd.FailOnError(err, "Unable to create SA client") rai.VA = &vac rai.CA = &cac rai.SA = &sac ras, err := rpc.NewRegistrationAuthorityServer(c.AMQP.RA.Server, ch, &rai) cmd.FailOnError(err, "Unable to create RA server") cmd.RunUntilSignaled(auditlogger, ras, closeChan) } } app.Run() }
func main() { app := cmd.NewAppShell("boulder-sa") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Couldn't connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to Syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) go cmd.DebugServer(c.SA.DebugAddr) dbMap, err := sa.NewDbMap(c.SA.DBConnect) cmd.FailOnError(err, "Couldn't connect to SA database") sai, err := sa.NewSQLStorageAuthority(dbMap) cmd.FailOnError(err, "Failed to create SA impl") sai.SetSQLDebug(c.SQL.SQLDebug) if c.SQL.CreateTables { err = sai.CreateTablesIfNotExists() cmd.FailOnError(err, "Failed to create tables") } go cmd.ProfileCmd("SA", stats) connectionHandler := func(*rpc.AmqpRPCServer) {} sas, err := rpc.NewAmqpRPCServer(c.AMQP.SA.Server, connectionHandler) cmd.FailOnError(err, "Unable to create SA RPC server") rpc.NewStorageAuthorityServer(sas, sai) auditlogger.Info(app.VersionString()) err = sas.Start(c) cmd.FailOnError(err, "Unable to run SA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("ocsp-updater", "Generates and updates OCSP responses") app.Action = func(c cmd.Config, stats statsd.Statter, auditlogger *blog.AuditLogger) { go cmd.DebugServer(c.OCSPUpdater.DebugAddr) go cmd.ProfileCmd("OCSP-Updater", stats) // Configure DB dbMap, err := sa.NewDbMap(c.OCSPUpdater.DBConnect) cmd.FailOnError(err, "Could not connect to database") cac, pubc, sac := setupClients(c, stats) updater, err := newUpdater( stats, clock.Default(), dbMap, cac, pubc, sac, // Necessary evil for now c.OCSPUpdater, len(c.Common.CT.Logs), c.Common.IssuerCert, ) cmd.FailOnError(err, "Failed to create updater") for _, l := range updater.loops { go func(loop *looper) { err = loop.loop() if err != nil { auditlogger.AuditErr(err) } }(l) } // Sleep forever (until signaled) select {} } app.Run() }
func main() { app := cmd.NewAppShell("boulder-publisher", "Submits issued certificates to CT logs") app.Action = func(c cmd.Config) { stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix) cmd.FailOnError(err, "Could not connect to statsd") // Set up logging auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) cmd.FailOnError(err, "Could not connect to syslog") // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() blog.SetAuditLogger(auditlogger) pubi, err := publisher.NewPublisherImpl(c.Publisher.CT) cmd.FailOnError(err, "Could not setup Publisher") go cmd.DebugServer(c.Publisher.DebugAddr) go cmd.ProfileCmd("Publisher", stats) connectionHandler := func(srv *rpc.AmqpRPCServer) { saRPC, err := rpc.NewAmqpRPCClient("Publisher->SA", c.AMQP.SA.Server, srv.Channel, stats) cmd.FailOnError(err, "Unable to create SA RPC client") sac, err := rpc.NewStorageAuthorityClient(saRPC) cmd.FailOnError(err, "Unable to create SA client") pubi.SA = &sac } pubs, err := rpc.NewAmqpRPCServer(c.AMQP.Publisher.Server, connectionHandler) cmd.FailOnError(err, "Unable to create Publisher RPC server") rpc.NewPublisherServer(pubs, &pubi) auditlogger.Info(app.VersionString()) err = pubs.Start(c) cmd.FailOnError(err, "Unable to run Publisher RPC server") } app.Run() }
func main() { configFile := flag.String("config", "", "File path to the configuration file for this service") flag.Parse() if *configFile == "" { flag.Usage() os.Exit(1) } var c config err := cmd.ReadJSONFile(*configFile, &c) cmd.FailOnError(err, "Reading JSON config file into config structure") go cmd.DebugServer(c.SA.DebugAddr) stats, logger := cmd.StatsAndLogging(c.StatsdConfig, c.SyslogConfig) defer logger.AuditPanic() logger.Info(cmd.VersionString(clientName)) saConf := c.SA dbURL, err := saConf.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, saConf.DBConfig.MaxDBConns) cmd.FailOnError(err, "Couldn't connect to SA database") go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "SA")) sai, err := sa.NewSQLStorageAuthority(dbMap, clock.Default(), logger) cmd.FailOnError(err, "Failed to create SA impl") go cmd.ProfileCmd("SA", stats) amqpConf := saConf.AMQP sas, err := rpc.NewAmqpRPCServer(amqpConf, c.SA.MaxConcurrentRPCServerRequests, stats, logger) cmd.FailOnError(err, "Unable to create SA RPC server") err = rpc.NewStorageAuthorityServer(sas, sai) cmd.FailOnError(err, "Unable to setup SA RPC server") err = sas.Start(amqpConf) cmd.FailOnError(err, "Unable to run SA RPC server") }