func setupContext(c config) (core.RegistrationAuthority, blog.Logger, *gorp.DbMap, core.StorageAuthority, metrics.Scope) { stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "AdminRevoker") amqpConf := c.Revoker.AMQP var rac core.RegistrationAuthority if c.Revoker.RAService != nil { conn, err := bgrpc.ClientSetup(c.Revoker.RAService, scope) cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to RA") rac = bgrpc.NewRegistrationAuthorityClient(rapb.NewRegistrationAuthorityClient(conn)) } else { var err error rac, err = rpc.NewRegistrationAuthorityClient(clientName, amqpConf, scope) cmd.FailOnError(err, "Unable to create RA AMQP client") } dbURL, err := c.Revoker.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, c.Revoker.DBConfig.MaxDBConns) cmd.FailOnError(err, "Couldn't setup database connection") go sa.ReportDbConnCount(dbMap, scope) var sac core.StorageAuthority if c.Revoker.SAService != nil { conn, err := bgrpc.ClientSetup(c.Revoker.SAService, scope) cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA") sac = bgrpc.NewStorageAuthorityClient(sapb.NewStorageAuthorityClient(conn)) } else { sac, err = rpc.NewStorageAuthorityClient(clientName, amqpConf, scope) cmd.FailOnError(err, "Failed to create SA client") } return rac, logger, dbMap, sac, scope }
func TestServerInterceptor(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() statter := metrics.NewMockStatter(ctrl) stats := metrics.NewStatsdScope(statter, "fake") si := serverInterceptor{stats, fc} statter.EXPECT().Inc("fake.gRPC.NoInfo", int64(1), float32(1.0)).Return(nil) _, err := si.intercept(context.Background(), nil, nil, testHandler) test.AssertError(t, err, "si.intercept didn't fail with a nil grpc.UnaryServerInfo") statter.EXPECT().Inc("fake.gRPC.test", int64(1), float32(1.0)).Return(nil) statter.EXPECT().GaugeDelta("fake.gRPC.test.InProgress", int64(1), float32(1.0)).Return(nil) statter.EXPECT().TimingDuration("fake.gRPC.test", time.Second, float32(1.0)).Return(nil) statter.EXPECT().GaugeDelta("fake.gRPC.test.InProgress", int64(-1), float32(1.0)).Return(nil) _, err = si.intercept(context.Background(), nil, &grpc.UnaryServerInfo{FullMethod: "test"}, testHandler) test.AssertNotError(t, err, "si.intercept failed with a non-nil grpc.UnaryServerInfo") statter.EXPECT().Inc("fake.gRPC.broke-test", int64(1), float32(1.0)).Return(nil) statter.EXPECT().GaugeDelta("fake.gRPC.broke-test.InProgress", int64(1), float32(1.0)).Return(nil) statter.EXPECT().TimingDuration("fake.gRPC.broke-test", time.Duration(0), float32(1.0)).Return(nil) statter.EXPECT().GaugeDelta("fake.gRPC.broke-test.InProgress", int64(-1), float32(1.0)).Return(nil) statter.EXPECT().Inc("fake.gRPC.broke-test.Failed", int64(1), float32(1.0)).Return(nil) _, err = si.intercept(context.Background(), 0, &grpc.UnaryServerInfo{FullMethod: "broke-test"}, testHandler) test.AssertError(t, err, "si.intercept didn't fail when handler returned a error") }
// NewRegistrationAuthorityImpl constructs a new RA object. func NewRegistrationAuthorityImpl( clk clock.Clock, logger blog.Logger, stats statsd.Statter, maxContactsPerReg int, keyPolicy goodkey.KeyPolicy, maxNames int, forceCNFromSAN bool, reuseValidAuthz bool, ) *RegistrationAuthorityImpl { scope := metrics.NewStatsdScope(stats, "RA") ra := &RegistrationAuthorityImpl{ stats: stats, clk: clk, log: logger, authorizationLifetime: DefaultAuthorizationLifetime, pendingAuthorizationLifetime: DefaultPendingAuthorizationLifetime, rlPolicies: ratelimit.New(), tiMu: new(sync.RWMutex), maxContactsPerReg: maxContactsPerReg, keyPolicy: keyPolicy, maxNames: maxNames, forceCNFromSAN: forceCNFromSAN, reuseValidAuthz: reuseValidAuthz, regByIPStats: scope.NewScope("RA", "RateLimit", "RegistrationsByIP"), pendAuthByRegIDStats: scope.NewScope("RA", "RateLimit", "PendingAuthorizationsByRegID"), certsForDomainStats: scope.NewScope("RA", "RateLimit", "CertificatesForDomain"), totalCertsStats: scope.NewScope("RA", "RateLimit", "TotalCertificates"), } return ra }
func TestCheckCAAFallback(t *testing.T) { testSrv := httptest.NewServer(http.HandlerFunc(mocks.GPDNSHandler)) defer testSrv.Close() stats := mocks.NewStatter() scope := metrics.NewStatsdScope(stats, "VA") logger := blog.NewMock() caaDR, err := cdr.New(metrics.NewNoopScope(), time.Second, 1, nil, blog.NewMock()) test.AssertNotError(t, err, "Failed to create CAADistributedResolver") caaDR.URI = testSrv.URL caaDR.Clients["1.1.1.1"] = new(http.Client) va := NewValidationAuthorityImpl( &cmd.PortConfig{}, nil, caaDR, &bdns.MockDNSResolver{}, "user agent 1.0", "ca.com", scope, clock.Default(), logger) prob := va.checkCAA(ctx, core.AcmeIdentifier{Value: "bad-local-resolver.com", Type: "dns"}) test.Assert(t, prob == nil, fmt.Sprintf("returned ProblemDetails was non-nil: %#v", prob)) va.caaDR = nil prob = va.checkCAA(ctx, core.AcmeIdentifier{Value: "bad-local-resolver.com", Type: "dns"}) test.Assert(t, prob != nil, "returned ProblemDetails was nil") test.AssertEquals(t, prob.Type, probs.ConnectionProblem) test.AssertEquals(t, prob.Detail, "server failure at resolver") }
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() { configPath := flag.String("config", "config.yml", "Path to configuration file") flag.Parse() configBytes, err := ioutil.ReadFile(*configPath) cmd.FailOnError(err, fmt.Sprintf("Failed to read configuration file from '%s'", *configPath)) var c config err = yaml.Unmarshal(configBytes, &c) cmd.FailOnError(err, fmt.Sprintf("Failed to parse configuration file from '%s'", *configPath)) go cmd.DebugServer(c.DebugAddr) stats, err := statsd.NewClient(c.StatsdServer, c.StatsdPrefix) cmd.FailOnError(err, "Failed to create StatsD client") scope := metrics.NewStatsdScope(stats, "caa-service") resolver := bdns.NewDNSResolverImpl( c.DNSTimeout.Duration, []string{c.DNSResolver}, scope, clock.Default(), 5, ) s, l, err := bgrpc.NewServer(&c.GRPC, scope) cmd.FailOnError(err, "Failed to setup gRPC server") ccs := &caaCheckerServer{resolver, scope} pb.RegisterCAACheckerServer(s, ccs) err = s.Serve(l) cmd.FailOnError(err, "gRPC service failed") }
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-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() { dryRun := flag.Bool("dryRun", true, "Whether to do a dry run.") sleep := flag.Duration("sleep", 60*time.Second, "How long to sleep between batches.") batchSize := flag.Uint("batchSize", 1000, "Number of certificates to process between sleeps.") numBatches := flag.Uint("numBatches", 999999, "Stop processing after N batches.") type config struct { NotAfterBackFiller struct { cmd.DBConfig } Statsd cmd.StatsdConfig Syslog cmd.SyslogConfig } configFile := flag.String("config", "", "File containing a JSON config.") flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n\n", usageIntro) fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) flag.PrintDefaults() } flag.Parse() if *configFile == "" { flag.Usage() os.Exit(1) } configData, err := ioutil.ReadFile(*configFile) cmd.FailOnError(err, fmt.Sprintf("Reading %q", *configFile)) var cfg config err = json.Unmarshal(configData, &cfg) cmd.FailOnError(err, "Unmarshaling config") stats, log := cmd.StatsAndLogging(cfg.Statsd, cfg.Syslog) defer log.AuditPanic() dbURL, err := cfg.NotAfterBackFiller.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, 10) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "NotAfterBackfiller")) b := backfiller{ dbMap: dbMap, log: log, clk: cmd.Clock(), dryRun: *dryRun, batchSize: *batchSize, numBatches: *numBatches, sleep: *sleep, } err = b.processForever() cmd.FailOnError(err, "Could not process certificate batches") }
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, metrics.NewStatsdScope(stats, "Publisher")) 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("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 setup() (*ValidationAuthorityImpl, *mocks.Statter, *blog.Mock) { stats := mocks.NewStatter() scope := metrics.NewStatsdScope(stats, "VA") logger := blog.NewMock() va := NewValidationAuthorityImpl( &cmd.PortConfig{}, nil, nil, &bdns.MockDNSResolver{}, "user agent 1.0", "letsencrypt.org", scope, clock.Default(), logger) return va, stats, logger }
func main() { yes := flag.Bool("yes", false, "Skips the purge confirmation") configPath := flag.String("config", "config.json", "Path to Boulder configuration file") flag.Parse() configJSON, err := ioutil.ReadFile(*configPath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read config file '%s': %s\n", *configPath, err) os.Exit(1) } var config eapConfig err = json.Unmarshal(configJSON, &config) cmd.FailOnError(err, "Failed to parse config") // Set up logging stats, auditlogger := cmd.StatsAndLogging(config.ExpiredAuthzPurger.Statsd, config.ExpiredAuthzPurger.Syslog) auditlogger.Info(cmd.Version()) // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() // Configure DB dbURL, err := config.ExpiredAuthzPurger.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, config.ExpiredAuthzPurger.DBConfig.MaxDBConns) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "AuthzPurger")) purger := &expiredAuthzPurger{ stats: stats, log: auditlogger, clk: cmd.Clock(), db: dbMap, batchSize: int64(config.ExpiredAuthzPurger.BatchSize), } if config.ExpiredAuthzPurger.GracePeriod.Duration == 0 { fmt.Fprintln(os.Stderr, "Grace period is 0, refusing to purge all pending authorizations") os.Exit(1) } purgeBefore := purger.clk.Now().Add(-config.ExpiredAuthzPurger.GracePeriod.Duration) _, err = purger.purgeAuthzs(purgeBefore, *yes) cmd.FailOnError(err, "Failed to purge authorizations") }
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") }
func setupContext(context *cli.Context) (rpc.RegistrationAuthorityClient, blog.Logger, *gorp.DbMap, rpc.StorageAuthorityClient, statsd.Statter) { c, err := loadConfig(context) cmd.FailOnError(err, "Failed to load Boulder configuration") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) amqpConf := c.Revoker.AMQP rac, err := rpc.NewRegistrationAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Unable to create CA client") dbURL, err := c.Revoker.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, c.Revoker.DBConfig.MaxDBConns) cmd.FailOnError(err, "Couldn't setup database connection") go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "AdminRevoker")) sac, err := rpc.NewStorageAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Failed to create SA client") return *rac, logger, dbMap, *sac, stats }
// NewRegistrationAuthorityImpl constructs a new RA object. func NewRegistrationAuthorityImpl(clk clock.Clock, logger *blog.AuditLogger, stats statsd.Statter, dc *DomainCheck, policies cmd.RateLimitConfig, maxContactsPerReg int, keyPolicy core.KeyPolicy) *RegistrationAuthorityImpl { // TODO(jmhodges): making RA take a "RA" stats.Scope, not Statter scope := metrics.NewStatsdScope(stats, "RA") ra := &RegistrationAuthorityImpl{ stats: stats, clk: clk, log: logger, dc: dc, authorizationLifetime: DefaultAuthorizationLifetime, pendingAuthorizationLifetime: DefaultPendingAuthorizationLifetime, rlPolicies: policies, tiMu: new(sync.RWMutex), maxContactsPerReg: maxContactsPerReg, keyPolicy: keyPolicy, regByIPStats: scope.NewScope("RA", "RateLimit", "RegistrationsByIP"), pendAuthByRegIDStats: scope.NewScope("RA", "RateLimit", "PendingAuthorizationsByRegID"), certsForDomainStats: scope.NewScope("RA", "RateLimit", "CertificatesForDomain"), totalCertsStats: scope.NewScope("RA", "RateLimit", "TotalCertificates"), } return ra }
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.RA.DebugAddr) stats, logger := cmd.StatsAndLogging(c.StatsdConfig, c.SyslogConfig) defer logger.AuditPanic() logger.Info(cmd.VersionString(clientName)) // Validate PA config and set defaults if needed cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration") pa, err := policy.New(c.PA.Challenges) cmd.FailOnError(err, "Couldn't create PA") if c.RA.HostnamePolicyFile == "" { cmd.FailOnError(fmt.Errorf("HostnamePolicyFile must be provided."), "") } err = pa.SetHostnamePolicyFile(c.RA.HostnamePolicyFile) cmd.FailOnError(err, "Couldn't load hostname policy file") go cmd.ProfileCmd("RA", stats) amqpConf := c.RA.AMQP var vac core.ValidationAuthority if c.RA.VAService != nil { conn, err := bgrpc.ClientSetup(c.RA.VAService) cmd.FailOnError(err, "Unable to create VA client") vac = bgrpc.NewValidationAuthorityGRPCClient(conn) } else { 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") rai := ra.NewRegistrationAuthorityImpl( clock.Default(), logger, stats, c.RA.MaxContactsPerRegistration, c.AllowedSigningAlgos.KeyPolicy(), c.RA.MaxNames, c.RA.DoNotForceCN, c.RA.ReuseValidAuthz) policyErr := rai.SetRateLimitPoliciesFile(c.RA.RateLimitPoliciesFilename) cmd.FailOnError(policyErr, "Couldn't load rate limit policies file") rai.PA = pa raDNSTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse RA DNS timeout") scoped := metrics.NewStatsdScope(stats, "RA", "DNS") dnsTries := c.RA.DNSTries if dnsTries < 1 { dnsTries = 1 } if !c.Common.DNSAllowLoopbackAddresses { rai.DNSResolver = bdns.NewDNSResolverImpl( raDNSTimeout, []string{c.Common.DNSResolver}, nil, scoped, clock.Default(), dnsTries) } else { rai.DNSResolver = bdns.NewTestDNSResolverImpl( raDNSTimeout, []string{c.Common.DNSResolver}, scoped, clock.Default(), dnsTries) } rai.VA = vac rai.CA = cac rai.SA = sac ras, err := rpc.NewAmqpRPCServer(amqpConf, c.RA.MaxConcurrentRPCServerRequests, stats, logger) cmd.FailOnError(err, "Unable to create RA RPC server") err = rpc.NewRegistrationAuthorityServer(ras, rai, logger) cmd.FailOnError(err, "Unable to setup RA RPC server") err = ras.Start(amqpConf) cmd.FailOnError(err, "Unable to run RA RPC server") }
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") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "Publisher") defer logger.AuditPanic() logger.Info(cmd.VersionString(clientName)) logs := make([]*publisher.Log, len(c.Common.CT.Logs)) 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)) } amqpConf := c.Publisher.AMQP var sac core.StorageAuthority if c.Publisher.SAService != nil { conn, err := bgrpc.ClientSetup(c.Publisher.SAService, scope) cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA") sac = bgrpc.NewStorageAuthorityClient(sapb.NewStorageAuthorityClient(conn)) } else { sac, err = rpc.NewStorageAuthorityClient(clientName, amqpConf, scope) cmd.FailOnError(err, "Unable to create SA client") } pubi := publisher.New( bundle, logs, c.Publisher.SubmissionTimeout.Duration, logger, scope, sac) var grpcSrv *grpc.Server if c.Publisher.GRPC != nil { s, l, err := bgrpc.NewServer(c.Publisher.GRPC, scope) cmd.FailOnError(err, "Unable to setup Publisher gRPC server") gw := bgrpc.NewPublisherServerWrapper(pubi) pubPB.RegisterPublisherServer(s, gw) go func() { err = s.Serve(l) cmd.FailOnError(err, "Publisher gRPC service failed") }() grpcSrv = s } pubs, err := rpc.NewAmqpRPCServer(amqpConf, c.Publisher.MaxConcurrentRPCServerRequests, scope, logger) cmd.FailOnError(err, "Unable to create Publisher RPC server") go cmd.CatchSignals(logger, func() { pubs.Stop() if grpcSrv != nil { grpcSrv.GracefulStop() } }) err = rpc.NewPublisherServer(pubs, pubi) cmd.FailOnError(err, "Unable to setup Publisher RPC server") go cmd.DebugServer(c.Publisher.DebugAddr) go cmd.ProfileCmd(scope) err = pubs.Start(amqpConf) cmd.FailOnError(err, "Unable to run Publisher RPC server") }
func newTestStats() metrics.Scope { c, _ := statsd.NewNoopClient() return metrics.NewStatsdScope(c, "fakesvc") }
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") err = features.Set(c.CA.Features) cmd.FailOnError(err, "Failed to set feature flags") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "CA") defer logger.AuditPanic() logger.Info(cmd.VersionString(clientName)) cmd.FailOnError(c.PA.CheckChallenges(), "Invalid PA configuration") 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(), scope, issuers, goodkey.NewKeyPolicy(), logger) cmd.FailOnError(err, "Failed to create CA impl") cai.PA = pa amqpConf := c.CA.AMQP if c.CA.SAService != nil { conn, err := bgrpc.ClientSetup(c.CA.SAService, scope) cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA") cai.SA = bgrpc.NewStorageAuthorityClient(sapb.NewStorageAuthorityClient(conn)) } else { cai.SA, err = rpc.NewStorageAuthorityClient(clientName, amqpConf, scope) cmd.FailOnError(err, "Failed to create SA client") } if amqpConf.Publisher != nil { cai.Publisher, err = rpc.NewPublisherClient(clientName, amqpConf, scope) cmd.FailOnError(err, "Failed to create Publisher client") } var grpcSrv *grpc.Server if c.CA.GRPC != nil { s, l, err := bgrpc.NewServer(c.CA.GRPC, scope) cmd.FailOnError(err, "Unable to setup CA gRPC server") caWrapper := bgrpc.NewCertificateAuthorityServer(cai) caPB.RegisterCertificateAuthorityServer(s, caWrapper) go func() { err = s.Serve(l) cmd.FailOnError(err, "CA gRPC service failed") }() grpcSrv = s } cas, err := rpc.NewAmqpRPCServer(amqpConf, c.CA.MaxConcurrentRPCServerRequests, scope, logger) cmd.FailOnError(err, "Unable to create CA RPC server") go cmd.CatchSignals(logger, func() { cas.Stop() if grpcSrv != nil { grpcSrv.GracefulStop() } }) err = rpc.NewCertificateAuthorityServer(cas, cai) cmd.FailOnError(err, "Failed to create Certificate Authority RPC server") go cmd.DebugServer(c.CA.DebugAddr) go cmd.ProfileCmd(scope) err = cas.Start(amqpConf) cmd.FailOnError(err, "Unable to run CA RPC server") }
func main() { configFile := flag.String("config", "", "File path to the configuration file for this service") certLimit := flag.Int("cert_limit", 0, "Count of certificates to process per expiration period") reconnBase := flag.Duration("reconnectBase", 1*time.Second, "Base sleep duration between reconnect attempts") reconnMax := flag.Duration("reconnectMax", 5*60*time.Second, "Max sleep duration between reconnect attempts after exponential backoff") 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") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "Expiration") defer logger.AuditPanic() logger.Info(cmd.VersionString(clientName)) if *certLimit > 0 { c.Mailer.CertLimit = *certLimit } // Default to 100 if no certLimit is set if c.Mailer.CertLimit == 0 { c.Mailer.CertLimit = 100 } // Configure DB dbURL, err := c.Mailer.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, c.Mailer.DBConfig.MaxDBConns) sa.SetSQLDebug(dbMap, logger) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(dbMap, scope) var sac core.StorageAuthority if c.Mailer.SAService != nil { conn, err := bgrpc.ClientSetup(c.Mailer.SAService, scope) cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA") sac = bgrpc.NewStorageAuthorityClient(sapb.NewStorageAuthorityClient(conn)) } else { sac, err = rpc.NewStorageAuthorityClient(clientName, c.Mailer.AMQP, scope) cmd.FailOnError(err, "Failed to create SA client") } // Load email template emailTmpl, err := ioutil.ReadFile(c.Mailer.EmailTemplate) cmd.FailOnError(err, fmt.Sprintf("Could not read email template file [%s]", c.Mailer.EmailTemplate)) tmpl, err := template.New("expiry-email").Parse(string(emailTmpl)) cmd.FailOnError(err, "Could not parse email template") fromAddress, err := netmail.ParseAddress(c.Mailer.From) cmd.FailOnError(err, fmt.Sprintf("Could not parse from address: %s", c.Mailer.From)) smtpPassword, err := c.Mailer.PasswordConfig.Pass() cmd.FailOnError(err, "Failed to load SMTP password") mailClient := bmail.New( c.Mailer.Server, c.Mailer.Port, c.Mailer.Username, smtpPassword, *fromAddress, logger, scope, *reconnBase, *reconnMax) nagCheckInterval := defaultNagCheckInterval if s := c.Mailer.NagCheckInterval; s != "" { nagCheckInterval, err = time.ParseDuration(s) if err != nil { logger.AuditErr(fmt.Sprintf("Failed to parse NagCheckInterval string %q: %s", s, err)) return } } var nags durationSlice for _, nagDuration := range c.Mailer.NagTimes { dur, err := time.ParseDuration(nagDuration) if err != nil { logger.AuditErr(fmt.Sprintf("Failed to parse nag duration string [%s]: %s", nagDuration, err)) return } nags = append(nags, dur+nagCheckInterval) } // Make sure durations are sorted in increasing order sort.Sort(nags) m := mailer{ stats: scope, subject: c.Mailer.Subject, log: logger, dbMap: dbMap, rs: sac, mailer: mailClient, emailTemplate: tmpl, nagTimes: nags, limit: c.Mailer.CertLimit, clk: cmd.Clock(), } go cmd.DebugServer(c.Mailer.DebugAddr) err = m.findExpiringCertificates() cmd.FailOnError(err, "expiration-mailer has failed") }
func main() { app := cmd.NewAppShell("boulder-va", "Handles challenge validation") app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) { go cmd.DebugServer(c.VA.DebugAddr) go cmd.ProfileCmd("VA", stats) pc := &cmd.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 } var caaClient caaPB.CAACheckerClient if c.VA.CAAService != nil { conn, err := bgrpc.ClientSetup(c.VA.CAAService) cmd.FailOnError(err, "Failed to load credentials and create connection to service") caaClient = caaPB.NewCAACheckerClient(conn) } scoped := metrics.NewStatsdScope(stats, "VA", "DNS") sbc := newGoogleSafeBrowsing(c.VA.GoogleSafeBrowsing) var cdrClient *cdr.CAADistributedResolver if c.VA.CAADistributedResolver != nil { var err error cdrClient, err = cdr.New( scoped, c.VA.CAADistributedResolver.Timeout.Duration, c.VA.CAADistributedResolver.MaxFailures, c.VA.CAADistributedResolver.Proxies, logger, ) cmd.FailOnError(err, "Failed to create CAADistributedResolver") } dnsTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse DNS timeout") dnsTries := c.VA.DNSTries if dnsTries < 1 { dnsTries = 1 } clk := clock.Default() var resolver bdns.DNSResolver if !c.Common.DNSAllowLoopbackAddresses { r := bdns.NewDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}, scoped, clk, dnsTries) r.LookupIPv6 = c.VA.LookupIPv6 resolver = r } else { r := bdns.NewTestDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}, scoped, clk, dnsTries) r.LookupIPv6 = c.VA.LookupIPv6 resolver = r } vai := va.NewValidationAuthorityImpl( pc, sbc, caaClient, cdrClient, resolver, c.VA.UserAgent, c.VA.IssuerDomain, stats, clk, logger) amqpConf := c.VA.AMQP if c.VA.GRPC != nil { s, l, err := bgrpc.NewServer(c.VA.GRPC, metrics.NewStatsdScope(stats, "VA")) cmd.FailOnError(err, "Unable to setup VA gRPC server") err = bgrpc.RegisterValidationAuthorityGRPCServer(s, vai) cmd.FailOnError(err, "Unable to register VA gRPC server") go func() { err = s.Serve(l) cmd.FailOnError(err, "VA gRPC service failed") }() } vas, err := rpc.NewAmqpRPCServer(amqpConf, c.VA.MaxConcurrentRPCServerRequests, stats, logger) cmd.FailOnError(err, "Unable to create VA RPC server") err = rpc.NewValidationAuthorityServer(vas, vai) cmd.FailOnError(err, "Unable to setup VA RPC server") err = vas.Start(amqpConf) cmd.FailOnError(err, "Unable to run VA RPC server") } app.Run() }
func main() { app := cmd.NewAppShell("expiration-mailer", "Sends certificate expiration emails") app.App.Flags = append(app.App.Flags, cli.IntFlag{ Name: "cert_limit", Value: 100, EnvVar: "CERT_LIMIT", Usage: "Count of certificates to process per expiration period", }) app.Config = func(c *cli.Context, config cmd.Config) cmd.Config { if c.GlobalInt("cert_limit") > 0 { config.Mailer.CertLimit = c.GlobalInt("cert_limit") } return config } app.Action = func(c cmd.Config, stats metrics.Statter, logger blog.Logger) { go cmd.DebugServer(c.Mailer.DebugAddr) // Configure DB dbURL, err := c.Mailer.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, c.Mailer.DBConfig.MaxDBConns) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "ExpirationMailer")) amqpConf := c.Mailer.AMQP sac, err := rpc.NewStorageAuthorityClient(clientName, amqpConf, stats) cmd.FailOnError(err, "Failed to create SA client") // Load email template emailTmpl, err := ioutil.ReadFile(c.Mailer.EmailTemplate) cmd.FailOnError(err, fmt.Sprintf("Could not read email template file [%s]", c.Mailer.EmailTemplate)) tmpl, err := template.New("expiry-email").Parse(string(emailTmpl)) cmd.FailOnError(err, "Could not parse email template") fromAddress, err := netmail.ParseAddress(c.Mailer.From) cmd.FailOnError(err, fmt.Sprintf("Could not parse from address: %s", c.Mailer.From)) smtpPassword, err := c.Mailer.PasswordConfig.Pass() cmd.FailOnError(err, "Failed to load SMTP password") mailClient := mail.New(c.Mailer.Server, c.Mailer.Port, c.Mailer.Username, smtpPassword, *fromAddress) err = mailClient.Connect() cmd.FailOnError(err, "Couldn't connect to mail server.") defer func() { _ = mailClient.Close() }() nagCheckInterval := defaultNagCheckInterval if s := c.Mailer.NagCheckInterval; s != "" { nagCheckInterval, err = time.ParseDuration(s) if err != nil { logger.AuditErr(fmt.Sprintf("Failed to parse NagCheckInterval string %q: %s", s, err)) return } } var nags durationSlice for _, nagDuration := range c.Mailer.NagTimes { dur, err := time.ParseDuration(nagDuration) if err != nil { logger.AuditErr(fmt.Sprintf("Failed to parse nag duration string [%s]: %s", nagDuration, err)) return } nags = append(nags, dur+nagCheckInterval) } // Make sure durations are sorted in increasing order sort.Sort(nags) subject := "Certificate expiration notice" if c.Mailer.Subject != "" { subject = c.Mailer.Subject } m := mailer{ stats: stats, subject: subject, log: logger, dbMap: dbMap, rs: sac, mailer: mailClient, emailTemplate: tmpl, nagTimes: nags, limit: c.Mailer.CertLimit, clk: cmd.Clock(), } err = m.findExpiringCertificates() cmd.FailOnError(err, "expiration-mailer has failed") } 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") err = features.Set(c.WFE.Features) cmd.FailOnError(err, "Failed to set feature flags") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "WFE") defer logger.AuditPanic() logger.Info(cmd.VersionString(clientName)) wfe, err := wfe.NewWebFrontEndImpl(scope, clock.Default(), goodkey.NewKeyPolicy(), logger) cmd.FailOnError(err, "Unable to create WFE") rac, sac := setupWFE(c, logger, scope) wfe.RA = rac wfe.SA = sac // TODO: remove this check once the production config uses the SubscriberAgreementURL in the wfe section if c.WFE.SubscriberAgreementURL != "" { wfe.SubscriberAgreementURL = c.WFE.SubscriberAgreementURL } else { wfe.SubscriberAgreementURL = c.SubscriberAgreementURL } wfe.AllowOrigins = c.WFE.AllowOrigins wfe.AcceptRevocationReason = c.WFE.AcceptRevocationReason wfe.AllowAuthzDeactivation = c.WFE.AllowAuthzDeactivation wfe.CertCacheDuration = c.WFE.CertCacheDuration.Duration wfe.CertNoCacheExpirationWindow = c.WFE.CertNoCacheExpirationWindow.Duration wfe.IndexCacheDuration = c.WFE.IndexCacheDuration.Duration wfe.IssuerCacheDuration = c.WFE.IssuerCacheDuration.Duration wfe.IssuerCert, err = cmd.LoadCert(c.Common.IssuerCert) cmd.FailOnError(err, fmt.Sprintf("Couldn't read issuer cert [%s]", c.Common.IssuerCert)) logger.Info(fmt.Sprintf("WFE using key policy: %#v", goodkey.NewKeyPolicy())) // Set up paths wfe.BaseURL = c.Common.BaseURL h := wfe.Handler() httpMonitor := metrics.NewHTTPMonitor(scope, h) logger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.WFE.ListenAddress)) srv := &http.Server{ Addr: c.WFE.ListenAddress, Handler: httpMonitor, } go cmd.DebugServer(c.WFE.DebugAddr) go cmd.ProfileCmd(scope) hd := &httpdown.HTTP{ StopTimeout: c.WFE.ShutdownStopTimeout.Duration, KillTimeout: c.WFE.ShutdownKillTimeout.Duration, Stats: metrics.NewFBAdapter(scope, clock.Default()), } hdSrv, err := hd.ListenAndServe(srv) cmd.FailOnError(err, "Error starting HTTP server") go cmd.CatchSignals(logger, func() { _ = hdSrv.Stop() }) forever := make(chan struct{}, 1) <-forever }
func main() { app := cli.NewApp() app.Name = "cert-checker" app.Usage = "Checks validity of issued certificates stored in the database" app.Version = cmd.Version() app.Author = "Boulder contributors" app.Email = "*****@*****.**" app.Flags = []cli.Flag{ cli.IntFlag{ Name: "workers", Value: runtime.NumCPU(), Usage: "The number of concurrent workers used to process certificates", }, cli.BoolFlag{ Name: "unexpired-only", Usage: "Only check currently unexpired certificates", }, cli.BoolFlag{ Name: "bad-results-only", Usage: "Only collect and display bad results", }, cli.StringFlag{ Name: "db-connect", Usage: "SQL URI if not provided in the configuration file", }, cli.StringFlag{ Name: "check-period", Value: "2160h", Usage: "How far back to check", }, cli.StringFlag{ Name: "config", Value: "config.json", Usage: "Path to configuration file", }, } app.Action = func(c *cli.Context) { configPath := c.GlobalString("config") if configPath == "" { fmt.Fprintln(os.Stderr, "--config is required") os.Exit(1) } configBytes, err := ioutil.ReadFile(configPath) cmd.FailOnError(err, "Failed to read config file") var config cmd.Config err = json.Unmarshal(configBytes, &config) cmd.FailOnError(err, "Failed to parse config file") stats, err := metrics.NewStatter(config.Statsd.Server, config.Statsd.Prefix) cmd.FailOnError(err, "Failed to create StatsD client") syslogger, err := syslog.Dial("", "", syslog.LOG_INFO|syslog.LOG_LOCAL0, "") cmd.FailOnError(err, "Failed to dial syslog") logger, err := blog.New(syslogger, 0, 0) cmd.FailOnError(err, "Failed to construct logger") err = blog.Set(logger) cmd.FailOnError(err, "Failed to set audit logger") if connect := c.GlobalString("db-connect"); connect != "" { config.CertChecker.DBConnect = connect } if workers := c.GlobalInt("workers"); workers != 0 { config.CertChecker.Workers = workers } config.CertChecker.UnexpiredOnly = c.GlobalBool("valid-only") config.CertChecker.BadResultsOnly = c.GlobalBool("bad-results-only") if cp := c.GlobalString("check-period"); cp != "" { config.CertChecker.CheckPeriod.Duration, err = time.ParseDuration(cp) cmd.FailOnError(err, "Failed to parse check period") } // Validate PA config and set defaults if needed cmd.FailOnError(config.PA.CheckChallenges(), "Invalid PA configuration") saDbURL, err := config.CertChecker.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") saDbMap, err := sa.NewDbMap(saDbURL, config.CertChecker.DBConfig.MaxDBConns) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(saDbMap, metrics.NewStatsdScope(stats, "CertChecker")) pa, err := policy.New(config.PA.Challenges) cmd.FailOnError(err, "Failed to create PA") err = pa.SetHostnamePolicyFile(config.CertChecker.HostnamePolicyFile) cmd.FailOnError(err, "Failed to load HostnamePolicyFile") checker := newChecker( saDbMap, clock.Default(), pa, config.CertChecker.CheckPeriod.Duration, ) fmt.Fprintf(os.Stderr, "# Getting certificates issued in the last %s\n", config.CertChecker.CheckPeriod) // Since we grab certificates in batches we don't want this to block, when it // is finished it will close the certificate channel which allows the range // loops in checker.processCerts to break go func() { err = checker.getCerts(config.CertChecker.UnexpiredOnly) cmd.FailOnError(err, "Batch retrieval of certificates failed") }() fmt.Fprintf(os.Stderr, "# Processing certificates using %d workers\n", config.CertChecker.Workers) wg := new(sync.WaitGroup) for i := 0; i < config.CertChecker.Workers; i++ { wg.Add(1) go func() { s := checker.clock.Now() checker.processCerts(wg, config.CertChecker.BadResultsOnly) stats.TimingDuration("certChecker.processingLatency", time.Since(s), 1.0) }() } wg.Wait() fmt.Fprintf( os.Stderr, "# Finished processing certificates, sample: %d, good: %d, bad: %d\n", len(checker.issuedReport.Entries), checker.issuedReport.GoodCerts, checker.issuedReport.BadCerts, ) err = checker.issuedReport.dump() cmd.FailOnError(err, "Failed to dump results: %s\n") } err := app.Run(os.Args) cmd.FailOnError(err, "Failed to run application") }
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, config.DBConfig.MaxDBConns) cmd.FailOnError(err, "Could not connect to database") sa.SetSQLDebug(dbMap, logger) go sa.ReportDbConnCount(dbMap, metrics.NewStatsdScope(stats, "OCSPResponder")) 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-ra", "Handles service orchestration") 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.RA.DebugAddr) pa, err := policy.New(c.PA.Challenges) cmd.FailOnError(err, "Couldn't create PA") if c.RA.HostnamePolicyFile == "" { cmd.FailOnError(fmt.Errorf("HostnamePolicyFile must be provided."), "") } err = pa.SetHostnamePolicyFile(c.RA.HostnamePolicyFile) cmd.FailOnError(err, "Couldn't load hostname policy file") 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(), logger, stats, dc, rateLimitPolicies, c.RA.MaxContactsPerRegistration, c.KeyPolicy(), c.RA.UseNewVARPC) rai.PA = pa raDNSTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse RA DNS timeout") scoped := metrics.NewStatsdScope(stats, "RA", "DNS") dnsTries := c.RA.DNSTries if dnsTries < 1 { dnsTries = 1 } if !c.Common.DNSAllowLoopbackAddresses { rai.DNSResolver = bdns.NewDNSResolverImpl(raDNSTimeout, []string{c.Common.DNSResolver}, scoped, clock.Default(), dnsTries) } else { rai.DNSResolver = bdns.NewTestDNSResolverImpl(raDNSTimeout, []string{c.Common.DNSResolver}, scoped, clock.Default(), dnsTries) } 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") err = rpc.NewRegistrationAuthorityServer(ras, rai) cmd.FailOnError(err, "Unable to setup RA RPC server") err = ras.Start(amqpConf) cmd.FailOnError(err, "Unable to run RA RPC server") } app.Run() }
func main() { configFile := flag.String("config", "", "File path to the configuration file for this service") workers := flag.Int("workers", runtime.NumCPU(), "The number of concurrent workers used to process certificates") badResultsOnly := flag.Bool("bad-results-only", false, "Only collect and display bad results") connect := flag.String("db-connect", "", "SQL URI if not provided in the configuration file") cp := flag.Duration("check-period", time.Hour*2160, "How far back to check") unexpiredOnly := flag.Bool("unexpired-only", false, "Only check currently unexpired certificates") flag.Parse() if *configFile == "" { flag.Usage() os.Exit(1) } var config config err := cmd.ReadConfigFile(*configFile, &config) cmd.FailOnError(err, "Reading JSON config file into config structure") err = features.Set(config.CertChecker.Features) cmd.FailOnError(err, "Failed to set feature flags") stats, err := metrics.NewStatter(config.Statsd.Server, config.Statsd.Prefix) cmd.FailOnError(err, "Failed to create StatsD client") syslogger, err := syslog.Dial("", "", syslog.LOG_INFO|syslog.LOG_LOCAL0, "") cmd.FailOnError(err, "Failed to dial syslog") logger, err := blog.New(syslogger, 0, 0) cmd.FailOnError(err, "Failed to construct logger") err = blog.Set(logger) cmd.FailOnError(err, "Failed to set audit logger") if *connect != "" { config.CertChecker.DBConnect = *connect } if *workers != 0 { config.CertChecker.Workers = *workers } config.CertChecker.UnexpiredOnly = *unexpiredOnly config.CertChecker.BadResultsOnly = *badResultsOnly config.CertChecker.CheckPeriod.Duration = *cp // Validate PA config and set defaults if needed cmd.FailOnError(config.PA.CheckChallenges(), "Invalid PA configuration") saDbURL, err := config.CertChecker.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") saDbMap, err := sa.NewDbMap(saDbURL, config.CertChecker.DBConfig.MaxDBConns) cmd.FailOnError(err, "Could not connect to database") go sa.ReportDbConnCount(saDbMap, metrics.NewStatsdScope(stats, "CertChecker")) pa, err := policy.New(config.PA.Challenges) cmd.FailOnError(err, "Failed to create PA") err = pa.SetHostnamePolicyFile(config.CertChecker.HostnamePolicyFile) cmd.FailOnError(err, "Failed to load HostnamePolicyFile") checker := newChecker( saDbMap, clock.Default(), pa, config.CertChecker.CheckPeriod.Duration, ) fmt.Fprintf(os.Stderr, "# Getting certificates issued in the last %s\n", config.CertChecker.CheckPeriod) // Since we grab certificates in batches we don't want this to block, when it // is finished it will close the certificate channel which allows the range // loops in checker.processCerts to break go func() { err = checker.getCerts(config.CertChecker.UnexpiredOnly) cmd.FailOnError(err, "Batch retrieval of certificates failed") }() fmt.Fprintf(os.Stderr, "# Processing certificates using %d workers\n", config.CertChecker.Workers) wg := new(sync.WaitGroup) for i := 0; i < config.CertChecker.Workers; i++ { wg.Add(1) go func() { s := checker.clock.Now() checker.processCerts(wg, config.CertChecker.BadResultsOnly) stats.TimingDuration("certChecker.processingLatency", time.Since(s), 1.0) }() } wg.Wait() fmt.Fprintf( os.Stderr, "# Finished processing certificates, sample: %d, good: %d, bad: %d\n", len(checker.issuedReport.Entries), checker.issuedReport.GoodCerts, checker.issuedReport.BadCerts, ) err = checker.issuedReport.dump() cmd.FailOnError(err, "Failed to dump results: %s\n") }
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") err = features.Set(c.SA.Features) cmd.FailOnError(err, "Failed to set feature flags") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "SA") 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, scope) sai, err := sa.NewSQLStorageAuthority(dbMap, clock.Default(), logger) cmd.FailOnError(err, "Failed to create SA impl") var grpcSrv *grpc.Server if c.SA.GRPC != nil { var listener net.Listener grpcSrv, listener, err = bgrpc.NewServer(c.SA.GRPC, scope) cmd.FailOnError(err, "Unable to setup SA gRPC server") gw := bgrpc.NewStorageAuthorityServer(sai) sapb.RegisterStorageAuthorityServer(grpcSrv, gw) go func() { err = grpcSrv.Serve(listener) cmd.FailOnError(err, "SA gRPC service failed") }() } amqpConf := saConf.AMQP sas, err := rpc.NewAmqpRPCServer(amqpConf, c.SA.MaxConcurrentRPCServerRequests, scope, logger) cmd.FailOnError(err, "Unable to create SA RPC server") go cmd.CatchSignals(logger, func() { sas.Stop() if grpcSrv != nil { grpcSrv.GracefulStop() } }) err = rpc.NewStorageAuthorityServer(sas, sai) cmd.FailOnError(err, "Unable to setup SA RPC server") go cmd.DebugServer(c.SA.DebugAddr) go cmd.ProfileCmd(scope) err = sas.Start(amqpConf) cmd.FailOnError(err, "Unable to run SA RPC server") }
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") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "VA") defer logger.AuditPanic() logger.Info(cmd.VersionString(clientName)) pc := &cmd.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) var cdrClient *cdr.CAADistributedResolver if c.VA.CAADistributedResolver != nil { var err error cdrClient, err = cdr.New( scope, c.VA.CAADistributedResolver.Timeout.Duration, c.VA.CAADistributedResolver.MaxFailures, c.VA.CAADistributedResolver.Proxies, logger) cmd.FailOnError(err, "Failed to create CAADistributedResolver") } dnsTimeout, err := time.ParseDuration(c.Common.DNSTimeout) cmd.FailOnError(err, "Couldn't parse DNS timeout") dnsTries := c.VA.DNSTries if dnsTries < 1 { dnsTries = 1 } clk := clock.Default() caaSERVFAILExceptions, err := bdns.ReadHostList(c.VA.CAASERVFAILExceptions) cmd.FailOnError(err, "Couldn't read CAASERVFAILExceptions file") var resolver bdns.DNSResolver if !c.Common.DNSAllowLoopbackAddresses { r := bdns.NewDNSResolverImpl( dnsTimeout, []string{c.Common.DNSResolver}, caaSERVFAILExceptions, scope, clk, dnsTries) resolver = r } else { r := bdns.NewTestDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver}, scope, clk, dnsTries) resolver = r } vai := va.NewValidationAuthorityImpl( pc, sbc, cdrClient, resolver, c.VA.UserAgent, c.VA.IssuerDomain, scope, clk, logger) amqpConf := c.VA.AMQP var grpcSrv *grpc.Server if c.VA.GRPC != nil { s, l, err := bgrpc.NewServer(c.VA.GRPC, scope) cmd.FailOnError(err, "Unable to setup VA gRPC server") err = bgrpc.RegisterValidationAuthorityGRPCServer(s, vai) cmd.FailOnError(err, "Unable to register VA gRPC server") go func() { err = s.Serve(l) cmd.FailOnError(err, "VA gRPC service failed") }() grpcSrv = s } vas, err := rpc.NewAmqpRPCServer(amqpConf, c.VA.MaxConcurrentRPCServerRequests, scope, logger) cmd.FailOnError(err, "Unable to create VA RPC server") go cmd.CatchSignals(logger, func() { vas.Stop() if grpcSrv != nil { grpcSrv.GracefulStop() } }) err = rpc.NewValidationAuthorityServer(vas, vai) cmd.FailOnError(err, "Unable to setup VA RPC server") go cmd.DebugServer(c.VA.DebugAddr) go cmd.ProfileCmd(scope) err = vas.Start(amqpConf) cmd.FailOnError(err, "Unable to run VA RPC server") }