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 TestGetAndProcessCerts(t *testing.T) { saDbMap, err := sa.NewDbMap(saDbConnStr) test.AssertNotError(t, err, "Couldn't connect to database") paDbMap, err := sa.NewDbMap(paDbConnStr) test.AssertNotError(t, err, "Couldn't connect to policy database") fc := clock.NewFake() checker := newChecker(saDbMap, paDbMap, fc, false) sa, err := sa.NewSQLStorageAuthority(saDbMap, fc) test.AssertNotError(t, err, "Couldn't create SA to insert certificates") saCleanUp := test.ResetTestDatabase(t, saDbMap.Db) paCleanUp := test.ResetTestDatabase(t, paDbMap.Db) defer func() { saCleanUp() paCleanUp() }() testKey, _ := rsa.GenerateKey(rand.Reader, 1024) // Problems // Expiry period is too long rawCert := x509.Certificate{ Subject: pkix.Name{ CommonName: "not-blacklisted.com", }, BasicConstraintsValid: true, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } reg, err := sa.NewRegistration(core.Registration{ Key: satest.GoodJWK(), }) test.AssertNotError(t, err, "Couldn't create registration") for i := int64(0); i < 5; i++ { rawCert.SerialNumber = big.NewInt(i) certDER, err := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) test.AssertNotError(t, err, "Couldn't create certificate") _, err = sa.AddCertificate(certDER, reg.ID) test.AssertNotError(t, err, "Couldn't add certificate") } err = checker.getCerts() test.AssertNotError(t, err, "Failed to retrieve certificates") test.AssertEquals(t, len(checker.certs), 5) wg := new(sync.WaitGroup) wg.Add(1) checker.processCerts(wg) test.AssertEquals(t, checker.issuedReport.BadCerts, int64(5)) test.AssertEquals(t, len(checker.issuedReport.Entries), 5) }
func setupContext(context *cli.Context) (rpc.CertificateAuthorityClient, *blog.AuditLogger, *gorp.DbMap, rpc.StorageAuthorityClient) { c, err := loadConfig(context) cmd.FailOnError(err, "Failed to load Boulder configuration") 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") blog.SetAuditLogger(auditlogger) ch, err := rpc.AmqpChannel(c) cmd.FailOnError(err, "Could not connect to AMQP") caRPC, err := rpc.NewAmqpRPCClient("revoker->CA", c.AMQP.CA.Server, ch) cmd.FailOnError(err, "Unable to create RPC client") cac, err := rpc.NewCertificateAuthorityClient(caRPC) cmd.FailOnError(err, "Unable to create CA client") dbMap, err := sa.NewDbMap(c.Revoker.DBConnect) cmd.FailOnError(err, "Couldn't setup database connection") saRPC, err := rpc.NewAmqpRPCClient("AdminRevoker->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") return cac, auditlogger, dbMap, sac }
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 makeDBSource(dbConnect, issuerCert string, sqlDebug bool) (cfocsp.Source, error) { var noSource cfocsp.Source // Configure DB dbMap, err := sa.NewDbMap(dbConnect) if err != nil { return noSource, fmt.Errorf("Could not connect to database: %s", err) } sa.SetSQLDebug(dbMap, sqlDebug) // Load the CA's key so we can store its SubjectKey in the DB caCertDER, err := cmd.LoadCert(issuerCert) if err != nil { return noSource, fmt.Errorf("Could not read issuer cert %s: %s", issuerCert, err) } caCert, err := x509.ParseCertificate(caCertDER) if err != nil { return noSource, fmt.Errorf("Could not parse issuer cert %s: %s", issuerCert, err) } if len(caCert.SubjectKeyId) == 0 { return noSource, fmt.Errorf("Empty subjectKeyID") } // Construct source from DB return NewSourceFromDatabase(dbMap, caCert.SubjectKeyId) }
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 setup(t *testing.T) testCtx { log := blog.UseMock() // Using DBConnSAFullPerms to be able to insert registrations and certificates dbMap, err := sa.NewDbMap(vars.DBConnSAFullPerms, 0) if err != nil { t.Fatalf("Couldn't connect the database: %s", err) } cleanUp := test.ResetSATestDatabase(t) fc := newFakeClock(t) ssa, err := sa.NewSQLStorageAuthority(dbMap, fc, log) if err != nil { t.Fatalf("unable to create SQLStorageAuthority: %s", err) } return testCtx{ c: contactExporter{ dbMap: dbMap, log: log, clk: fc, }, ssa: ssa, cleanUp: cleanUp, } }
func BenchmarkCheckCert(b *testing.B) { dbMap, err := sa.NewDbMap(dbConnStr) if err != nil { fmt.Println("Couldn't connect to database") return } checker := newChecker(dbMap) testKey, _ := rsa.GenerateKey(rand.Reader, 1024) expiry := time.Now().AddDate(0, 0, 1) serial := big.NewInt(1337) rawCert := x509.Certificate{ Subject: pkix.Name{ CommonName: "example.com", }, NotAfter: expiry, DNSNames: []string{"example-a.com"}, SerialNumber: serial, } certDer, _ := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) cert := core.Certificate{ Status: core.StatusValid, Serial: core.SerialToString(serial), Digest: core.Fingerprint256(certDer), DER: certDer, Issued: time.Now(), Expires: expiry, } b.ResetTimer() for i := 0; i < b.N; i++ { checker.checkCert(cert) } }
func setup(t *testing.T) (*OCSPUpdater, core.StorageAuthority, *gorp.DbMap, clock.FakeClock, func()) { dbMap, err := sa.NewDbMap(vars.DBConnSA) test.AssertNotError(t, err, "Failed to create dbMap") fc := clock.NewFake() fc.Add(1 * time.Hour) sa, err := sa.NewSQLStorageAuthority(dbMap, fc) test.AssertNotError(t, err, "Failed to create SA") cleanUp := test.ResetSATestDatabase(t) stats, _ := statsd.NewNoopClient(nil) updater, err := newUpdater( stats, fc, dbMap, &mockCA{}, &mockPub{sa}, sa, cmd.OCSPUpdaterConfig{ NewCertificateBatchSize: 1, OldOCSPBatchSize: 1, MissingSCTBatchSize: 1, NewCertificateWindow: cmd.ConfigDuration{Duration: time.Second}, OldOCSPWindow: cmd.ConfigDuration{Duration: time.Second}, MissingSCTWindow: cmd.ConfigDuration{Duration: time.Second}, }, 0, "", ) return updater, sa, dbMap, fc, cleanUp }
func setup(t *testing.T) (OCSPUpdater, core.StorageAuthority, *gorp.DbMap, clock.FakeClock, func()) { dbMap, err := sa.NewDbMap(dbConnStr) test.AssertNotError(t, err, "Failed to create dbMap") fc := clock.NewFake() fc.Add(1 * time.Hour) sa, err := sa.NewSQLStorageAuthority(dbMap, fc) test.AssertNotError(t, err, "Failed to create SA") cleanUp := test.ResetSATestDatabase(t) stats, _ := statsd.NewNoopClient(nil) updater := OCSPUpdater{ dbMap: dbMap, clk: fc, cac: &mockCA{}, pubc: &mockPub{sa}, sac: sa, stats: stats, log: blog.GetAuditLogger(), } return updater, sa, dbMap, fc, cleanUp }
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", "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 setup(t *testing.T, nagTimes []time.Duration) *testCtx { dbMap, err := sa.NewDbMap(dbConnStr) if err != nil { t.Fatalf("Couldn't connect the database: %s", err) } fc := clock.NewFake() ssa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("unable to create SQLStorageAuthority: %s", err) } cleanUp := test.ResetTestDatabase(t, dbMap.Db) stats, _ := statsd.NewNoopClient(nil) mc := &mockMail{} m := &mailer{ log: blog.GetAuditLogger(), stats: stats, mailer: mc, emailTemplate: tmpl, dbMap: dbMap, rs: ssa, nagTimes: nagTimes, limit: 100, clk: fc, } return &testCtx{ dbMap: dbMap, ssa: ssa, mc: mc, fc: fc, m: m, cleanUp: cleanUp, } }
func TestParseLine(t *testing.T) { dbMap, err := sa.NewDbMap(vars.DBConnSA) if err != nil { t.Fatalf("Failed to create dbMap: %s", err) } fc := clock.NewFake() fc.Set(time.Date(2015, 3, 4, 5, 0, 0, 0, time.UTC)) sa, err := sa.NewSQLStorageAuthority(dbMap, fc) if err != nil { t.Fatalf("Failed to create SA: %s", err) } defer test.ResetSATestDatabase(t)() logger := blog.GetAuditLogger() found, added := parseLogLine(sa, logger, "") test.AssertEquals(t, found, false) test.AssertEquals(t, added, false) found, added = parseLogLine(sa, logger, "0000-00-00T00:00:00+00:00 hostname boulder-ca[pid]: [AUDIT] Failed RPC to store at SA, orphaning certificate: b64der=[] err=[AMQP-RPC timeout], regID=[1337]") test.AssertEquals(t, found, true) test.AssertEquals(t, added, false) found, added = parseLogLine(sa, logger, "0000-00-00T00:00:00+00:00 hostname boulder-ca[pid]: [AUDIT] Failed RPC to store at SA, orphaning certificate: b64der=[deadbeef] err=[AMQP-RPC timeout], regID=[]") test.AssertEquals(t, found, true) test.AssertEquals(t, added, false) reg := satest.CreateWorkingRegistration(t, sa) found, added = parseLogLine(sa, logger, fmt.Sprintf("0000-00-00T00:00:00+00:00 hostname boulder-ca[pid]: [AUDIT] Failed RPC to store at SA, orphaning certificate: b64der=[MIIEWzCCA0OgAwIBAgITAP+gFgYw1hiy61wFEIJLFCdIVjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRoYXBweSBoYWNrZXIgZmFrZSBDQTAeFw0xNTEwMDMwNTIxMDBaFw0xNjAxMDEwNTIxMDBaMBgxFjAUBgNVBAMTDWV4YW1wbGUuY28uYm4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCeo/HSH63lWW42pqdwlalHWOS3JGa3REraT3xM9v3psdRwuTtlwf3YlpF/JIzK5JtXyA3CHGSwEGmUMhMNBZ0tg5I0booXnHyUeDVUnGSnpWgMUY+vCly+pI5oT8pjBHdcj6kjnDTx1cstBjsJi9HBcYPHUh78iEZBsvC0FAKsh8cHaEjUNHzvWd1anBdK0lRn25M8le9IxXi6di9SeyFmahmPteH+LYKZtNzrF5HpatB14+ywV8d212T62PCCnUPDLd+YWjo2+t5pZs7IlGhyGh7EerOOrI2kUUBg3tUdKDp4e3xplxvaAfSfdrqkGx+bQ0iqQnng+lVkXWYWRB8NAgMBAAGjggGVMIIBkTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDadDBAEUrnrP/566FLp6DmjrlrbMB8GA1UdIwQYMBaAFPt4TxL5YBWDLJ8XfzQZsy426kGJMGoGCCsGAQUFBwEBBF4wXDAmBggrBgEFBQcwAYYaaHR0cDovL2xvY2FsaG9zdDo0MDAyL29jc3AwMgYIKwYBBQUHMAKGJmh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hY21lL2lzc3Vlci1jZXJ0MBgGA1UdEQQRMA+CDWV4YW1wbGUuY28uYm4wJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL2V4YW1wbGUuY29tL2NybDBjBgNVHSAEXDBaMAoGBmeBDAECATAAMEwGAyoDBDBFMCIGCCsGAQUFBwIBFhZodHRwOi8vZXhhbXBsZS5jb20vY3BzMB8GCCsGAQUFBwICMBMMEURvIFdoYXQgVGhvdSBXaWx0MA0GCSqGSIb3DQEBCwUAA4IBAQC7tLmUlxyvouVuIljbRtiL+zYdi/zXVSHAMXTkceqp8/8ucZBZu1fMBkB5SW2FUFd8EnuqhKGOeS3dNr9Pe4dLbUDR0UKIwV045Na+Jet4BbHDdWs3NXAutFhdGIa8ivLBQIbTzlBuVRhJE8g6qqjf5hYL0DXkLNptl2l+0+4xJMm/liCp/mYCGRwbdGUzwdSjACO76QLLSqZhkBF37ZJOuDbJTMBi3QzkOcTs6e4d/gSZpCy7yy6nJDxZ9N9P3XBYIpus+aZAYy29d2shYzE3st8cQfB2Wmb0SHd67sftTAzeudiiNW/4E4IKKH4R1S794apUO07y7pkqep1cz32k] err=[AMQP-RPC timeout], regID=[%d]", reg.ID)) test.AssertEquals(t, found, true) test.AssertEquals(t, added, true) }
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() { 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("external-cert-importer", "Imports external certificates for POP checks") app.App.Flags = append(app.App.Flags, cli.StringFlag{ Name: "a, valid-certs-file", Value: "ssl-observatory-valid-certs.csv", Usage: "The CSV file containing the valid certs to import.", }, cli.StringFlag{ Name: "d, domains-file", Value: "ssl-observatory-domains.csv", Usage: "The CSV file containing the domains associated with the certs that are being imported.", }, cli.StringFlag{ Name: "r, invalid-certs-file", Value: "ssl-observatory-invalid-certs.csv", Usage: "The CSV file Containing now invalid certs which should be removed.", }, cli.Float64Flag{ Name: "statsd-rate", Value: 0.1, Usage: "A floating point number between 0 and 1 representing the rate at which the statsd client will send data.", }) app.Config = func(c *cli.Context, config cmd.Config) cmd.Config { fmt.Println(c.Args()) config.ExternalCertImporter.CertsToImportCSVFilename = c.GlobalString("a") config.ExternalCertImporter.DomainsToImportCSVFilename = c.GlobalString("d") config.ExternalCertImporter.CertsToRemoveCSVFilename = c.GlobalString("r") config.ExternalCertImporter.StatsdRate = float32(math.Min(math.Max(c.Float64("statsd-rate"), 0.0), 1.0)) return config } 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") blog.SetAuditLogger(auditlogger) // Configure DB dbMap, err := sa.NewDbMap(c.PA.DBConnect) cmd.FailOnError(err, "Could not connect to database") dbMap.AddTableWithName(core.ExternalCert{}, "externalCerts").SetKeys(false, "SHA1") dbMap.AddTableWithName(core.IdentifierData{}, "identifierData").SetKeys(false, "CertSHA1") // Note that this order of operations is intentional: we first add // new certs to the database. Then, since certs are identified by // the entries in the identifiers table, we add those. Then, we // can remove invalid certs (which first removes the associated // identifiers). addCerts(c.ExternalCertImporter.CertsToImportCSVFilename, dbMap, stats, c.ExternalCertImporter.StatsdRate) addIdentifiers(c.ExternalCertImporter.DomainsToImportCSVFilename, dbMap, stats, c.ExternalCertImporter.StatsdRate) removeInvalidCerts(c.ExternalCertImporter.CertsToRemoveCSVFilename, dbMap, stats, c.ExternalCertImporter.StatsdRate) } app.Run() }
func TestDontFindRevokedCert(t *testing.T) { expiresIn := 24 * time.Hour ctx := setup(t, []time.Duration{expiresIn}) var keyA jose.JsonWebKey err := json.Unmarshal(jsonKeyA, &keyA) test.AssertNotError(t, err, "Failed to unmarshal public JWK") emailA, _ := core.ParseAcmeURL("mailto:[email protected]") regA := core.Registration{ ID: 1, Contact: []*core.AcmeURL{ emailA, }, Key: keyA, InitialIP: net.ParseIP("6.5.5.6"), } regA, err = ctx.ssa.NewRegistration(regA) if err != nil { t.Fatalf("Couldn't store regA: %s", err) } rawCertA := x509.Certificate{ Subject: pkix.Name{ CommonName: "happy A", }, NotAfter: ctx.fc.Now().Add(expiresIn), DNSNames: []string{"example-a.com"}, SerialNumber: big.NewInt(1337), } certDerA, _ := x509.CreateCertificate(rand.Reader, &rawCertA, &rawCertA, &testKey.PublicKey, &testKey) certA := &core.Certificate{ RegistrationID: regA.ID, Serial: "001", Expires: rawCertA.NotAfter, DER: certDerA, } certStatusA := &core.CertificateStatus{ Serial: "001", Status: core.OCSPStatusRevoked, } setupDBMap, err := sa.NewDbMap("mysql+tcp://test_setup@localhost:3306/boulder_sa_test") err = setupDBMap.Insert(certA) test.AssertNotError(t, err, "unable to insert Certificate") err = setupDBMap.Insert(certStatusA) test.AssertNotError(t, err, "unable to insert CertificateStatus") err = ctx.m.findExpiringCertificates() test.AssertNotError(t, err, "err from findExpiringCertificates") if len(ctx.mc.Messages) != 0 { t.Errorf("no emails should have been sent, but sent %d", len(ctx.mc.Messages)) } }
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 BenchmarkCheckCert(b *testing.B) { saDbMap, err := sa.NewDbMap(vars.DBConnSA) if err != nil { fmt.Println("Couldn't connect to database") return } paDbMap, err := sa.NewDbMap(vars.DBConnPolicy) if err != nil { fmt.Println("Couldn't connect to database") return } defer func() { err = saDbMap.TruncateTables() fmt.Printf("Failed to truncate tables: %s\n", err) err = paDbMap.TruncateTables() fmt.Printf("Failed to truncate tables: %s\n", err) }() checker := newChecker(saDbMap, paDbMap, clock.Default(), false, nil) testKey, _ := rsa.GenerateKey(rand.Reader, 1024) expiry := time.Now().AddDate(0, 0, 1) serial := big.NewInt(1337) rawCert := x509.Certificate{ Subject: pkix.Name{ CommonName: "example.com", }, NotAfter: expiry, DNSNames: []string{"example-a.com"}, SerialNumber: serial, } certDer, _ := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) cert := core.Certificate{ Serial: core.SerialToString(serial), Digest: core.Fingerprint256(certDer), DER: certDer, Issued: time.Now(), Expires: expiry, } b.ResetTimer() for i := 0; i < b.N; i++ { checker.checkCert(cert) } }
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 padbImpl(t *testing.T) (*PolicyAuthorityDatabaseImpl, func()) { dbMap, err := sa.NewDbMap(vars.DBConnPolicy) test.AssertNotError(t, err, "Could not construct dbMap") padb, err := NewPolicyAuthorityDatabaseImpl(dbMap) test.AssertNotError(t, err, "Couldn't create PADB") cleanUp := test.ResetPolicyTestDatabase(t) return padb, cleanUp }
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 paImpl(t *testing.T) (*PolicyAuthorityImpl, func()) { dbMap, err := sa.NewDbMap(dbConnStr) test.AssertNotError(t, err, "Could not construct dbMap") pa, err := NewPolicyAuthorityImpl(dbMap, false) test.AssertNotError(t, err, "Couldn't create PADB") cleanUp := test.ResetTestDatabase(t, dbMap.Db) return pa, cleanUp }
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() }
// This is an unfortunate bit of tech debt that is being taken on in // order to get the more important change of using MySQL/MariaDB in // all of our tests working without SQLite. We already had issues with // the RA here getting a real CertificateAuthority instead of a // CertificateAuthorityClient, so this is only marginally worse. // TODO(Issue #628): use a CAClient fake instead of a CAImpl instance func caDBImpl(t *testing.T) (core.CertificateAuthorityDatabase, func()) { dbMap, err := sa.NewDbMap(caDBConnStr) if err != nil { t.Fatalf("Could not construct dbMap: %s", err) } cadb, err := ca.NewCertificateAuthorityDatabaseImpl(dbMap) if err != nil { t.Fatalf("Could not construct CA DB: %s", err) } cleanUp := test.ResetTestDatabase(t, dbMap.Db) return cadb, cleanUp }
func main() { outFile := flag.String("outfile", "", "File to write contacts to (defaults to stdout).") grace := flag.Duration("grace", 2*24*time.Hour, "Include contacts with certificates that expired in < grace ago") type config struct { ContactExporter struct { cmd.DBConfig cmd.PasswordConfig } } 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 *outFile == "" || *configFile == "" { flag.Usage() os.Exit(1) } _, log := cmd.StatsAndLogging(cmd.StatsdConfig{}, cmd.SyslogConfig{StdoutLevel: 7}) 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") dbURL, err := cfg.ContactExporter.DBConfig.URL() cmd.FailOnError(err, "Couldn't load DB URL") dbMap, err := sa.NewDbMap(dbURL, 10) cmd.FailOnError(err, "Could not connect to database") exporter := contactExporter{ log: log, dbMap: dbMap, clk: cmd.Clock(), grace: *grace, } contacts, err := exporter.findContacts() cmd.FailOnError(err, "Could not find contacts") err = writeContacts(contacts, *outFile) cmd.FailOnError(err, fmt.Sprintf("Could not write contacts to outfile %q", *outFile)) }
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() }