feat: crl support, metrics
This commit is contained in:
92
main.go
92
main.go
@@ -4,17 +4,36 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"log"
|
||||
"net/http"
|
||||
"ocspcrl/internal/metrics"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
cfocsp "github.com/cloudflare/cfssl/ocsp"
|
||||
|
||||
"ocspcrl/internal/ocsp_source"
|
||||
)
|
||||
|
||||
func loadCrlFromFile(path string) (*x509.RevocationList, error) {
|
||||
crlContent, openCrlError := os.ReadFile(path)
|
||||
if openCrlError != nil {
|
||||
return nil, openCrlError
|
||||
}
|
||||
block, rest := pem.Decode(crlContent)
|
||||
if len(rest) > 0 {
|
||||
return nil, fmt.Errorf("failed to decode crl")
|
||||
}
|
||||
crl, parseCrlError := x509.ParseRevocationList(block.Bytes)
|
||||
if parseCrlError != nil {
|
||||
return nil, parseCrlError
|
||||
}
|
||||
return crl, nil
|
||||
}
|
||||
|
||||
type responder struct {
|
||||
certificatePath string
|
||||
keyPath string
|
||||
@@ -24,24 +43,19 @@ type crlSourceFile struct {
|
||||
path string
|
||||
}
|
||||
|
||||
type addresses struct {
|
||||
ocsp string
|
||||
crl string
|
||||
}
|
||||
|
||||
type configuration struct {
|
||||
responder *responder
|
||||
caCrtPath string
|
||||
crlSourceType string
|
||||
crlSourceFile *crlSourceFile
|
||||
addresses *addresses
|
||||
responder *responder
|
||||
caCrtPath string
|
||||
crlSourceType string
|
||||
crlSourceFile *crlSourceFile
|
||||
applicationListenAddress string
|
||||
metricsListenAddress string
|
||||
}
|
||||
|
||||
func main() {
|
||||
config := &configuration{
|
||||
responder: &responder{},
|
||||
crlSourceFile: &crlSourceFile{},
|
||||
addresses: &addresses{},
|
||||
}
|
||||
app := kingpin.New("ocspcrl", "OCSP responder / CRL server")
|
||||
app.HelpFlag.Short('h')
|
||||
@@ -50,42 +64,68 @@ func main() {
|
||||
app.Flag("ca-crt-path", "Path to the CA certificate").Envar("CA_CRL_PATH").Required().ExistingFileVar(&config.caCrtPath)
|
||||
app.Flag("crl-source-type", "Type of CRL source").Envar("CRL_SOURCE").Default("file").EnumVar(&config.crlSourceType, "file")
|
||||
app.Flag("source.file.path", "Path to the CRL file").Envar("SOURCE_FILE_PATH").ExistingFileVar(&config.crlSourceFile.path)
|
||||
app.Flag("ocsp.listen-address", "Address for ocsp endpoint").Envar("OCSP_LISTEN_ADDRESS").Default(":8080").StringVar(&config.addresses.ocsp)
|
||||
app.Flag("crl.listen-address", "Address for crl endpoint").Envar("CRL_LISTEN_ADDRESS").Default(":8081").StringVar(&config.addresses.crl)
|
||||
app.Flag("web.listen-address", "Address for application endpoint").Envar("WEB_LISTEN_ADDRESS").Default(":8080").StringVar(&config.applicationListenAddress)
|
||||
app.Flag("metrics.listen-address", "Address for metrics endpoint").Envar("METRICS_LISTEN_ADDRESS").Default("[::1]:8081").StringVar(&config.metricsListenAddress)
|
||||
kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
|
||||
responderKeyPair, loadResponderKeyPairError := tls.LoadX509KeyPair(config.responder.certificatePath, config.responder.keyPath)
|
||||
if loadResponderKeyPairError != nil {
|
||||
panic(loadResponderKeyPairError)
|
||||
log.Fatalf("failed to load responder key pair: %v", loadResponderKeyPairError)
|
||||
}
|
||||
|
||||
caCrtContent, openCaCrtError := os.ReadFile(config.caCrtPath)
|
||||
if openCaCrtError != nil {
|
||||
panic(openCaCrtError)
|
||||
log.Fatalf("failed to open ca certificate: %v", openCaCrtError)
|
||||
}
|
||||
block, rest := pem.Decode(caCrtContent)
|
||||
if len(rest) > 0 {
|
||||
panic("failed to decode ca certificate")
|
||||
log.Fatalln("failed to decode ca certificate")
|
||||
}
|
||||
caCertificate, loadCaCertificateError := x509.ParseCertificate(block.Bytes)
|
||||
if loadCaCertificateError != nil {
|
||||
panic(loadCaCertificateError)
|
||||
log.Fatalf("failed to parse ca certificate: %v", loadCaCertificateError)
|
||||
}
|
||||
|
||||
source := ocsp_source.NewCrlSource(caCertificate, responderKeyPair)
|
||||
loadCrlError := source.LoadCrlFromFile(config.crlSourceFile.path)
|
||||
crl, loadCrlError := loadCrlFromFile(config.crlSourceFile.path)
|
||||
if loadCrlError != nil {
|
||||
panic(loadCrlError)
|
||||
log.Fatalf("failed to load crl: %v", loadCrlError)
|
||||
}
|
||||
source.UseCrl(crl)
|
||||
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
responder := cfocsp.NewResponder(source, nil)
|
||||
listenError := http.ListenAndServe(config.addresses.ocsp, responder)
|
||||
if listenError != nil {
|
||||
panic(listenError)
|
||||
}
|
||||
applicationRouter := http.NewServeMux()
|
||||
applicationRouter.Handle("/ocsp", cfocsp.NewResponder(source, nil))
|
||||
applicationRouter.HandleFunc("/crl", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/pkix-crl")
|
||||
w.Write(crl.Raw)
|
||||
})
|
||||
|
||||
// TODO: Implement CRL server
|
||||
applicationServer := &http.Server{Addr: config.applicationListenAddress, Handler: metrics.Middleware(applicationRouter)}
|
||||
metricsSever := &http.Server{Addr: config.metricsListenAddress, Handler: promhttp.Handler()}
|
||||
|
||||
applicationServerClosed := make(chan any)
|
||||
metricsServerClosed := make(chan any)
|
||||
go func() {
|
||||
log.Printf("starting application server on %s", config.applicationListenAddress)
|
||||
if listenError := applicationServer.ListenAndServe(); listenError != nil {
|
||||
log.Printf("application error: %v", listenError)
|
||||
}
|
||||
close(applicationServerClosed)
|
||||
}()
|
||||
go func() {
|
||||
log.Printf("starting metrics server on %s", config.metricsListenAddress)
|
||||
if listenError := metricsSever.ListenAndServe(); listenError != nil {
|
||||
log.Printf("metrics error: %v", listenError)
|
||||
}
|
||||
close(metricsServerClosed)
|
||||
}()
|
||||
|
||||
<-signalChan
|
||||
applicationServer.Shutdown(nil)
|
||||
metricsSever.Shutdown(nil)
|
||||
<-applicationServerClosed
|
||||
<-metricsServerClosed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user