github.com/letsencrypt/boulder@v0.20251208.0/test/aia-test-srv/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  	"os"
    10  	"path"
    11  	"regexp"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/letsencrypt/boulder/cmd"
    16  	"github.com/letsencrypt/boulder/issuance"
    17  )
    18  
    19  type aiaTestSrv struct {
    20  	issuersByName map[string]*issuance.Certificate
    21  }
    22  
    23  func (srv *aiaTestSrv) handleIssuer(w http.ResponseWriter, r *http.Request) {
    24  	issuerName, err := url.PathUnescape(r.URL.Path[1:])
    25  	if err != nil {
    26  		w.WriteHeader(http.StatusBadRequest)
    27  		return
    28  	}
    29  	issuerName = strings.ReplaceAll(issuerName, "-", " ")
    30  
    31  	issuer, ok := srv.issuersByName[issuerName]
    32  	if !ok {
    33  		w.WriteHeader(http.StatusNotFound)
    34  		w.Write(fmt.Appendf(nil, "issuer %q not found", issuerName))
    35  		return
    36  	}
    37  
    38  	w.Header().Set("Content-Type", "application/pkix-cert")
    39  	w.WriteHeader(http.StatusOK)
    40  	w.Write(issuer.Certificate.Raw)
    41  }
    42  
    43  // This regex excludes the "...-cross.cert.pem" files, since we don't serve our
    44  // cross-signed certs at AIA URLs.
    45  var issuerCertRegex = regexp.MustCompile(`int-(rsa|ecdsa)-[a-z]\.cert\.pem$`)
    46  
    47  func main() {
    48  	listenAddr := flag.String("addr", "", "Address to listen on")
    49  	hierarchyDir := flag.String("hierarchy", "", "Directory to load certs from")
    50  	flag.Parse()
    51  
    52  	files, err := os.ReadDir(*hierarchyDir)
    53  	cmd.FailOnError(err, "opening hierarchy directory")
    54  
    55  	byName := make(map[string]*issuance.Certificate)
    56  	for _, file := range files {
    57  		if issuerCertRegex.Match([]byte(file.Name())) {
    58  			cert, err := issuance.LoadCertificate(path.Join(*hierarchyDir, file.Name()))
    59  			cmd.FailOnError(err, "loading issuer certificate")
    60  
    61  			name := cert.Certificate.Subject.CommonName
    62  			if _, found := byName[name]; found {
    63  				cmd.FailOnError(fmt.Errorf("loaded two certs with CN %q", name), "")
    64  			}
    65  			byName[name] = cert
    66  		}
    67  	}
    68  
    69  	srv := aiaTestSrv{
    70  		issuersByName: byName,
    71  	}
    72  
    73  	http.HandleFunc("/", srv.handleIssuer)
    74  
    75  	s := http.Server{
    76  		ReadTimeout: 30 * time.Second,
    77  		Addr:        *listenAddr,
    78  	}
    79  
    80  	go func() {
    81  		err := s.ListenAndServe()
    82  		if err != nil && err != http.ErrServerClosed {
    83  			cmd.FailOnError(err, "Running TLS server")
    84  		}
    85  	}()
    86  
    87  	defer func() {
    88  		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    89  		defer cancel()
    90  		_ = s.Shutdown(ctx)
    91  	}()
    92  
    93  	cmd.WaitForSignal()
    94  }