Пример #1
0
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()
}
Пример #2
0
// ocspServerMain is the command line entry point to the OCSP responder.
// It sets up a new HTTP server that responds to OCSP requests.
func ocspServerMain(args []string, c cli.Config) error {
	// serve doesn't support arguments.
	if len(args) > 0 {
		return errors.New("argument is provided but not defined; please refer to the usage by flag -h")
	}

	if c.Responses == "" {
		return errors.New("no response file provided, please set the -responses flag")
	}

	src, err := ocsp.NewSourceFromFile(c.Responses)
	if err != nil {
		return errors.New("unable to read response file")
	}

	log.Info("Registering OCSP responder handler")
	http.Handle(c.Path, ocsp.Responder{Source: src})

	addr := fmt.Sprintf("%s:%d", c.Address, c.Port)
	log.Info("Now listening on ", addr)
	return http.ListenAndServe(addr, nil)
}
Пример #3
0
func main() {
	configFile := flag.String("config", "", "File path to the configuration file for this service")
	flag.Parse()
	if *configFile == "" {
		fmt.Fprintf(os.Stderr, `Usage of %s:
Config JSON should contain either a DBConnectFile or a Source value containing a file: URL.
If Source is a file: URL, the file should contain a list of OCSP responses in base64-encoded DER,
as generated by Boulder's single-ocsp command.
`, os.Args[0])
		flag.PrintDefaults()
		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, "OCSPResponder")
	defer logger.AuditPanic()
	logger.Info(cmd.VersionString("ocsp-responder"))

	config := c.OCSPResponder
	var source cfocsp.Source

	if strings.HasPrefix(config.Source, "file:") {
		url, err := url.Parse(config.Source)
		cmd.FailOnError(err, "Source was not a URL")
		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 {
		// For databases, DBConfig takes precedence over Source, if present.
		dbConnect, err := config.DBConfig.URL()
		cmd.FailOnError(err, "Reading DB config")
		if dbConnect == "" {
			dbConnect = config.Source
		}
		logger.Info(fmt.Sprintf("Loading OCSP Database for CA Cert: %s", c.Common.IssuerCert))
		dbMap, err := sa.NewDbMap(dbConnect, config.DBConfig.MaxDBConns)
		cmd.FailOnError(err, "Could not connect to database")
		sa.SetSQLDebug(dbMap, logger)
		go sa.ReportDbConnCount(dbMap, scope)
		source, err = makeDBSource(dbMap, c.Common.IssuerCert, logger)
		cmd.FailOnError(err, "Couldn't load OCSP DB")
	}

	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(scope, c.OCSPResponder.Path, source)
	srv := &http.Server{
		Addr:    c.OCSPResponder.ListenAddress,
		Handler: m,
	}

	go cmd.DebugServer(c.OCSPResponder.DebugAddr)
	go cmd.ProfileCmd(scope)

	hd := &httpdown.HTTP{
		StopTimeout: stopTimeout,
		KillTimeout: killTimeout,
		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
}