95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"path"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/letsencrypt/boulder/cmd"
|
|
"github.com/letsencrypt/boulder/issuance"
|
|
)
|
|
|
|
type aiaTestSrv struct {
|
|
issuersByName map[string]*issuance.Certificate
|
|
}
|
|
|
|
func (srv *aiaTestSrv) handleIssuer(w http.ResponseWriter, r *http.Request) {
|
|
issuerName, err := url.PathUnescape(r.URL.Path[1:])
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
issuerName = strings.ReplaceAll(issuerName, "-", " ")
|
|
|
|
issuer, ok := srv.issuersByName[issuerName]
|
|
if !ok {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
w.Write([]byte(fmt.Sprintf("issuer %q not found", issuerName)))
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/pkix-cert")
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(issuer.Certificate.Raw)
|
|
}
|
|
|
|
// This regex excludes the "...-cross.cert.pem" files, since we don't serve our
|
|
// cross-signed certs at AIA URLs.
|
|
var issuerCertRegex = regexp.MustCompile(`int-(rsa|ecdsa)-[a-z]\.cert\.pem$`)
|
|
|
|
func main() {
|
|
listenAddr := flag.String("addr", "", "Address to listen on")
|
|
hierarchyDir := flag.String("hierarchy", "", "Directory to load certs from")
|
|
flag.Parse()
|
|
|
|
files, err := os.ReadDir(*hierarchyDir)
|
|
cmd.FailOnError(err, "opening hierarchy directory")
|
|
|
|
byName := make(map[string]*issuance.Certificate)
|
|
for _, file := range files {
|
|
if issuerCertRegex.Match([]byte(file.Name())) {
|
|
cert, err := issuance.LoadCertificate(path.Join(*hierarchyDir, file.Name()))
|
|
cmd.FailOnError(err, "loading issuer certificate")
|
|
|
|
name := cert.Certificate.Subject.CommonName
|
|
if _, found := byName[name]; found {
|
|
cmd.FailOnError(fmt.Errorf("loaded two certs with CN %q", name), "")
|
|
}
|
|
byName[name] = cert
|
|
}
|
|
}
|
|
|
|
srv := aiaTestSrv{
|
|
issuersByName: byName,
|
|
}
|
|
|
|
http.HandleFunc("/", srv.handleIssuer)
|
|
|
|
s := http.Server{
|
|
ReadTimeout: 30 * time.Second,
|
|
Addr: *listenAddr,
|
|
}
|
|
|
|
go func() {
|
|
err := s.ListenAndServe()
|
|
if err != nil && err != http.ErrServerClosed {
|
|
cmd.FailOnError(err, "Running TLS server")
|
|
}
|
|
}()
|
|
|
|
defer func() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
defer cancel()
|
|
_ = s.Shutdown(ctx)
|
|
}()
|
|
|
|
cmd.WaitForSignal()
|
|
}
|