diff --git a/internal/ocsp/ocsp.go b/internal/ocsp/ocsp.go new file mode 100644 index 00000000000..4fa51bd3fe0 --- /dev/null +++ b/internal/ocsp/ocsp.go @@ -0,0 +1,275 @@ +// Copyright 2019-2024 The NATS Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testhelper + +import ( + "crypto" + "crypto/tls" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "fmt" + "io" + "net/http" + "os" + "strconv" + "strings" + "sync" + "testing" + "time" + + "golang.org/x/crypto/ocsp" +) + +const ( + defaultResponseTTL = 4 * time.Second + defaultAddress = "127.0.0.1:8888" +) + +func NewOCSPResponderCustomAddress(t *testing.T, issuerCertPEM, issuerKeyPEM string, addr string) *http.Server { + t.Helper() + return NewOCSPResponderBase(t, issuerCertPEM, issuerCertPEM, issuerKeyPEM, false, addr, defaultResponseTTL, "") +} + +func NewOCSPResponder(t *testing.T, issuerCertPEM, issuerKeyPEM string) *http.Server { + t.Helper() + return NewOCSPResponderBase(t, issuerCertPEM, issuerCertPEM, issuerKeyPEM, false, defaultAddress, defaultResponseTTL, "") +} + +func NewOCSPResponderDesignatedCustomAddress(t *testing.T, issuerCertPEM, respCertPEM, respKeyPEM string, addr string) *http.Server { + t.Helper() + return NewOCSPResponderBase(t, issuerCertPEM, respCertPEM, respKeyPEM, true, addr, defaultResponseTTL, "") +} + +func NewOCSPResponderPreferringHTTPMethod(t *testing.T, issuerCertPEM, issuerKeyPEM, method string) *http.Server { + t.Helper() + return NewOCSPResponderBase(t, issuerCertPEM, issuerCertPEM, issuerKeyPEM, false, defaultAddress, defaultResponseTTL, method) +} + +func NewOCSPResponderCustomTimeout(t *testing.T, issuerCertPEM, issuerKeyPEM string, responseTTL time.Duration) *http.Server { + t.Helper() + return NewOCSPResponderBase(t, issuerCertPEM, issuerCertPEM, issuerKeyPEM, false, defaultAddress, responseTTL, "") +} + +func NewOCSPResponderBase(t *testing.T, issuerCertPEM, respCertPEM, respKeyPEM string, embed bool, addr string, responseTTL time.Duration, method string) *http.Server { + t.Helper() + var mu sync.Mutex + status := make(map[string]int) + + issuerCert := parseCertPEM(t, issuerCertPEM) + respCert := parseCertPEM(t, respCertPEM) + respKey := parseKeyPEM(t, respKeyPEM) + + mux := http.NewServeMux() + // The "/statuses/" endpoint is for directly setting a key-value pair in + // the CA's status database. + mux.HandleFunc("/statuses/", func(rw http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + + key := r.URL.Path[len("/statuses/"):] + switch r.Method { + case "GET": + mu.Lock() + n, ok := status[key] + if !ok { + n = ocsp.Unknown + } + mu.Unlock() + + fmt.Fprintf(rw, "%s %d", key, n) + case "POST": + data, err := io.ReadAll(r.Body) + if err != nil { + http.Error(rw, err.Error(), http.StatusBadRequest) + return + } + + n, err := strconv.Atoi(string(data)) + if err != nil { + http.Error(rw, err.Error(), http.StatusBadRequest) + return + } + + mu.Lock() + status[key] = n + mu.Unlock() + + fmt.Fprintf(rw, "%s %d", key, n) + default: + http.Error(rw, "Method Not Allowed", http.StatusMethodNotAllowed) + return + } + }) + // The "/" endpoint is for normal OCSP requests. This actually parses an + // OCSP status request and signs a response with a CA. Lightly based off: + // https://www.ietf.org/rfc/rfc2560.txt + mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { + var reqData []byte + var err error + + switch { + case r.Method == "GET": + if method != "" && r.Method != method { + http.Error(rw, "", http.StatusBadRequest) + return + } + reqData, err = base64.StdEncoding.DecodeString(r.URL.Path[1:]) + case r.Method == "POST": + if method != "" && r.Method != method { + http.Error(rw, "", http.StatusBadRequest) + return + } + reqData, err = io.ReadAll(r.Body) + r.Body.Close() + default: + http.Error(rw, "Method Not Allowed", http.StatusMethodNotAllowed) + return + } + if err != nil { + http.Error(rw, err.Error(), http.StatusBadRequest) + return + } + + ocspReq, err := ocsp.ParseRequest(reqData) + if err != nil { + http.Error(rw, err.Error(), http.StatusBadRequest) + return + } + + mu.Lock() + n, ok := status[ocspReq.SerialNumber.String()] + if !ok { + n = ocsp.Unknown + } + mu.Unlock() + + tmpl := ocsp.Response{ + Status: n, + SerialNumber: ocspReq.SerialNumber, + ThisUpdate: time.Now(), + } + if responseTTL != 0 { + tmpl.NextUpdate = tmpl.ThisUpdate.Add(responseTTL) + } + if embed { + tmpl.Certificate = respCert + } + respData, err := ocsp.CreateResponse(issuerCert, respCert, tmpl, respKey) + if err != nil { + http.Error(rw, err.Error(), http.StatusInternalServerError) + return + } + + rw.Header().Set("Content-Type", "application/ocsp-response") + rw.Header().Set("Content-Length", fmt.Sprint(len(respData))) + + fmt.Fprint(rw, string(respData)) + }) + + srv := &http.Server{ + Addr: addr, + Handler: mux, + } + go srv.ListenAndServe() + time.Sleep(1 * time.Second) + return srv +} + +func parseCertPEM(t *testing.T, certPEM string) *x509.Certificate { + t.Helper() + block := parsePEM(t, certPEM) + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + t.Fatalf("failed to parse cert '%s': %s", certPEM, err) + } + return cert +} + +func parseKeyPEM(t *testing.T, keyPEM string) crypto.Signer { + t.Helper() + block := parsePEM(t, keyPEM) + + key, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + key, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + t.Fatalf("failed to parse ikey %s: %s", keyPEM, err) + } + } + keyc := key.(crypto.Signer) + return keyc +} + +func parsePEM(t *testing.T, pemPath string) *pem.Block { + t.Helper() + data, err := os.ReadFile(pemPath) + if err != nil { + t.Fatal(err) + } + + block, _ := pem.Decode(data) + if block == nil { + t.Fatalf("failed to decode PEM %s", pemPath) + } + return block +} + +func GetOCSPStatus(s tls.ConnectionState) (*ocsp.Response, error) { + if len(s.VerifiedChains) == 0 { + return nil, fmt.Errorf("missing TLS verified chains") + } + chain := s.VerifiedChains[0] + + if got, want := len(chain), 2; got < want { + return nil, fmt.Errorf("incomplete cert chain, got %d, want at least %d", got, want) + } + leaf, issuer := chain[0], chain[1] + + resp, err := ocsp.ParseResponseForCert(s.OCSPResponse, leaf, issuer) + if err != nil { + return nil, fmt.Errorf("failed to parse OCSP response: %w", err) + } + if err := resp.CheckSignatureFrom(issuer); err != nil { + return resp, err + } + return resp, nil +} + +func SetOCSPStatus(t *testing.T, ocspURL, certPEM string, status int) { + t.Helper() + + cert := parseCertPEM(t, certPEM) + + hc := &http.Client{Timeout: 10 * time.Second} + resp, err := hc.Post( + fmt.Sprintf("%s/statuses/%s", ocspURL, cert.SerialNumber), + "", + strings.NewReader(fmt.Sprint(status)), + ) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + + data, err := io.ReadAll(resp.Body) + if err != nil { + t.Fatalf("failed to read OCSP HTTP response body: %s", err) + } + + if got, want := resp.Status, "200 OK"; got != want { + t.Error(strings.TrimSpace(string(data))) + t.Fatalf("unexpected OCSP HTTP set status, got %q, want %q", got, want) + } +} diff --git a/server/gateway.go b/server/gateway.go index 65769546892..79999afe649 100644 --- a/server/gateway.go +++ b/server/gateway.go @@ -432,6 +432,22 @@ func (g *srvGateway) updateRemotesTLSConfig(opts *Options) { } else if opts.Gateway.TLSConfig != nil { cfg.TLSConfig = opts.Gateway.TLSConfig.Clone() } + + // Ensure that OCSP callbacks are always setup after a reload if needed. + mustStaple := opts.OCSPConfig != nil && opts.OCSPConfig.Mode == OCSPModeAlways + if mustStaple && opts.Gateway.TLSConfig != nil { + clientCB := opts.Gateway.TLSConfig.GetClientCertificate + verifyCB := opts.Gateway.TLSConfig.VerifyConnection + if mustStaple && cfg.TLSConfig != nil { + if clientCB != nil && cfg.TLSConfig.GetClientCertificate == nil { + cfg.TLSConfig.GetClientCertificate = clientCB + } + if verifyCB != nil && cfg.TLSConfig.VerifyConnection == nil { + cfg.TLSConfig.VerifyConnection = verifyCB + } + } + } + cfg.Unlock() } } @@ -811,10 +827,35 @@ func (s *Server) createGateway(cfg *gatewayCfg, url *url.URL, conn net.Conn) { var timeout float64 if solicit { + var ( + mustStaple = opts.OCSPConfig != nil && opts.OCSPConfig.Mode == OCSPModeAlways + clientCB func(*tls.CertificateRequestInfo) (*tls.Certificate, error) + verifyCB func(tls.ConnectionState) error + ) + // Snapshot callbacks for OCSP outside an ongoing reload which might be happening. + if mustStaple { + s.reloadMu.RLock() + s.optsMu.RLock() + clientCB = s.opts.Gateway.TLSConfig.GetClientCertificate + verifyCB = s.opts.Gateway.TLSConfig.VerifyConnection + s.optsMu.RUnlock() + s.reloadMu.RUnlock() + } + cfg.RLock() tlsName = cfg.tlsName tlsConfig = cfg.TLSConfig.Clone() timeout = cfg.TLSTimeout + + // Ensure that OCSP callbacks are always setup on gateway reconnect when OCSP policy is set to always. + if mustStaple { + if clientCB != nil && tlsConfig.GetClientCertificate == nil { + tlsConfig.GetClientCertificate = clientCB + } + if verifyCB != nil && tlsConfig.VerifyConnection == nil { + tlsConfig.VerifyConnection = verifyCB + } + } cfg.RUnlock() } else { tlsConfig = opts.Gateway.TLSConfig @@ -880,6 +921,7 @@ func (s *Server) createGateway(cfg *gatewayCfg, url *url.URL, conn net.Conn) { // Builds and sends the CONNECT protocol for a gateway. // Client lock held on entry. func (c *client) sendGatewayConnect(opts *Options) { + // FIXME: This can race with updateRemotesTLSConfig tlsRequired := c.gw.cfg.TLSConfig != nil url := c.gw.connectURL c.gw.connectURL = nil diff --git a/server/gateway_test.go b/server/gateway_test.go index 21c14f4ac79..97d2f25aae2 100644 --- a/server/gateway_test.go +++ b/server/gateway_test.go @@ -22,6 +22,7 @@ import ( "fmt" "net" "net/url" + "os" "runtime" "strconv" "strings" @@ -30,8 +31,10 @@ import ( "testing" "time" + . "github.com/nats-io/nats-server/v2/internal/ocsp" "github.com/nats-io/nats-server/v2/logger" "github.com/nats-io/nats.go" + "golang.org/x/crypto/ocsp" ) func init() { @@ -6950,3 +6953,394 @@ func TestGatewayConnectEvents(t *testing.T) { checkEvents(t, "Unqueued", false) checkEvents(t, "Queued", true) } + +func disconnectInboundGateways(s *Server) { + s.gateway.RLock() + in := s.gateway.in + s.gateway.RUnlock() + + s.gateway.RLock() + for _, client := range in { + s.gateway.RUnlock() + client.closeConnection(ClientClosed) + s.gateway.RLock() + } + s.gateway.RUnlock() +} + +type testMissingOCSPStapleLogger struct { + DummyLogger + ch chan string +} + +func (l *testMissingOCSPStapleLogger) Errorf(format string, v ...interface{}) { + msg := fmt.Sprintf(format, v...) + if strings.Contains(msg, "peer missing OCSP Staple") { + select { + case l.ch <- msg: + default: + } + } +} + +func TestOCSPGatewayMissingPeerStapleIssue(t *testing.T) { + const ( + caCert = "../test/configs/certs/ocsp/ca-cert.pem" + caKey = "../test/configs/certs/ocsp/ca-key.pem" + ) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + ocspr := NewOCSPResponderCustomTimeout(t, caCert, caKey, 10*time.Minute) + defer ocspr.Shutdown(ctx) + addr := fmt.Sprintf("http://%s", ocspr.Addr) + + // Node A + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + + // Node B + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + + // Node C + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + + // Node A rotated certs + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "../test/configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + + // Store Dirs + storeDirA := t.TempDir() + storeDirB := t.TempDir() + storeDirC := t.TempDir() + + // Gateway server configuration + srvConfA := ` + host: "127.0.0.1" + port: -1 + + server_name: "AAA" + + ocsp { mode = always } + + system_account = sys + accounts { + sys { users = [{ user: sys, pass: sys }]} + guest { users = [{ user: guest, pass: guest }]} + } + no_auth_user = guest + + store_dir: '%s' + gateway { + name: A + host: "127.0.0.1" + port: -1 + advertise: "127.0.0.1" + + tls { + cert_file: "../test/configs/certs/ocsp/server-status-request-url-02-cert.pem" + key_file: "../test/configs/certs/ocsp/server-status-request-url-02-key.pem" + ca_file: "../test/configs/certs/ocsp/ca-cert.pem" + timeout: 5 + } + } + ` + srvConfA = fmt.Sprintf(srvConfA, storeDirA) + sconfA := createConfFile(t, []byte(srvConfA)) + srvA, optsA := RunServerWithConfig(sconfA) + defer srvA.Shutdown() + + // Gateway B connects to Gateway A. + srvConfB := ` + host: "127.0.0.1" + port: -1 + + server_name: "BBB" + + ocsp { mode = always } + + system_account = sys + accounts { + sys { users = [{ user: sys, pass: sys }]} + guest { users = [{ user: guest, pass: guest }]} + } + no_auth_user = guest + + store_dir: '%s' + gateway { + name: B + host: "127.0.0.1" + advertise: "127.0.0.1" + port: -1 + gateways: [{ + name: "A" + url: "nats://127.0.0.1:%d" + }] + + tls { + cert_file: "../test/configs/certs/ocsp/server-status-request-url-04-cert.pem" + key_file: "../test/configs/certs/ocsp/server-status-request-url-04-key.pem" + ca_file: "../test/configs/certs/ocsp/ca-cert.pem" + timeout: 5 + } + } + ` + srvConfB = fmt.Sprintf(srvConfB, storeDirB, optsA.Gateway.Port) + conf := createConfFile(t, []byte(srvConfB)) + srvB, optsB := RunServerWithConfig(conf) + defer srvB.Shutdown() + + // Client connects to server A. + cA, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", optsA.Port), + nats.ErrorHandler(noOpErrHandler), + ) + if err != nil { + t.Fatal(err) + } + defer cA.Close() + + // Wait for connectivity between A and B. + waitForOutboundGateways(t, srvB, 1, 5*time.Second) + + // Gateway C also connects to Gateway A. + srvConfC := ` + host: "127.0.0.1" + port: -1 + + server_name: "CCC" + + ocsp { mode = always } + + system_account = sys + accounts { + sys { users = [{ user: sys, pass: sys }]} + guest { users = [{ user: guest, pass: guest }]} + } + no_auth_user = guest + + store_dir: '%s' + gateway { + name: C + host: "127.0.0.1" + advertise: "127.0.0.1" + port: -1 + gateways: [{name: "A", url: "nats://127.0.0.1:%d" }] + + tls { + cert_file: "../test/configs/certs/ocsp/server-status-request-url-06-cert.pem" + key_file: "../test/configs/certs/ocsp/server-status-request-url-06-key.pem" + ca_file: "../test/configs/certs/ocsp/ca-cert.pem" + timeout: 5 + } + } + ` + srvConfC = fmt.Sprintf(srvConfC, storeDirC, optsA.Gateway.Port) + conf = createConfFile(t, []byte(srvConfC)) + srvC, optsC := RunServerWithConfig(conf) + defer srvC.Shutdown() + + //////////////////////////////////////////////////////////////////////////// + // // + // A and B are connected at this point and A is starting with certs that // + // will be rotated. + // // + //////////////////////////////////////////////////////////////////////////// + cB, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", optsB.Port), + nats.ErrorHandler(noOpErrHandler), + ) + require_NoError(t, err) + defer cB.Close() + + cC, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", optsC.Port), + nats.ErrorHandler(noOpErrHandler), + ) + require_NoError(t, err) + defer cC.Close() + + _, err = cA.Subscribe("foo", func(m *nats.Msg) { + m.Respond(nil) + }) + require_NoError(t, err) + + cA.Flush() + + _, err = cB.Subscribe("bar", func(m *nats.Msg) { + m.Respond(nil) + }) + require_NoError(t, err) + cB.Flush() + + waitForOutboundGateways(t, srvB, 1, 10*time.Second) + waitForOutboundGateways(t, srvC, 2, 10*time.Second) + + ///////////////////////////////////////////////////////////////////////////////// + // // + // Switch all the certs from server A, all OCSP monitors should be restarted // + // so it should have new staples. // + // // + ///////////////////////////////////////////////////////////////////////////////// + srvConfA = ` + host: "127.0.0.1" + port: -1 + + server_name: "AAA" + + ocsp { mode = always } + + system_account = sys + accounts { + sys { users = [{ user: sys, pass: sys }]} + guest { users = [{ user: guest, pass: guest }]} + } + no_auth_user = guest + + store_dir: '%s' + gateway { + name: A + host: "127.0.0.1" + port: -1 + advertise: "127.0.0.1" + + tls { + cert_file: "../test/configs/certs/ocsp/server-status-request-url-08-cert.pem" + key_file: "../test/configs/certs/ocsp/server-status-request-url-08-key.pem" + ca_file: "../test/configs/certs/ocsp/ca-cert.pem" + timeout: 5 + + } + } + ` + + srvConfA = fmt.Sprintf(srvConfA, storeDirA) + if err := os.WriteFile(sconfA, []byte(srvConfA), 0666); err != nil { + t.Fatalf("Error writing config: %v", err) + } + if err := srvA.Reload(); err != nil { + t.Fatal(err) + } + waitForOutboundGateways(t, srvA, 2, 5*time.Second) + waitForOutboundGateways(t, srvB, 2, 5*time.Second) + waitForOutboundGateways(t, srvC, 2, 5*time.Second) + + // Now clients connect to C can communicate with B and A. + _, err = cC.Request("foo", nil, 2*time.Second) + require_NoError(t, err) + + _, err = cC.Request("bar", nil, 2*time.Second) + require_NoError(t, err) + + // Reload and disconnect very fast trying to produce the race. + ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + // Swap logger from server to capture the missing peer log. + lA := &testMissingOCSPStapleLogger{ch: make(chan string, 30)} + srvA.SetLogger(lA, false, false) + + lB := &testMissingOCSPStapleLogger{ch: make(chan string, 30)} + srvB.SetLogger(lB, false, false) + + lC := &testMissingOCSPStapleLogger{ch: make(chan string, 30)} + srvC.SetLogger(lC, false, false) + + // Start with a reload from the last server that connected directly to A. + err = srvC.Reload() + require_NoError(t, err) + + // Stress reconnections and reloading servers without getting + // missing OCSP peer staple errors. + var wg sync.WaitGroup + + wg.Add(1) + go func() { + for range time.NewTicker(500 * time.Millisecond).C { + select { + case <-ctx.Done(): + wg.Done() + return + default: + } + disconnectInboundGateways(srvA) + } + }() + + wg.Add(1) + go func() { + for range time.NewTicker(500 * time.Millisecond).C { + select { + case <-ctx.Done(): + wg.Done() + return + default: + } + disconnectInboundGateways(srvB) + } + }() + + wg.Add(1) + go func() { + for range time.NewTicker(500 * time.Millisecond).C { + select { + case <-ctx.Done(): + wg.Done() + return + default: + } + disconnectInboundGateways(srvC) + } + }() + + wg.Add(1) + go func() { + for range time.NewTicker(700 * time.Millisecond).C { + select { + case <-ctx.Done(): + wg.Done() + return + default: + } + srvC.Reload() + } + }() + + wg.Add(1) + go func() { + for range time.NewTicker(800 * time.Millisecond).C { + select { + case <-ctx.Done(): + wg.Done() + return + default: + } + srvB.Reload() + } + }() + + wg.Add(1) + go func() { + for range time.NewTicker(900 * time.Millisecond).C { + select { + case <-ctx.Done(): + wg.Done() + return + default: + } + srvA.Reload() + } + }() + + select { + case <-ctx.Done(): + case msg := <-lA.ch: + t.Fatalf("Server A: Got OCSP Staple error: %v", msg) + case msg := <-lB.ch: + t.Fatalf("Server B: Got OCSP Staple error: %v", msg) + case msg := <-lC.ch: + t.Fatalf("Server C: Got OCSP Staple error: %v", msg) + } + waitForOutboundGateways(t, srvA, 2, 5*time.Second) + waitForOutboundGateways(t, srvB, 2, 5*time.Second) + waitForOutboundGateways(t, srvC, 2, 5*time.Second) + wg.Wait() +} diff --git a/server/ocsp.go b/server/ocsp.go index 7f8fb8fae02..50021cf75f6 100644 --- a/server/ocsp.go +++ b/server/ocsp.go @@ -460,18 +460,18 @@ func (srv *Server) NewOCSPMonitor(config *tlsConfigKind) (*tls.Config, *OCSPMoni // GetCertificate returns a certificate that's presented to a client. tc.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { + ccert := cert raw, _, err := mon.getStatus() if err != nil { return nil, err } - return &tls.Certificate{ OCSPStaple: raw, - Certificate: cert.Certificate, - PrivateKey: cert.PrivateKey, - SupportedSignatureAlgorithms: cert.SupportedSignatureAlgorithms, - SignedCertificateTimestamps: cert.SignedCertificateTimestamps, - Leaf: cert.Leaf, + Certificate: ccert.Certificate, + PrivateKey: ccert.PrivateKey, + SupportedSignatureAlgorithms: ccert.SupportedSignatureAlgorithms, + SignedCertificateTimestamps: ccert.SignedCertificateTimestamps, + Leaf: ccert.Leaf, }, nil } @@ -532,13 +532,20 @@ func (srv *Server) NewOCSPMonitor(config *tlsConfigKind) (*tls.Config, *OCSPMoni // When server makes a peer connection, need to also present an OCSP Staple. tc.GetClientCertificate = func(info *tls.CertificateRequestInfo) (*tls.Certificate, error) { + ccert := cert raw, _, err := mon.getStatus() if err != nil { return nil, err } - cert.OCSPStaple = raw - - return &cert, nil + // NOTE: crypto/tls.sendClientCertificate internally also calls getClientCertificate + // so if for some reason these callbacks are triggered concurrently during a reconnect + // there can be a race. To avoid that, the OCSP monitor lock is used to serialize access + // to the staple which could also change inflight during an update. + mon.mu.Lock() + ccert.OCSPStaple = raw + mon.mu.Unlock() + + return &ccert, nil } default: // GetClientCertificate returns a certificate that's presented to a server. @@ -546,7 +553,6 @@ func (srv *Server) NewOCSPMonitor(config *tlsConfigKind) (*tls.Config, *OCSPMoni return &cert, nil } } - } return tc, mon, nil } @@ -761,8 +767,8 @@ func (s *Server) reloadOCSP() error { if mon != nil { ocspm = append(ocspm, mon) - // Apply latest TLS configuration. - config.apply(tc) + // Apply latest TLS configuration after OCSP monitors have started. + defer config.apply(tc) } } @@ -774,7 +780,7 @@ func (s *Server) reloadOCSP() error { } if plugged && tc != nil { s.ocspPeerVerify = true - config.apply(tc) + defer config.apply(tc) } } } diff --git a/test/ocsp_peer_test.go b/test/ocsp_peer_test.go index ed25ef8563c..1c97100d44a 100644 --- a/test/ocsp_peer_test.go +++ b/test/ocsp_peer_test.go @@ -26,50 +26,50 @@ import ( "testing" "time" - "golang.org/x/crypto/ocsp" - + . "github.com/nats-io/nats-server/v2/internal/ocsp" "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" + "golang.org/x/crypto/ocsp" ) -func newOCSPResponderRootCA(t *testing.T) *http.Server { +func NewOCSPResponderRootCA(t *testing.T) *http.Server { t.Helper() respCertPEM := "configs/certs/ocsp_peer/mini-ca/caocsp/caocsp_cert.pem" respKeyPEM := "configs/certs/ocsp_peer/mini-ca/caocsp/private/caocsp_keypair.pem" issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem" - return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:8888") + return NewOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:8888") } -func newOCSPResponderIntermediateCA1(t *testing.T) *http.Server { +func NewOCSPResponderIntermediateCA1(t *testing.T) *http.Server { t.Helper() respCertPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/ocsp1_bundle.pem" respKeyPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/private/ocsp1_keypair.pem" issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem" - return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:18888") + return NewOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:18888") } -func newOCSPResponderIntermediateCA1Undelegated(t *testing.T) *http.Server { +func NewOCSPResponderIntermediateCA1Undelegated(t *testing.T) *http.Server { t.Helper() issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem" issuerCertKey := "configs/certs/ocsp_peer/mini-ca/intermediate1/private/intermediate1_keypair.pem" - return newOCSPResponderCustomAddress(t, issuerCertPEM, issuerCertKey, "127.0.0.1:18888") + return NewOCSPResponderCustomAddress(t, issuerCertPEM, issuerCertKey, "127.0.0.1:18888") } -func newOCSPResponderBadDelegateIntermediateCA1(t *testing.T) *http.Server { +func NewOCSPResponderBadDelegateIntermediateCA1(t *testing.T) *http.Server { t.Helper() // UserA2 is a cert issued by intermediate1, but intermediate1 did not add OCSP signing extension respCertPEM := "configs/certs/ocsp_peer/mini-ca/client1/UserA2_bundle.pem" respKeyPEM := "configs/certs/ocsp_peer/mini-ca/client1/private/UserA2_keypair.pem" issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem" - return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:18888") + return NewOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:18888") } -func newOCSPResponderIntermediateCA2(t *testing.T) *http.Server { +func NewOCSPResponderIntermediateCA2(t *testing.T) *http.Server { t.Helper() respCertPEM := "configs/certs/ocsp_peer/mini-ca/ocsp2/ocsp2_bundle.pem" respKeyPEM := "configs/certs/ocsp_peer/mini-ca/ocsp2/private/ocsp2_keypair.pem" issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem" - return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:28888") + return NewOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:28888") } // TestOCSPPeerGoodClients is test of two NATS client (AIA enabled at leaf and cert) under good path (different intermediates) @@ -78,21 +78,21 @@ func TestOCSPPeerGoodClients(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) - intermediateCA2Responder := newOCSPResponderIntermediateCA2(t) + intermediateCA2Responder := NewOCSPResponderIntermediateCA2(t) intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr) defer intermediateCA2Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -223,12 +223,12 @@ func TestOCSPPeerUnknownClient(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) defer intermediateCA1Responder.Shutdown(ctx) for _, test := range []struct { @@ -295,15 +295,15 @@ func TestOCSPPeerRevokedClient(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked) for _, test := range []struct { name string @@ -439,21 +439,21 @@ func TestOCSPPeerUnknownAndRevokedIntermediate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Revoked) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Revoked) // No test OCSP status set on intermediate2, so unknown - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) - intermediateCA2Responder := newOCSPResponderIntermediateCA2(t) + intermediateCA2Responder := NewOCSPResponderIntermediateCA2(t) intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr) defer intermediateCA2Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -544,16 +544,16 @@ func TestOCSPPeerLeafGood(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -691,16 +691,16 @@ func TestOCSPPeerLeafReject(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Revoked) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Revoked) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Revoked) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Revoked) for _, test := range []struct { name string @@ -849,21 +849,21 @@ func TestOCSPPeerGoodClientsNoneCache(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) - intermediateCA2Responder := newOCSPResponderIntermediateCA2(t) + intermediateCA2Responder := NewOCSPResponderIntermediateCA2(t) intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr) defer intermediateCA2Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) deleteLocalStore(t, "") @@ -975,21 +975,21 @@ func TestOCSPPeerGoodClientsLocalCache(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) - intermediateCA2Responder := newOCSPResponderIntermediateCA2(t) + intermediateCA2Responder := NewOCSPResponderIntermediateCA2(t) intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr) defer intermediateCA2Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -1603,10 +1603,10 @@ func TestOCSPPeerPreserveRevokedCacheItem(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -1711,9 +1711,9 @@ func TestOCSPPeerPreserveRevokedCacheItem(t *testing.T) { t.Fatal(err) } } else { - intermediateCA1Responder = newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder = NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) defer intermediateCA1Responder.Shutdown(ctx) } content := test.config @@ -1755,15 +1755,15 @@ func TestOCSPStapleFeatureInterop(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -1815,7 +1815,7 @@ func TestOCSPStapleFeatureInterop(t *testing.T) { nil, nil, func() { - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) }, }, { @@ -1860,7 +1860,7 @@ func TestOCSPStapleFeatureInterop(t *testing.T) { fmt.Errorf("remote error: tls: bad certificate"), nil, func() { - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked) }, }, } { @@ -1904,15 +1904,15 @@ func TestOCSPPeerWarnOnlyOption(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked) for _, test := range []struct { name string @@ -2007,12 +2007,12 @@ func TestOCSPPeerUnknownIsGoodOption(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) defer intermediateCA1Responder.Shutdown(ctx) for _, test := range []struct { @@ -2104,10 +2104,10 @@ func TestOCSPPeerAllowWhenCAUnreachableOption(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -2310,10 +2310,10 @@ func TestOCSPResponseCacheLocalStoreOpt(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -2446,21 +2446,21 @@ func TestOCSPPeerIncrementalSaveLocalCache(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) - intermediateCA2Responder := newOCSPResponderIntermediateCA2(t) + intermediateCA2Responder := NewOCSPResponderIntermediateCA2(t) intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr) defer intermediateCA2Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good) var fi os.FileInfo var err error @@ -2597,15 +2597,15 @@ func TestOCSPPeerUndelegatedCAResponseSigner(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1Undelegated(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1Undelegated(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -2669,15 +2669,15 @@ func TestOCSPPeerDelegatedCAResponseSigner(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -2741,15 +2741,15 @@ func TestOCSPPeerBadDelegatedCAResponseSigner(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) - intermediateCA1Responder := newOCSPResponderBadDelegateIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderBadDelegateIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) for _, test := range []struct { name string @@ -2813,18 +2813,18 @@ func TestOCSPPeerNextUpdateUnset(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - rootCAResponder := newOCSPResponderRootCA(t) + rootCAResponder := NewOCSPResponderRootCA(t) rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr) defer rootCAResponder.Shutdown(ctx) - setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) + SetOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good) respCertPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/ocsp1_bundle.pem" respKeyPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/private/ocsp1_keypair.pem" issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem" - intermediateCA1Responder := newOCSPResponderBase(t, issuerCertPEM, respCertPEM, respKeyPEM, true, "127.0.0.1:18888", 0, "") + intermediateCA1Responder := NewOCSPResponderBase(t, issuerCertPEM, respCertPEM, respKeyPEM, true, "127.0.0.1:18888", 0, "") intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good) for _, test := range []struct { name string diff --git a/test/ocsp_test.go b/test/ocsp_test.go index 56eef3fc9b2..973c512ad39 100644 --- a/test/ocsp_test.go +++ b/test/ocsp_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2023 The NATS Authors +// Copyright 2021-2024 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -16,31 +16,17 @@ package test import ( "bytes" "context" - "crypto" "crypto/tls" - "crypto/x509" - "encoding/base64" - "encoding/pem" "fmt" - "io" - "net/http" "os" "path/filepath" - "strconv" - "strings" - "sync" "testing" "time" - "golang.org/x/crypto/ocsp" - + . "github.com/nats-io/nats-server/v2/internal/ocsp" "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" -) - -const ( - defaultResponseTTL = 4 * time.Second - defaultAddress = "127.0.0.1:8888" + "golang.org/x/crypto/ocsp" ) func TestOCSPAlwaysMustStapleAndShutdown(t *testing.T) { @@ -54,10 +40,10 @@ func TestOCSPAlwaysMustStapleAndShutdown(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) opts := server.Options{} opts.Host = "127.0.0.1" @@ -92,7 +78,7 @@ func TestOCSPAlwaysMustStapleAndShutdown(t *testing.T) { nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -126,7 +112,7 @@ func TestOCSPAlwaysMustStapleAndShutdown(t *testing.T) { // and the policy is to always must-staple. The OCSP Responder // instructs the NATS Server to fetch OCSP Staples every 2 seconds. time.Sleep(2 * time.Second) - setOCSPStatus(t, addr, serverCert, ocsp.Revoked) + SetOCSPStatus(t, addr, serverCert, ocsp.Revoked) time.Sleep(2 * time.Second) // Should be connection refused since server will abort now. @@ -151,10 +137,10 @@ func TestOCSPMustStapleShutdown(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) opts := server.Options{} opts.Host = "127.0.0.1" @@ -190,7 +176,7 @@ func TestOCSPMustStapleShutdown(t *testing.T) { nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -224,7 +210,7 @@ func TestOCSPMustStapleShutdown(t *testing.T) { // and the policy is to always must-staple. The OCSP Responder // instructs the NATS Server to fetch OCSP Staples every 2 seconds. time.Sleep(2 * time.Second) - setOCSPStatus(t, addr, serverCert, ocsp.Revoked) + SetOCSPStatus(t, addr, serverCert, ocsp.Revoked) time.Sleep(2 * time.Second) // Should be connection refused since server will abort now. @@ -245,10 +231,10 @@ func TestOCSPMustStapleAutoDoesNotShutdown(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) content := ` port: -1 @@ -267,7 +253,7 @@ func TestOCSPMustStapleAutoDoesNotShutdown(t *testing.T) { nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -301,7 +287,7 @@ func TestOCSPMustStapleAutoDoesNotShutdown(t *testing.T) { // and the policy is to always must-staple. The OCSP Responder // instructs the NATS Server to fetch OCSP Staples every 2 seconds. time.Sleep(2 * time.Second) - setOCSPStatus(t, addr, serverCert, ocsp.Revoked) + SetOCSPStatus(t, addr, serverCert, ocsp.Revoked) time.Sleep(2 * time.Second) // Should not be connection refused, the client will continue running and @@ -309,7 +295,7 @@ func TestOCSPMustStapleAutoDoesNotShutdown(t *testing.T) { nc, err = nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -338,10 +324,10 @@ func TestOCSPAutoWithoutMustStapleDoesNotShutdownOnRevoke(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) opts := server.Options{} opts.Host = "127.0.0.1" @@ -406,7 +392,7 @@ func TestOCSPAutoWithoutMustStapleDoesNotShutdownOnRevoke(t *testing.T) { // Revoke the client certificate, nothing will happens since does // not have MustStaple. time.Sleep(2 * time.Second) - setOCSPStatus(t, addr, serverCert, ocsp.Revoked) + SetOCSPStatus(t, addr, serverCert, ocsp.Revoked) time.Sleep(2 * time.Second) // Should not be connection refused since server will continue running. @@ -430,7 +416,7 @@ func TestOCSPClient(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) ocspURL := fmt.Sprintf("http://%s", ocspr.Addr) defer ocspr.Shutdown(ctx) @@ -487,7 +473,7 @@ func TestOCSPClient(t *testing.T) { }, nil, nil, - func() { setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, + func() { SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, { "OCSP Stapling honored by default if server has must staple status", @@ -509,7 +495,7 @@ func TestOCSPClient(t *testing.T) { nil, nil, func() { - setOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) }, }, { @@ -534,7 +520,7 @@ func TestOCSPClient(t *testing.T) { nil, nil, func() { - setOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Revoked) + SetOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Revoked) }, }, } { @@ -583,10 +569,10 @@ func TestOCSPReloadRotateTLSCertWithNoURL(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) content := ` port: -1 @@ -605,7 +591,7 @@ func TestOCSPReloadRotateTLSCertWithNoURL(t *testing.T) { nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -685,10 +671,10 @@ func TestOCSPReloadRotateTLSCertDisableMustStaple(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) storeDir := t.TempDir() @@ -715,7 +701,7 @@ func TestOCSPReloadRotateTLSCertDisableMustStaple(t *testing.T) { nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { staple = s.OCSPResponse - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -825,7 +811,7 @@ func TestOCSPReloadRotateTLSCertDisableMustStaple(t *testing.T) { nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { newStaple = s.OCSPResponse - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -882,11 +868,11 @@ func TestOCSPReloadRotateTLSCertEnableMustStaple(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) - setOCSPStatus(t, addr, updatedServerCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, updatedServerCert, ocsp.Good) // Start without OCSP Stapling MustStaple content := ` @@ -956,7 +942,7 @@ func TestOCSPReloadRotateTLSCertEnableMustStaple(t *testing.T) { nc, err = nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -982,17 +968,17 @@ func TestOCSPCluster(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -1090,7 +1076,7 @@ func TestOCSPCluster(t *testing.T) { checkClusterFormed(t, srvA, srvB) // Revoke the seed server cluster certificate, following servers will not be able to verify connection. - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) // Original set of servers still can communicate to each other, even though the cert has been revoked. // NOTE: Should we unplug from the cluster in case our server is revoke and OCSP policy is always or must? @@ -1255,18 +1241,18 @@ func TestOCSPLeaf(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -1362,7 +1348,7 @@ func TestOCSPLeaf(t *testing.T) { checkLeafNodeConnected(t, srvA) // Revoke the seed server cluster certificate, following servers will not be able to verify connection. - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) // Original set of servers still can communicate to each other via leafnode, even though the staple // for the leaf server has been revoked. @@ -1529,18 +1515,18 @@ func TestOCSPLeafNoVerify(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -1635,7 +1621,7 @@ func TestOCSPLeafNoVerify(t *testing.T) { checkLeafNodeConnected(t, srvA) // Revoke the seed server cluster certificate, following servers will not be able to verify connection. - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) // Original set of servers still can communicate to each other, even though the cert has been revoked. checkLeafNodeConnected(t, srvA) @@ -1803,18 +1789,18 @@ func TestOCSPLeafVerifyLeafRemote(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -1913,18 +1899,18 @@ func TestOCSPLeafVerifyAndMapLeafRemote(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/client-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -2035,17 +2021,17 @@ func TestOCSPGateway(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -2147,7 +2133,7 @@ func TestOCSPGateway(t *testing.T) { waitForOutboundGateways(t, srvB, 1, 5*time.Second) // Revoke the seed server cluster certificate, following servers will not be able to verify connection. - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Revoked) // Original set of servers still can communicate to each other, even though the cert has been revoked. waitForOutboundGateways(t, srvA, 1, 5*time.Second) @@ -2308,11 +2294,11 @@ func TestOCSPGatewayIntermediate(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Good) // Gateway server configuration srvConfA := ` @@ -2404,25 +2390,25 @@ func TestOCSPGatewayReload(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) // Node A - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) // Node B - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) // Node C - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) // Node A rotated certs - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -2630,7 +2616,7 @@ func TestOCSPCustomConfig(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) ocspURL := fmt.Sprintf("http://%s", ocspr.Addr) defer ocspr.Shutdown(ctx) @@ -2678,7 +2664,7 @@ func TestOCSPCustomConfig(t *testing.T) { }, nil, nil, - func() { setOCSPStatus(t, ocspURL, serverCert, ocsp.Revoked) }, + func() { SetOCSPStatus(t, ocspURL, serverCert, ocsp.Revoked) }, }, { "OCSP Stapling must staple ignored if disabled with ocsp: false", @@ -2710,7 +2696,7 @@ func TestOCSPCustomConfig(t *testing.T) { nil, nil, func() { - setOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) }, }, { @@ -2743,7 +2729,7 @@ func TestOCSPCustomConfig(t *testing.T) { nil, nil, func() { - setOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) }, }, { @@ -2778,7 +2764,7 @@ func TestOCSPCustomConfig(t *testing.T) { }, nil, nil, - func() { setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, + func() { SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, { "OCSP Stapling in must staple mode does not fetch staple if there is no must staple flag", @@ -2812,7 +2798,7 @@ func TestOCSPCustomConfig(t *testing.T) { }, nil, nil, - func() { setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, + func() { SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, { "OCSP Stapling in must staple mode fetches staple if there is a must staple flag", @@ -2847,7 +2833,7 @@ func TestOCSPCustomConfig(t *testing.T) { nil, nil, func() { - setOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, ocspURL, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) }, }, } { @@ -2896,11 +2882,11 @@ func TestOCSPCustomConfigReloadDisable(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) - setOCSPStatus(t, addr, updatedServerCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, updatedServerCert, ocsp.Good) // Start with server without OCSP Stapling MustStaple content := ` @@ -2998,11 +2984,11 @@ func TestOCSPCustomConfigReloadEnable(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) - setOCSPStatus(t, addr, updatedServerCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, updatedServerCert, ocsp.Good) // Start with server without OCSP Stapling MustStaple content := ` @@ -3089,237 +3075,6 @@ func TestOCSPCustomConfigReloadEnable(t *testing.T) { nc.Close() } -func newOCSPResponderCustomAddress(t *testing.T, issuerCertPEM, issuerKeyPEM string, addr string) *http.Server { - t.Helper() - return newOCSPResponderBase(t, issuerCertPEM, issuerCertPEM, issuerKeyPEM, false, addr, defaultResponseTTL, "") -} - -func newOCSPResponder(t *testing.T, issuerCertPEM, issuerKeyPEM string) *http.Server { - t.Helper() - return newOCSPResponderBase(t, issuerCertPEM, issuerCertPEM, issuerKeyPEM, false, defaultAddress, defaultResponseTTL, "") -} - -func newOCSPResponderDesignatedCustomAddress(t *testing.T, issuerCertPEM, respCertPEM, respKeyPEM string, addr string) *http.Server { - t.Helper() - return newOCSPResponderBase(t, issuerCertPEM, respCertPEM, respKeyPEM, true, addr, defaultResponseTTL, "") -} - -func newOCSPResponderPreferringHTTPMethod(t *testing.T, issuerCertPEM, issuerKeyPEM, method string) *http.Server { - t.Helper() - return newOCSPResponderBase(t, issuerCertPEM, issuerCertPEM, issuerKeyPEM, false, defaultAddress, defaultResponseTTL, method) -} - -func newOCSPResponderBase(t *testing.T, issuerCertPEM, respCertPEM, respKeyPEM string, embed bool, addr string, responseTTL time.Duration, method string) *http.Server { - t.Helper() - var mu sync.Mutex - status := make(map[string]int) - - issuerCert := parseCertPEM(t, issuerCertPEM) - respCert := parseCertPEM(t, respCertPEM) - respKey := parseKeyPEM(t, respKeyPEM) - - mux := http.NewServeMux() - // The "/statuses/" endpoint is for directly setting a key-value pair in - // the CA's status database. - mux.HandleFunc("/statuses/", func(rw http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - - key := r.URL.Path[len("/statuses/"):] - switch r.Method { - case "GET": - mu.Lock() - n, ok := status[key] - if !ok { - n = ocsp.Unknown - } - mu.Unlock() - - fmt.Fprintf(rw, "%s %d", key, n) - case "POST": - data, err := io.ReadAll(r.Body) - if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) - return - } - - n, err := strconv.Atoi(string(data)) - if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) - return - } - - mu.Lock() - status[key] = n - mu.Unlock() - - fmt.Fprintf(rw, "%s %d", key, n) - default: - http.Error(rw, "Method Not Allowed", http.StatusMethodNotAllowed) - return - } - }) - // The "/" endpoint is for normal OCSP requests. This actually parses an - // OCSP status request and signs a response with a CA. Lightly based off: - // https://www.ietf.org/rfc/rfc2560.txt - mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { - var reqData []byte - var err error - - switch { - case r.Method == "GET": - if method != "" && r.Method != method { - http.Error(rw, "", http.StatusBadRequest) - return - } - reqData, err = base64.StdEncoding.DecodeString(r.URL.Path[1:]) - case r.Method == "POST": - if method != "" && r.Method != method { - http.Error(rw, "", http.StatusBadRequest) - return - } - reqData, err = io.ReadAll(r.Body) - default: - http.Error(rw, "Method Not Allowed", http.StatusMethodNotAllowed) - return - } - if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) - return - } - - ocspReq, err := ocsp.ParseRequest(reqData) - if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) - return - } - - mu.Lock() - n, ok := status[ocspReq.SerialNumber.String()] - if !ok { - n = ocsp.Unknown - } - mu.Unlock() - - tmpl := ocsp.Response{ - Status: n, - SerialNumber: ocspReq.SerialNumber, - ThisUpdate: time.Now(), - } - if responseTTL != 0 { - tmpl.NextUpdate = tmpl.ThisUpdate.Add(responseTTL) - } - if embed { - tmpl.Certificate = respCert - } - respData, err := ocsp.CreateResponse(issuerCert, respCert, tmpl, respKey) - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - - rw.Header().Set("Content-Type", "application/ocsp-response") - rw.Header().Set("Content-Length", fmt.Sprint(len(respData))) - - fmt.Fprint(rw, string(respData)) - }) - - srv := &http.Server{ - Addr: addr, - Handler: mux, - } - go srv.ListenAndServe() - time.Sleep(1 * time.Second) - return srv -} - -func setOCSPStatus(t *testing.T, ocspURL, certPEM string, status int) { - t.Helper() - - cert := parseCertPEM(t, certPEM) - - hc := &http.Client{Timeout: 10 * time.Second} - resp, err := hc.Post( - fmt.Sprintf("%s/statuses/%s", ocspURL, cert.SerialNumber), - "", - strings.NewReader(fmt.Sprint(status)), - ) - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - - data, err := io.ReadAll(resp.Body) - if err != nil { - t.Fatalf("failed to read OCSP HTTP response body: %s", err) - } - - if got, want := resp.Status, "200 OK"; got != want { - t.Error(strings.TrimSpace(string(data))) - t.Fatalf("unexpected OCSP HTTP set status, got %q, want %q", got, want) - } -} - -func parseCertPEM(t *testing.T, certPEM string) *x509.Certificate { - t.Helper() - block := parsePEM(t, certPEM) - - cert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - t.Fatalf("failed to parse cert '%s': %s", certPEM, err) - } - return cert -} - -func parseKeyPEM(t *testing.T, keyPEM string) crypto.Signer { - t.Helper() - block := parsePEM(t, keyPEM) - - key, err := x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - key, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - t.Fatalf("failed to parse ikey %s: %s", keyPEM, err) - } - } - keyc := key.(crypto.Signer) - return keyc -} - -func parsePEM(t *testing.T, pemPath string) *pem.Block { - t.Helper() - data, err := os.ReadFile(pemPath) - if err != nil { - t.Fatal(err) - } - - block, _ := pem.Decode(data) - if block == nil { - t.Fatalf("failed to decode PEM %s", pemPath) - } - return block -} - -func getOCSPStatus(s tls.ConnectionState) (*ocsp.Response, error) { - if len(s.VerifiedChains) == 0 { - return nil, fmt.Errorf("missing TLS verified chains") - } - chain := s.VerifiedChains[0] - - if got, want := len(chain), 2; got < want { - return nil, fmt.Errorf("incomplete cert chain, got %d, want at least %d", got, want) - } - leaf, issuer := chain[0], chain[1] - - resp, err := ocsp.ParseResponseForCert(s.OCSPResponse, leaf, issuer) - if err != nil { - return nil, fmt.Errorf("failed to parse OCSP response: %w", err) - } - if err := resp.CheckSignatureFrom(issuer); err != nil { - return resp, err - } - return resp, nil -} - func TestOCSPTLSConfigNoLeafSet(t *testing.T) { o := DefaultTestOptions o.HTTPHost = "127.0.0.1" @@ -3341,18 +3096,18 @@ func TestOCSPSuperCluster(t *testing.T) { ) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponder(t, caCert, caKey) + ocspr := NewOCSPResponder(t, caCert, caKey) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) - setOCSPStatus(t, addr, "configs/certs/ocsp/server-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-01-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-02-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-03-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-04-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-05-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-06-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-07-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-status-request-url-08-cert.pem", ocsp.Good) + SetOCSPStatus(t, addr, "configs/certs/ocsp/server-cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -3686,7 +3441,7 @@ func TestOCSPLocalIssuerDetermination(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) @@ -3741,7 +3496,7 @@ func TestOCSPLocalIssuerDetermination(t *testing.T) { nil, true, func() { - setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) + SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, { @@ -3777,7 +3532,7 @@ func TestOCSPLocalIssuerDetermination(t *testing.T) { nil, false, func() { - setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) + SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, { @@ -3813,7 +3568,7 @@ func TestOCSPLocalIssuerDetermination(t *testing.T) { nil, true, func() { - setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) + SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, { @@ -3849,7 +3604,7 @@ func TestOCSPLocalIssuerDetermination(t *testing.T) { nil, true, func() { - setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) + SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, { @@ -3885,7 +3640,7 @@ func TestOCSPLocalIssuerDetermination(t *testing.T) { nil, true, func() { - setOCSPStatus(t, ocspURL, serverCert, ocsp.Good) + SetOCSPStatus(t, ocspURL, serverCert, ocsp.Good) }, }, } { @@ -3945,15 +3700,15 @@ func TestMixedCAOCSPSuperCluster(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - intermediateCA1Responder := newOCSPResponderIntermediateCA1(t) + intermediateCA1Responder := NewOCSPResponderIntermediateCA1(t) intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr) defer intermediateCA1Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good) - intermediateCA2Responder := newOCSPResponderIntermediateCA2(t) + intermediateCA2Responder := NewOCSPResponderIntermediateCA2(t) intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr) defer intermediateCA2Responder.Shutdown(ctx) - setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/server2/TestServer3_cert.pem", ocsp.Good) + SetOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/server2/TestServer3_cert.pem", ocsp.Good) // Store Dirs storeDirA := t.TempDir() @@ -4240,14 +3995,14 @@ func testOCSPResponderHTTPMethods(t *testing.T, method string) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponderPreferringHTTPMethod(t, caCert, caKey, method) + ocspr := NewOCSPResponderPreferringHTTPMethod(t, caCert, caKey, method) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) // Add another responder that fails. badaddr := "http://127.0.0.1:8889" - badocsp := newOCSPResponderCustomAddress(t, caCert, caKey, badaddr) + badocsp := NewOCSPResponderCustomAddress(t, caCert, caKey, badaddr) defer badocsp.Shutdown(ctx) opts := server.Options{} @@ -4283,7 +4038,7 @@ func testOCSPResponderHTTPMethods(t *testing.T, method string) { nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), nats.Secure(&tls.Config{ VerifyConnection: func(s tls.ConnectionState) error { - resp, err := getOCSPStatus(s) + resp, err := GetOCSPStatus(s) if err != nil { return err } @@ -4324,10 +4079,10 @@ func testOCSPResponderFailing(t *testing.T, method string) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ocspr := newOCSPResponderPreferringHTTPMethod(t, caCert, caKey, method) + ocspr := NewOCSPResponderPreferringHTTPMethod(t, caCert, caKey, method) defer ocspr.Shutdown(ctx) addr := fmt.Sprintf("http://%s", ocspr.Addr) - setOCSPStatus(t, addr, serverCert, ocsp.Good) + SetOCSPStatus(t, addr, serverCert, ocsp.Good) opts := server.Options{} opts.Host = "127.0.0.1"