func TestAddCertificate(t *testing.T) { // Enable the feature for the `CertStatusOptimizationsMigrated` flag so that // adding a new certificate will populate the `certificateStatus.NotAfter` // field correctly. This will let the unit test assertion for `NotAfter` // pass provided everything is working as intended. Note: this must be done // **before** the DbMap is created in `initSA()` or the feature flag won't be // set correctly at the time the table maps are set up. _ = features.Set(map[string]bool{"CertStatusOptimizationsMigrated": true}) defer features.Reset() sa, _, cleanUp := initSA(t) defer cleanUp() reg := satest.CreateWorkingRegistration(t, sa) // An example cert taken from EFF's website certDER, err := ioutil.ReadFile("www.eff.org.der") test.AssertNotError(t, err, "Couldn't read example cert DER") digest, err := sa.AddCertificate(ctx, certDER, reg.ID) test.AssertNotError(t, err, "Couldn't add www.eff.org.der") test.AssertEquals(t, digest, "qWoItDZmR4P9eFbeYgXXP3SR4ApnkQj8x4LsB_ORKBo") retrievedCert, err := sa.GetCertificate(ctx, "000000000000000000000000000000021bd4") test.AssertNotError(t, err, "Couldn't get www.eff.org.der by full serial") test.AssertByteEquals(t, certDER, retrievedCert.DER) certificateStatus, err := sa.GetCertificateStatus(ctx, "000000000000000000000000000000021bd4") test.AssertNotError(t, err, "Couldn't get status for www.eff.org.der") test.Assert(t, !certificateStatus.SubscriberApproved, "SubscriberApproved should be false") test.Assert(t, certificateStatus.Status == core.OCSPStatusGood, "OCSP Status should be good") test.Assert(t, certificateStatus.OCSPLastUpdated.IsZero(), "OCSPLastUpdated should be nil") test.AssertEquals(t, certificateStatus.NotAfter, retrievedCert.Expires) // Test cert generated locally by Boulder / CFSSL, names [example.com, // www.example.com, admin.example.com] certDER2, err := ioutil.ReadFile("test-cert.der") test.AssertNotError(t, err, "Couldn't read example cert DER") serial := "ffdd9b8a82126d96f61d378d5ba99a0474f0" digest2, err := sa.AddCertificate(ctx, certDER2, reg.ID) test.AssertNotError(t, err, "Couldn't add test-cert.der") test.AssertEquals(t, digest2, "vrlPN5wIPME1D2PPsCy-fGnTWh8dMyyYQcXPRkjHAQI") retrievedCert2, err := sa.GetCertificate(ctx, serial) test.AssertNotError(t, err, "Couldn't get test-cert.der") test.AssertByteEquals(t, certDER2, retrievedCert2.DER) certificateStatus2, err := sa.GetCertificateStatus(ctx, serial) test.AssertNotError(t, err, "Couldn't get status for test-cert.der") test.Assert(t, !certificateStatus2.SubscriberApproved, "SubscriberApproved should be false") test.Assert(t, certificateStatus2.Status == core.OCSPStatusGood, "OCSP Status should be good") test.Assert(t, certificateStatus2.OCSPLastUpdated.IsZero(), "OCSPLastUpdated should be nil") }
func TestDeactivateAccount(t *testing.T) { _ = features.Set(map[string]bool{"AllowAccountDeactivation": true}) defer features.Reset() sa, _, cleanUp := initSA(t) defer cleanUp() reg := satest.CreateWorkingRegistration(t, sa) err := sa.DeactivateRegistration(context.Background(), reg.ID) test.AssertNotError(t, err, "DeactivateRegistration failed") dbReg, err := sa.GetRegistration(context.Background(), reg.ID) test.AssertNotError(t, err, "GetRegistration failed") test.AssertEquals(t, dbReg.Status, core.StatusDeactivated) }
func TestModelToRegistrationNilContact(t *testing.T) { _ = features.Set(map[string]bool{"AllowAccountDeactivation": true}) defer features.Reset() reg, err := modelToRegistration(®Modelv2{ regModelv1: regModelv1{ Key: []byte(`{"kty":"RSA","n":"AQAB","e":"AQAB"}`), Contact: nil, }}) if err != nil { t.Errorf("Got error from modelToRegistration: %s", err) } if reg.Contact == nil { t.Errorf("Expected non-nil Contact field, got %#v", reg.Contact) } if len(*reg.Contact) != 0 { t.Errorf("Expected empty Contact field, got %#v", reg.Contact) } }
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() { 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 TestWillingToIssue(t *testing.T) { testCases := []struct { domain string err error }{ {``, errEmptyName}, // Empty name {`zomb!.com`, errInvalidDNSCharacter}, // ASCII character out of range {`[email protected]`, errInvalidDNSCharacter}, {`user:[email protected]`, errInvalidDNSCharacter}, {`zömbo.com`, errInvalidDNSCharacter}, // non-ASCII character {`127.0.0.1`, errIPAddress}, // IPv4 address {`fe80::1:1`, errInvalidDNSCharacter}, // IPv6 addresses {`[2001:db8:85a3:8d3:1319:8a2e:370:7348]`, errInvalidDNSCharacter}, // unexpected IPv6 variants {`[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443`, errInvalidDNSCharacter}, {`2001:db8::/32`, errInvalidDNSCharacter}, {`a.b.c.d.e.f.g.h.i.j.k`, errTooManyLabels}, // Too many labels (>10) {`www.0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef012345.com`, errNameTooLong}, // Too long (254 characters) {`www.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.com`, errLabelTooLong}, // Label too long (>63 characters) {`www.-ombo.com`, errInvalidDNSCharacter}, // Label starts with '-' {`www.zomb-.com`, errInvalidDNSCharacter}, // Label ends with '-' {`xn--.net`, errInvalidDNSCharacter}, // Label ends with '-' {`0`, errTooFewLabels}, {`1`, errTooFewLabels}, {`*`, errInvalidDNSCharacter}, {`**`, errInvalidDNSCharacter}, {`*.*`, errInvalidDNSCharacter}, {`zombo*com`, errInvalidDNSCharacter}, {`*.com`, errInvalidDNSCharacter}, {`*.zombo.com`, errInvalidDNSCharacter}, {`..a`, errLabelTooShort}, {`a..a`, errLabelTooShort}, {`.a..a`, errLabelTooShort}, {`..foo.com`, errLabelTooShort}, {`.`, errNameEndsInDot}, {`..`, errNameEndsInDot}, {`a..`, errNameEndsInDot}, {`.....`, errNameEndsInDot}, {`.a.`, errNameEndsInDot}, {`www.zombo.com.`, errNameEndsInDot}, {`www.zombo_com.com`, errInvalidDNSCharacter}, {`\uFEFF`, errInvalidDNSCharacter}, // Byte order mark {`\uFEFFwww.zombo.com`, errInvalidDNSCharacter}, {`www.zom\u202Ebo.com`, errInvalidDNSCharacter}, // Right-to-Left Override {`\u202Ewww.zombo.com`, errInvalidDNSCharacter}, {`www.zom\u200Fbo.com`, errInvalidDNSCharacter}, // Right-to-Left Mark {`\u200Fwww.zombo.com`, errInvalidDNSCharacter}, // Underscores are technically disallowed in DNS. Some DNS // implementations accept them but we will be conservative. {`www.zom_bo.com`, errInvalidDNSCharacter}, {`zombocom`, errTooFewLabels}, {`localhost`, errTooFewLabels}, {`mail`, errTooFewLabels}, // disallow capitalized letters for #927 {`CapitalizedLetters.com`, errInvalidDNSCharacter}, {`example.acting`, errNonPublic}, {`example.internal`, errNonPublic}, // All-numeric final label not okay. {`www.zombo.163`, errNonPublic}, } shouldBeTLDError := []string{ `co.uk`, `foo.bn`, } shouldBeBlacklisted := []string{ `highvalue.website1.org`, `website2.co.uk`, `www.website3.com`, `lots.of.labels.website4.com`, } blacklistContents := []string{ `website2.com`, `website2.org`, `website2.co.uk`, `website3.com`, `website4.com`, } exactBlacklistContents := []string{ `www.website1.org`, `highvalue.website1.org`, `dl.website1.org`, } shouldBeAccepted := []string{ `lowvalue.website1.org`, `website4.sucks`, "www.unrelated.com", "unrelated.com", "www.8675309.com", "8675309.com", "web5ite2.com", "www.web-site2.com", } pa := paImpl(t) blacklistBytes, err := json.Marshal(blacklistJSON{ Blacklist: blacklistContents, ExactBlacklist: exactBlacklistContents, }) test.AssertNotError(t, err, "Couldn't serialize blacklist") f, _ := ioutil.TempFile("", "test-blacklist.txt") defer os.Remove(f.Name()) err = ioutil.WriteFile(f.Name(), blacklistBytes, 0640) test.AssertNotError(t, err, "Couldn't write blacklist") err = pa.SetHostnamePolicyFile(f.Name()) test.AssertNotError(t, err, "Couldn't load rules") // Test for invalid identifier type identifier := core.AcmeIdentifier{Type: "ip", Value: "example.com"} err = pa.WillingToIssue(identifier) if err != errInvalidIdentifier { t.Error("Identifier was not correctly forbidden: ", identifier) } // Test syntax errors for _, tc := range testCases { identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: tc.domain} err := pa.WillingToIssue(identifier) if err != tc.err { t.Errorf("WillingToIssue(%q) = %q, expected %q", tc.domain, err, tc.err) } } // Test IDNs err = pa.WillingToIssue(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "www.xn--mnich-kva.com"}) test.AssertError(t, err, "WillingToIssue didn't fail on a IDN with features.IDNASupport disabled") _ = features.Set(map[string]bool{"IDNASupport": true}) // Invalid encoding err = pa.WillingToIssue(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "www.xn--m.com"}) test.AssertError(t, err, "WillingToIssue didn't fail on a malformed IDN") // Valid encoding err = pa.WillingToIssue(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "www.xn--mnich-kva.com"}) test.AssertNotError(t, err, "WillingToIssue failed on a properly formed IDN") // IDN TLD err = pa.WillingToIssue(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "xn--example--3bhk5a.xn--p1ai"}) test.AssertNotError(t, err, "WillingToIssue failed on a properly formed domain with IDN TLD") features.Reset() // Test domains that are equal to public suffixes for _, domain := range shouldBeTLDError { identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: domain} err := pa.WillingToIssue(identifier) if err != errICANNTLD { t.Error("Identifier was not correctly forbidden: ", identifier, err) } } // Test blacklisting for _, domain := range shouldBeBlacklisted { identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: domain} err := pa.WillingToIssue(identifier) if err != errBlacklisted { t.Error("Identifier was not correctly forbidden: ", identifier, err) } } // Test acceptance of good names for _, domain := range shouldBeAccepted { identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: domain} if err := pa.WillingToIssue(identifier); err != nil { t.Error("Identifier was incorrectly forbidden: ", identifier, err) } } }
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") 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") 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.RA.Features) cmd.FailOnError(err, "Failed to set feature flags") stats, logger := cmd.StatsAndLogging(c.Statsd, c.Syslog) scope := metrics.NewStatsdScope(stats, "RA") 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") amqpConf := c.RA.AMQP var vac core.ValidationAuthority if c.RA.VAService != nil { conn, err := bgrpc.ClientSetup(c.RA.VAService, scope) cmd.FailOnError(err, "Unable to create VA client") vac = bgrpc.NewValidationAuthorityGRPCClient(conn) } else { vac, err = rpc.NewValidationAuthorityClient(clientName, amqpConf, scope) cmd.FailOnError(err, "Unable to create VA client") } var cac core.CertificateAuthority if c.RA.CAService != nil { conn, err := bgrpc.ClientSetup(c.RA.CAService, scope) cmd.FailOnError(err, "Unable to create CA client") cac = bgrpc.NewCertificateAuthorityClient(caPB.NewCertificateAuthorityClient(conn)) } else { cac, err = rpc.NewCertificateAuthorityClient(clientName, amqpConf, scope) cmd.FailOnError(err, "Unable to create CA client") } var pubc core.Publisher if c.RA.PublisherService != nil { conn, err := bgrpc.ClientSetup(c.RA.PublisherService, scope) cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to Publisher") pubc = bgrpc.NewPublisherClientWrapper(pubPB.NewPublisherClient(conn)) } var sac core.StorageAuthority if c.RA.SAService != nil { conn, err := bgrpc.ClientSetup(c.RA.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") } // TODO(patf): remove once RA.authorizationLifetimeDays is deployed authorizationLifetime := 300 * 24 * time.Hour if c.RA.AuthorizationLifetimeDays != 0 { authorizationLifetime = time.Duration(c.RA.AuthorizationLifetimeDays) * 24 * time.Hour } // TODO(patf): remove once RA.pendingAuthorizationLifetimeDays is deployed pendingAuthorizationLifetime := 7 * 24 * time.Hour if c.RA.PendingAuthorizationLifetimeDays != 0 { pendingAuthorizationLifetime = time.Duration(c.RA.PendingAuthorizationLifetimeDays) * 24 * time.Hour } rai := ra.NewRegistrationAuthorityImpl( clock.Default(), logger, scope, c.RA.MaxContactsPerRegistration, goodkey.NewKeyPolicy(), c.RA.MaxNames, c.RA.DoNotForceCN, c.RA.ReuseValidAuthz, authorizationLifetime, pendingAuthorizationLifetime, pubc) 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") dnsTries := c.RA.DNSTries if dnsTries < 1 { dnsTries = 1 } if !c.Common.DNSAllowLoopbackAddresses { rai.DNSResolver = bdns.NewDNSResolverImpl( raDNSTimeout, []string{c.Common.DNSResolver}, nil, scope, clock.Default(), dnsTries) } else { rai.DNSResolver = bdns.NewTestDNSResolverImpl( raDNSTimeout, []string{c.Common.DNSResolver}, scope, clock.Default(), dnsTries) } rai.VA = vac rai.CA = cac rai.SA = sac err = rai.UpdateIssuedCountForever() cmd.FailOnError(err, "Updating total issuance count") var grpcSrv *grpc.Server if c.RA.GRPC != nil { var listener net.Listener grpcSrv, listener, err = bgrpc.NewServer(c.RA.GRPC, scope) cmd.FailOnError(err, "Unable to setup RA gRPC server") gw := bgrpc.NewRegistrationAuthorityServer(rai) rapb.RegisterRegistrationAuthorityServer(grpcSrv, gw) go func() { err = grpcSrv.Serve(listener) cmd.FailOnError(err, "RA gRPC service failed") }() } ras, err := rpc.NewAmqpRPCServer(amqpConf, c.RA.MaxConcurrentRPCServerRequests, scope, logger) cmd.FailOnError(err, "Unable to create RA RPC server") go cmd.CatchSignals(logger, func() { ras.Stop() if grpcSrv != nil { grpcSrv.GracefulStop() } }) err = rpc.NewRegistrationAuthorityServer(ras, rai, logger) cmd.FailOnError(err, "Unable to setup RA RPC server") go cmd.DebugServer(c.RA.DebugAddr) go cmd.ProfileCmd(scope) err = ras.Start(amqpConf) cmd.FailOnError(err, "Unable to run RA RPC server") }