get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/test/ocsp_peer_test.go (about)

     1  // Copyright 2023 The NATS Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package test
    15  
    16  import (
    17  	"context"
    18  	"crypto/tls"
    19  	"encoding/json"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"net/http"
    24  	"os"
    25  	"path/filepath"
    26  	"testing"
    27  	"time"
    28  
    29  	"golang.org/x/crypto/ocsp"
    30  
    31  	"get.pme.sh/pnats/server"
    32  	"github.com/nats-io/nats.go"
    33  )
    34  
    35  func newOCSPResponderRootCA(t *testing.T) *http.Server {
    36  	t.Helper()
    37  	respCertPEM := "configs/certs/ocsp_peer/mini-ca/caocsp/caocsp_cert.pem"
    38  	respKeyPEM := "configs/certs/ocsp_peer/mini-ca/caocsp/private/caocsp_keypair.pem"
    39  	issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
    40  	return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:8888")
    41  }
    42  
    43  func newOCSPResponderIntermediateCA1(t *testing.T) *http.Server {
    44  	t.Helper()
    45  	respCertPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/ocsp1_bundle.pem"
    46  	respKeyPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/private/ocsp1_keypair.pem"
    47  	issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem"
    48  	return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:18888")
    49  }
    50  
    51  func newOCSPResponderIntermediateCA1Undelegated(t *testing.T) *http.Server {
    52  	t.Helper()
    53  	issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem"
    54  	issuerCertKey := "configs/certs/ocsp_peer/mini-ca/intermediate1/private/intermediate1_keypair.pem"
    55  	return newOCSPResponderCustomAddress(t, issuerCertPEM, issuerCertKey, "127.0.0.1:18888")
    56  }
    57  
    58  func newOCSPResponderBadDelegateIntermediateCA1(t *testing.T) *http.Server {
    59  	t.Helper()
    60  	// UserA2 is a cert issued by intermediate1, but intermediate1 did not add OCSP signing extension
    61  	respCertPEM := "configs/certs/ocsp_peer/mini-ca/client1/UserA2_bundle.pem"
    62  	respKeyPEM := "configs/certs/ocsp_peer/mini-ca/client1/private/UserA2_keypair.pem"
    63  	issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem"
    64  	return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:18888")
    65  }
    66  
    67  func newOCSPResponderIntermediateCA2(t *testing.T) *http.Server {
    68  	t.Helper()
    69  	respCertPEM := "configs/certs/ocsp_peer/mini-ca/ocsp2/ocsp2_bundle.pem"
    70  	respKeyPEM := "configs/certs/ocsp_peer/mini-ca/ocsp2/private/ocsp2_keypair.pem"
    71  	issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem"
    72  	return newOCSPResponderDesignatedCustomAddress(t, issuerCertPEM, respCertPEM, respKeyPEM, "127.0.0.1:28888")
    73  }
    74  
    75  // TestOCSPPeerGoodClients is test of two NATS client (AIA enabled at leaf and cert) under good path (different intermediates)
    76  // and default ocsp_cache implementation and oscp_cache=false configuration
    77  func TestOCSPPeerGoodClients(t *testing.T) {
    78  	ctx, cancel := context.WithCancel(context.Background())
    79  	defer cancel()
    80  
    81  	rootCAResponder := newOCSPResponderRootCA(t)
    82  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
    83  	defer rootCAResponder.Shutdown(ctx)
    84  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
    85  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good)
    86  
    87  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
    88  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
    89  	defer intermediateCA1Responder.Shutdown(ctx)
    90  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
    91  
    92  	intermediateCA2Responder := newOCSPResponderIntermediateCA2(t)
    93  	intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr)
    94  	defer intermediateCA2Responder.Shutdown(ctx)
    95  	setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good)
    96  
    97  	for _, test := range []struct {
    98  		name      string
    99  		config    string
   100  		opts      []nats.Option
   101  		err       error
   102  		rerr      error
   103  		configure func()
   104  	}{
   105  		{
   106  			"Default cache: mTLS OCSP peer check on inbound client connection, client of intermediate CA 1",
   107  			`
   108  				port: -1
   109  				# default ocsp_cache since omitted
   110  				tls: {
   111  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   112  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   113  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   114  					timeout: 5
   115  					verify: true
   116  					# Long form configuration, non-default ca_timeout
   117  					ocsp_peer: {
   118  						verify: true
   119  						ca_timeout: 5
   120  						allowed_clockskew: 30
   121  					}
   122  				}
   123  			`,
   124  			[]nats.Option{
   125  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   126  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   127  				nats.ErrorHandler(noOpErrHandler),
   128  			},
   129  			nil,
   130  			nil,
   131  			func() {},
   132  		},
   133  		{
   134  			"Default cache: mTLS OCSP peer check on inbound client connection, client of intermediate CA 2",
   135  			`
   136  				port: -1
   137  				# default ocsp_cache since omitted
   138  				tls: {
   139  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   140  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   141  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   142  					timeout: 5
   143  					verify: true
   144  					# Short form configuration
   145  					ocsp_peer: true
   146  				}
   147  			`,
   148  			[]nats.Option{
   149  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client2/UserB1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client2/private/UserB1_keypair.pem"),
   150  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   151  				nats.ErrorHandler(noOpErrHandler),
   152  			},
   153  			nil,
   154  			nil,
   155  			func() {},
   156  		},
   157  		{
   158  			"Explicit true cache: mTLS OCSP peer check on inbound client connection, client of intermediate CA 1",
   159  			`
   160  				port: -1
   161  				# Short form configuration
   162  				ocsp_cache: true
   163  				tls: {
   164  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   165  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   166  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   167  					timeout: 5
   168  					verify: true
   169  					# Long form configuration
   170  					ocsp_peer: {
   171  						verify: true
   172  						ca_timeout: 5
   173  						allowed_clockskew: 30
   174  					}
   175  				}
   176  			`,
   177  			[]nats.Option{
   178  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   179  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   180  				nats.ErrorHandler(noOpErrHandler),
   181  			},
   182  			nil,
   183  			nil,
   184  			func() {},
   185  		},
   186  	} {
   187  		t.Run(test.name, func(t *testing.T) {
   188  			deleteLocalStore(t, "")
   189  			test.configure()
   190  			content := test.config
   191  			conf := createConfFile(t, []byte(content))
   192  			s, opts := RunServerWithConfig(conf)
   193  			defer s.Shutdown()
   194  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
   195  			if test.err == nil && err != nil {
   196  				t.Errorf("Expected to connect, got %v", err)
   197  			} else if test.err != nil && err == nil {
   198  				t.Errorf("Expected error on connect")
   199  			} else if test.err != nil && err != nil {
   200  				// Error on connect was expected
   201  				if test.err.Error() != err.Error() {
   202  					t.Errorf("Expected error %s, got: %s", test.err, err)
   203  				}
   204  				return
   205  			}
   206  			defer nc.Close()
   207  			nc.Subscribe("ping", func(m *nats.Msg) {
   208  				m.Respond([]byte("pong"))
   209  			})
   210  			nc.Flush()
   211  			_, err = nc.Request("ping", []byte("ping"), 250*time.Millisecond)
   212  			if test.rerr != nil && err == nil {
   213  				t.Errorf("Expected error getting response")
   214  			} else if test.rerr == nil && err != nil {
   215  				t.Errorf("Expected response")
   216  			}
   217  		})
   218  	}
   219  }
   220  
   221  // TestOCSPPeerUnknownClient is test of NATS client that is OCSP status Unknown from its OCSP Responder
   222  func TestOCSPPeerUnknownClient(t *testing.T) {
   223  	ctx, cancel := context.WithCancel(context.Background())
   224  	defer cancel()
   225  
   226  	rootCAResponder := newOCSPResponderRootCA(t)
   227  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
   228  	defer rootCAResponder.Shutdown(ctx)
   229  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
   230  
   231  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
   232  	defer intermediateCA1Responder.Shutdown(ctx)
   233  
   234  	for _, test := range []struct {
   235  		name      string
   236  		config    string
   237  		opts      []nats.Option
   238  		err       error
   239  		rerr      error
   240  		configure func()
   241  	}{
   242  		{
   243  			"Default cache, mTLS OCSP peer check on inbound client connection, client unknown to intermediate CA 1",
   244  			`
   245  				port: -1
   246  				# Cache configuration is default
   247  				tls: {
   248  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   249  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   250  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   251  					timeout: 5
   252  					verify: true
   253  					# Short form configuration
   254  					ocsp_peer: true
   255  				}
   256  			`,
   257  			[]nats.Option{
   258  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   259  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   260  				nats.ErrorHandler(noOpErrHandler),
   261  			},
   262  			errors.New("remote error: tls: bad certificate"),
   263  			errors.New("expect error"),
   264  			func() {},
   265  		},
   266  	} {
   267  		t.Run(test.name, func(t *testing.T) {
   268  			deleteLocalStore(t, "")
   269  			test.configure()
   270  			content := test.config
   271  			conf := createConfFile(t, []byte(content))
   272  			s, opts := RunServerWithConfig(conf)
   273  			defer s.Shutdown()
   274  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
   275  			if test.err == nil && err != nil {
   276  				t.Errorf("Expected to connect, got %v", err)
   277  			} else if test.err != nil && err == nil {
   278  				t.Errorf("Expected error on connect")
   279  			} else if test.err != nil && err != nil {
   280  				// Error on connect was expected
   281  				if test.err.Error() != err.Error() {
   282  					t.Errorf("Expected error %s, got: %s", test.err, err)
   283  				}
   284  				return
   285  			}
   286  			defer nc.Close()
   287  
   288  			t.Errorf("Expected connection error, fell through")
   289  		})
   290  	}
   291  }
   292  
   293  // TestOCSPPeerRevokedClient is test of NATS client that is OCSP status Revoked from its OCSP Responder
   294  func TestOCSPPeerRevokedClient(t *testing.T) {
   295  	ctx, cancel := context.WithCancel(context.Background())
   296  	defer cancel()
   297  
   298  	rootCAResponder := newOCSPResponderRootCA(t)
   299  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
   300  	defer rootCAResponder.Shutdown(ctx)
   301  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
   302  
   303  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
   304  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
   305  	defer intermediateCA1Responder.Shutdown(ctx)
   306  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked)
   307  
   308  	for _, test := range []struct {
   309  		name      string
   310  		config    string
   311  		opts      []nats.Option
   312  		err       error
   313  		rerr      error
   314  		configure func()
   315  	}{
   316  		{
   317  			"mTLS OCSP peer check on inbound client connection, client revoked by intermediate CA 1",
   318  			`
   319  				port: -1
   320  				# Cache configuration is default
   321  				tls: {
   322  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   323  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   324  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   325  					timeout: 5
   326  					verify: true
   327  					# Turn on CA OCSP check so this revoked client should NOT be able to connect
   328  					ocsp_peer: true
   329  				}
   330  			`,
   331  			[]nats.Option{
   332  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   333  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   334  				nats.ErrorHandler(noOpErrHandler),
   335  			},
   336  			errors.New("remote error: tls: bad certificate"),
   337  			errors.New("expect error"),
   338  			func() {},
   339  		},
   340  		{
   341  			"Explicit disable, mTLS OCSP peer check on inbound client connection, client revoked by intermediate CA 1 but no OCSP check",
   342  			`
   343  				port: -1
   344  				# Cache configuration is default
   345  				tls: {
   346  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   347  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   348  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   349  					timeout: 5
   350  					verify: true
   351  					# Explicit disable of OCSP peer check
   352  					ocsp_peer: false
   353  				}
   354  			`,
   355  			[]nats.Option{
   356  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   357  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   358  				nats.ErrorHandler(noOpErrHandler),
   359  			},
   360  			nil,
   361  			nil,
   362  			func() {},
   363  		},
   364  		{
   365  			"Implicit disable, mTLS OCSP peer check on inbound client connection, client revoked by intermediate CA 1 but no OCSP check",
   366  			`
   367  				port: -1
   368  				# Cache configuration is default
   369  				tls: {
   370  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   371  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   372  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   373  					timeout: 5
   374  					verify: true
   375  					# Implicit disable of OCSP peer check (i.e. not configured)
   376  					# ocsp_peer: false
   377  				}
   378  			`,
   379  			[]nats.Option{
   380  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   381  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   382  				nats.ErrorHandler(noOpErrHandler),
   383  			},
   384  			nil,
   385  			nil,
   386  			func() {},
   387  		},
   388  		{
   389  			"Explicit disable (long form), mTLS OCSP peer check on inbound client connection, client revoked by intermediate CA 1 but no OCSP check",
   390  			`
   391  				port: -1
   392  				# Cache configuration is default
   393  				tls: {
   394  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   395  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   396  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   397  					timeout: 5
   398  					verify: true
   399  					# Explicit disable of OCSP peer check, long form
   400  					ocsp_peer: { verify: false }
   401  				}
   402  			`,
   403  			[]nats.Option{
   404  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   405  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   406  				nats.ErrorHandler(noOpErrHandler),
   407  			},
   408  			nil,
   409  			nil,
   410  			func() {},
   411  		},
   412  	} {
   413  		t.Run(test.name, func(t *testing.T) {
   414  			deleteLocalStore(t, "")
   415  			test.configure()
   416  			content := test.config
   417  			conf := createConfFile(t, []byte(content))
   418  			s, opts := RunServerWithConfig(conf)
   419  			defer s.Shutdown()
   420  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
   421  			if test.err == nil && err != nil {
   422  				t.Errorf("Expected to connect, got %v", err)
   423  			} else if test.err != nil && err == nil {
   424  				t.Errorf("Expected error on connect")
   425  			} else if test.err != nil && err != nil {
   426  				// Error on connect was expected
   427  				if test.err.Error() != err.Error() {
   428  					t.Errorf("Expected error %s, got: %s", test.err, err)
   429  				}
   430  				return
   431  			}
   432  			defer nc.Close()
   433  		})
   434  	}
   435  }
   436  
   437  // TestOCSPPeerUnknownAndRevokedIntermediate test of NATS client that is OCSP good but either its intermediate is unknown or revoked
   438  func TestOCSPPeerUnknownAndRevokedIntermediate(t *testing.T) {
   439  	ctx, cancel := context.WithCancel(context.Background())
   440  	defer cancel()
   441  
   442  	rootCAResponder := newOCSPResponderRootCA(t)
   443  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
   444  	defer rootCAResponder.Shutdown(ctx)
   445  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Revoked)
   446  	// No test OCSP status set on intermediate2, so unknown
   447  
   448  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
   449  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
   450  	defer intermediateCA1Responder.Shutdown(ctx)
   451  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
   452  
   453  	intermediateCA2Responder := newOCSPResponderIntermediateCA2(t)
   454  	intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr)
   455  	defer intermediateCA2Responder.Shutdown(ctx)
   456  	setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good)
   457  
   458  	for _, test := range []struct {
   459  		name      string
   460  		config    string
   461  		opts      []nats.Option
   462  		err       error
   463  		rerr      error
   464  		configure func()
   465  	}{
   466  		{
   467  			"mTLS OCSP peer check on inbound client connection, client's intermediate is revoked",
   468  			`
   469  				port: -1
   470  				# Cache configuration is default
   471  				tls: {
   472  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   473  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   474  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   475  					timeout: 5
   476  					verify: true
   477  					# Short form configuration
   478  					ocsp_peer: true
   479  				}
   480  			`,
   481  			[]nats.Option{
   482  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   483  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   484  				nats.ErrorHandler(noOpErrHandler),
   485  			},
   486  			errors.New("remote error: tls: bad certificate"),
   487  			errors.New("expect error"),
   488  			func() {},
   489  		},
   490  		{
   491  			"mTLS OCSP peer check on inbound client connection, client's intermediate is unknown'",
   492  			`
   493  				port: -1
   494  				# Cache configuration is default
   495  				tls: {
   496  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   497  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   498  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   499  					timeout: 5
   500  					verify: true
   501  					# Short form configuration
   502  					ocsp_peer: true
   503  				}
   504  			`,
   505  			[]nats.Option{
   506  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client2/UserB1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client2/private/UserB1_keypair.pem"),
   507  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   508  				nats.ErrorHandler(noOpErrHandler),
   509  			},
   510  			errors.New("remote error: tls: bad certificate"),
   511  			errors.New("expect error"),
   512  			func() {},
   513  		},
   514  	} {
   515  		t.Run(test.name, func(t *testing.T) {
   516  			deleteLocalStore(t, "")
   517  			test.configure()
   518  			content := test.config
   519  			conf := createConfFile(t, []byte(content))
   520  			s, opts := RunServerWithConfig(conf)
   521  			defer s.Shutdown()
   522  
   523  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
   524  			if test.err == nil && err != nil {
   525  				t.Errorf("Expected to connect, got %v", err)
   526  			} else if test.err != nil && err == nil {
   527  				t.Errorf("Expected error on connect")
   528  			} else if test.err != nil && err != nil {
   529  				// Error on connect was expected
   530  				if test.err.Error() != err.Error() {
   531  					t.Errorf("Expected error %s, got: %s", test.err, err)
   532  				}
   533  				return
   534  			}
   535  			defer nc.Close()
   536  
   537  			t.Errorf("Expected connection error, fell through")
   538  		})
   539  	}
   540  }
   541  
   542  // TestOCSPPeerLeafGood tests Leaf Spoke peer checking Leaf Hub, Leaf Hub peer checking Leaf Spoke, and both peer checking
   543  func TestOCSPPeerLeafGood(t *testing.T) {
   544  	ctx, cancel := context.WithCancel(context.Background())
   545  	defer cancel()
   546  
   547  	rootCAResponder := newOCSPResponderRootCA(t)
   548  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
   549  	defer rootCAResponder.Shutdown(ctx)
   550  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
   551  
   552  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
   553  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
   554  	defer intermediateCA1Responder.Shutdown(ctx)
   555  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good)
   556  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Good)
   557  
   558  	for _, test := range []struct {
   559  		name        string
   560  		hubconfig   string
   561  		spokeconfig string
   562  		expected    int
   563  	}{
   564  		{
   565  			"OCSP peer check on Leaf Hub by Leaf Spoke (TLS client OCSP verification of TLS server)",
   566  			`
   567  				port: -1
   568  				# Cache configuration is default
   569  				leaf: {
   570  					listen: 127.0.0.1:7444
   571  					tls: {
   572  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   573  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   574  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   575  						timeout: 5
   576  					}
   577  				}
   578  			`,
   579  			`
   580  				port: -1
   581  				leaf: {
   582  					remotes: [
   583  						{
   584  							url: "nats://127.0.0.1:7444",
   585  							tls: {
   586  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   587  								timeout: 5
   588  								# Short form configuration
   589  								ocsp_peer: true
   590  							}
   591  						}
   592  					]
   593  				}
   594  			`,
   595  			1,
   596  		},
   597  		{
   598  			"OCSP peer check on Leaf Spoke by Leaf Hub (TLS server OCSP verification of TLS client)",
   599  			`
   600  				port: -1
   601  				# Cache configuration is default
   602  				leaf: {
   603  					listen: 127.0.0.1:7444
   604  					tls: {
   605  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   606  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   607  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   608  						timeout: 5
   609  						verify: true
   610  						# Short form configuration
   611  						ocsp_peer: true
   612  					}
   613  				}
   614  			`,
   615  			`
   616  				port: -1
   617  				leaf: {
   618  					remotes: [
   619  						{
   620  							url: "nats://127.0.0.1:7444",
   621  							tls: {
   622  								cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_bundle.pem"
   623  								key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer2_keypair.pem"
   624  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   625  								timeout: 5
   626  							}
   627  						}
   628  					]
   629  				}
   630  			`,
   631  			1,
   632  		},
   633  		{
   634  			"OCSP peer check bi-directionally",
   635  			`
   636  				port: -1
   637  				# Cache configuration is default
   638  				leaf: {
   639  					listen: 127.0.0.1:7444
   640  					tls: {
   641  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   642  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   643  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   644  						timeout: 5
   645  						verify: true
   646  						# Short form configuration
   647  						ocsp_peer: true
   648  					}
   649  				}
   650  			`,
   651  			`
   652  				port: -1
   653  				leaf: {
   654  					remotes: [
   655  						{
   656  							url: "nats://127.0.0.1:7444",
   657  							tls: {
   658  								cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_bundle.pem"
   659  								key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer2_keypair.pem"
   660  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   661  								timeout: 5
   662  								# Short form configuration
   663  								ocsp_peer: true
   664  							}
   665  						}
   666  					]
   667  				}
   668  			`,
   669  			1,
   670  		},
   671  	} {
   672  		t.Run(test.name, func(t *testing.T) {
   673  			deleteLocalStore(t, "")
   674  			hubcontent := test.hubconfig
   675  			hubconf := createConfFile(t, []byte(hubcontent))
   676  			hub, _ := RunServerWithConfig(hubconf)
   677  			defer hub.Shutdown()
   678  
   679  			spokecontent := test.spokeconfig
   680  			spokeconf := createConfFile(t, []byte(spokecontent))
   681  			spoke, _ := RunServerWithConfig(spokeconf)
   682  			defer spoke.Shutdown()
   683  
   684  			checkLeafNodeConnectedCount(t, hub, test.expected)
   685  		})
   686  	}
   687  }
   688  
   689  // TestOCSPPeerLeafRejects tests rejected Leaf Hub, rejected Leaf Spoke, and both rejecting each other
   690  func TestOCSPPeerLeafReject(t *testing.T) {
   691  	ctx, cancel := context.WithCancel(context.Background())
   692  	defer cancel()
   693  
   694  	rootCAResponder := newOCSPResponderRootCA(t)
   695  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
   696  	defer rootCAResponder.Shutdown(ctx)
   697  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
   698  
   699  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
   700  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
   701  	defer intermediateCA1Responder.Shutdown(ctx)
   702  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Revoked)
   703  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_cert.pem", ocsp.Revoked)
   704  
   705  	for _, test := range []struct {
   706  		name        string
   707  		hubconfig   string
   708  		spokeconfig string
   709  		expected    int
   710  	}{
   711  		{
   712  			"OCSP peer check on Leaf Hub by Leaf Spoke (TLS client OCSP verification of TLS server)",
   713  			`
   714  				port: -1
   715  				# Cache configuration is default
   716  				leaf: {
   717  					listen: 127.0.0.1:7444
   718  					tls: {
   719  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   720  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   721  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   722  						timeout: 5
   723  					}
   724  				}
   725  			`,
   726  			`
   727  				port: -1
   728  				leaf: {
   729  					remotes: [
   730  						{
   731  							url: "nats://127.0.0.1:7444",
   732  							tls: {
   733  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   734  								timeout: 5
   735  								# Short form configuration
   736  								ocsp_peer: true
   737  							}
   738  						}
   739  					]
   740  				}
   741  			`,
   742  			0,
   743  		},
   744  		{
   745  			"OCSP peer check on Leaf Spoke by Leaf Hub (TLS server OCSP verification of TLS client)",
   746  			`
   747  				port: -1
   748  				leaf: {
   749  					listen: 127.0.0.1:7444
   750  					tls: {
   751  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   752  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   753  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   754  						timeout: 5
   755  						verify: true
   756  						# Short form configuration
   757  						ocsp_peer: true
   758  					}
   759  				}
   760  			`,
   761  			`
   762  				port: -1
   763  				leaf: {
   764  					remotes: [
   765  						{
   766  							url: "nats://127.0.0.1:7444",
   767  							tls: {
   768  								cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_bundle.pem"
   769  								key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer2_keypair.pem"
   770  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   771  								timeout: 5
   772  							}
   773  						}
   774  					]
   775  				}
   776  			`,
   777  			0,
   778  		},
   779  		{
   780  			"OCSP peer check bi-directionally",
   781  			`
   782  				port: -1
   783  				leaf: {
   784  					listen: 127.0.0.1:7444
   785  					tls: {
   786  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   787  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   788  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   789  						timeout: 5
   790  						verify: true
   791  						# Short form configuration
   792  						ocsp_peer: true
   793  					}
   794  				}
   795  			`,
   796  			`
   797  				port: -1
   798  				leaf: {
   799  					remotes: [
   800  						{
   801  							url: "nats://127.0.0.1:7444",
   802  							tls: {
   803  								cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer2_bundle.pem"
   804  								key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer2_keypair.pem"
   805  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   806  								timeout: 5
   807  								# Short form configuration
   808  								ocsp_peer: true
   809  							}
   810  						}
   811  					]
   812  				}
   813  			`,
   814  			0,
   815  		},
   816  	} {
   817  		t.Run(test.name, func(t *testing.T) {
   818  			deleteLocalStore(t, "")
   819  			hubcontent := test.hubconfig
   820  			hubconf := createConfFile(t, []byte(hubcontent))
   821  			hub, _ := RunServerWithConfig(hubconf)
   822  			defer hub.Shutdown()
   823  			spokecontent := test.spokeconfig
   824  			spokeconf := createConfFile(t, []byte(spokecontent))
   825  			spoke, _ := RunServerWithConfig(spokeconf)
   826  			defer spoke.Shutdown()
   827  			// Need to inject some time for leaf connection attempts to complete, could refine this to better
   828  			// negative test
   829  			time.Sleep(2000 * time.Millisecond)
   830  			checkLeafNodeConnectedCount(t, hub, test.expected)
   831  		})
   832  	}
   833  }
   834  
   835  func checkLeafNodeConnectedCount(t testing.TB, s *server.Server, lnCons int) {
   836  	t.Helper()
   837  	checkFor(t, 5*time.Second, 15*time.Millisecond, func() error {
   838  		if nln := s.NumLeafNodes(); nln != lnCons {
   839  			return fmt.Errorf("expected %d connected leafnode(s) for server %q, got %d",
   840  				lnCons, s.ID(), nln)
   841  		}
   842  		return nil
   843  	})
   844  }
   845  
   846  // TestOCSPPeerGoodClientsNoneCache is test of two NATS client (AIA enabled at leaf and cert) under good path (different intermediates)
   847  // and ocsp cache type of none (no-op)
   848  func TestOCSPPeerGoodClientsNoneCache(t *testing.T) {
   849  	ctx, cancel := context.WithCancel(context.Background())
   850  	defer cancel()
   851  
   852  	rootCAResponder := newOCSPResponderRootCA(t)
   853  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
   854  	defer rootCAResponder.Shutdown(ctx)
   855  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
   856  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good)
   857  
   858  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
   859  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
   860  	defer intermediateCA1Responder.Shutdown(ctx)
   861  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
   862  
   863  	intermediateCA2Responder := newOCSPResponderIntermediateCA2(t)
   864  	intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr)
   865  	defer intermediateCA2Responder.Shutdown(ctx)
   866  	setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good)
   867  
   868  	deleteLocalStore(t, "")
   869  
   870  	for _, test := range []struct {
   871  		name      string
   872  		config    string
   873  		opts      []nats.Option
   874  		err       error
   875  		rerr      error
   876  		configure func()
   877  	}{
   878  		{
   879  			"None cache explicit long form: mTLS OCSP peer check on inbound client connection, client of intermediate CA 1",
   880  			`
   881  				port: -1
   882  				tls: {
   883  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   884  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   885  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   886  					timeout: 5
   887  					verify: true
   888  					# Long form configuration
   889  					ocsp_peer: {
   890  						verify: true
   891  						ca_timeout: 5
   892  						allowed_clockskew: 30
   893  					}
   894  				}
   895  				# Long form configuration
   896  				ocsp_cache: {
   897  					type: none
   898  				}
   899  			`,
   900  			[]nats.Option{
   901  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   902  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   903  				nats.ErrorHandler(noOpErrHandler),
   904  			},
   905  			nil,
   906  			nil,
   907  			func() {},
   908  		},
   909  		{
   910  			"None cache explicit short form: mTLS OCSP peer check on inbound client connection, client of intermediate CA 1",
   911  			`
   912  				port: -1
   913  				tls: {
   914  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
   915  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
   916  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
   917  					timeout: 5
   918  					verify: true
   919  					# Long form configuration
   920  					ocsp_peer: {
   921  						verify: true
   922  						ca_timeout: 5
   923  						allowed_clockskew: 30
   924  					}
   925  				}
   926  				# Short form configuration
   927  				ocsp_cache: false
   928  			`,
   929  			[]nats.Option{
   930  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
   931  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
   932  				nats.ErrorHandler(noOpErrHandler),
   933  			},
   934  			nil,
   935  			nil,
   936  			func() {},
   937  		},
   938  	} {
   939  		t.Run(test.name, func(t *testing.T) {
   940  			test.configure()
   941  			content := test.config
   942  			conf := createConfFile(t, []byte(content))
   943  			s, opts := RunServerWithConfig(conf)
   944  			defer s.Shutdown()
   945  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
   946  			if test.err == nil && err != nil {
   947  				t.Errorf("Expected to connect, got %v", err)
   948  			} else if test.err != nil && err == nil {
   949  				t.Errorf("Expected error on connect")
   950  			} else if test.err != nil && err != nil {
   951  				// Error on connect was expected
   952  				if test.err.Error() != err.Error() {
   953  					t.Errorf("Expected error %s, got: %s", test.err, err)
   954  				}
   955  				return
   956  			}
   957  			defer nc.Close()
   958  			nc.Subscribe("ping", func(m *nats.Msg) {
   959  				m.Respond([]byte("pong"))
   960  			})
   961  			nc.Flush()
   962  			_, err = nc.Request("ping", []byte("ping"), 250*time.Millisecond)
   963  			if test.rerr != nil && err == nil {
   964  				t.Errorf("Expected error getting response")
   965  			} else if test.rerr == nil && err != nil {
   966  				t.Errorf("Expected response")
   967  			}
   968  		})
   969  	}
   970  }
   971  
   972  // TestOCSPPeerGoodClientsLocalCache is test of two NATS client (AIA enabled at leaf and cert) under good path (different intermediates)
   973  // and leveraging the local ocsp cache type
   974  func TestOCSPPeerGoodClientsLocalCache(t *testing.T) {
   975  	ctx, cancel := context.WithCancel(context.Background())
   976  	defer cancel()
   977  
   978  	rootCAResponder := newOCSPResponderRootCA(t)
   979  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
   980  	defer rootCAResponder.Shutdown(ctx)
   981  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
   982  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good)
   983  
   984  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
   985  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
   986  	defer intermediateCA1Responder.Shutdown(ctx)
   987  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
   988  
   989  	intermediateCA2Responder := newOCSPResponderIntermediateCA2(t)
   990  	intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr)
   991  	defer intermediateCA2Responder.Shutdown(ctx)
   992  	setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good)
   993  
   994  	for _, test := range []struct {
   995  		name      string
   996  		config    string
   997  		opts      []nats.Option
   998  		err       error
   999  		rerr      error
  1000  		configure func()
  1001  	}{
  1002  		{
  1003  			"Default cache, short form: mTLS OCSP peer check on inbound client connection, UserA1 client of intermediate CA 1",
  1004  			`
  1005  				port: -1
  1006  				http_port: 8222
  1007  				tls: {
  1008  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1009  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1010  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1011  					timeout: 5
  1012  					verify: true
  1013  					# Long form configuration
  1014  					ocsp_peer: {
  1015  						verify: true
  1016  						ca_timeout: 5
  1017  						allowed_clockskew: 30
  1018  					}
  1019  				}
  1020  				# Short form configuration, local as default
  1021  				ocsp_cache: true
  1022  			`,
  1023  			[]nats.Option{
  1024  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  1025  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1026  				nats.ErrorHandler(noOpErrHandler),
  1027  			},
  1028  			nil,
  1029  			nil,
  1030  			func() {},
  1031  		},
  1032  		{
  1033  			"Local cache long form: mTLS OCSP peer check on inbound client connection, UserB1 client of intermediate CA 2",
  1034  			`
  1035  				port: -1
  1036  				http_port: 8222
  1037  
  1038  				tls: {
  1039  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1040  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1041  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1042  					timeout: 5
  1043  					verify: true
  1044  					# Short form configuration
  1045  					ocsp_peer: true
  1046  				}
  1047  				# Long form configuration
  1048  				ocsp_cache: {
  1049  					type: local
  1050  				}
  1051  			`,
  1052  			[]nats.Option{
  1053  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client2/UserB1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client2/private/UserB1_keypair.pem"),
  1054  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1055  				nats.ErrorHandler(noOpErrHandler),
  1056  			},
  1057  			nil,
  1058  			nil,
  1059  			func() {},
  1060  		},
  1061  	} {
  1062  		t.Run(test.name, func(t *testing.T) {
  1063  			// Cleanup any previous test that saved a local cache
  1064  			deleteLocalStore(t, "")
  1065  			test.configure()
  1066  			content := test.config
  1067  			conf := createConfFile(t, []byte(content))
  1068  			s, opts := RunServerWithConfig(conf)
  1069  			defer s.Shutdown()
  1070  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  1071  			if test.err == nil && err != nil {
  1072  				t.Errorf("Expected to connect, got %v", err)
  1073  			} else if test.err != nil && err == nil {
  1074  				t.Errorf("Expected error on connect")
  1075  			} else if test.err != nil && err != nil {
  1076  				// Error on connect was expected
  1077  				if test.err.Error() != err.Error() {
  1078  					t.Errorf("Expected error %s, got: %s", test.err, err)
  1079  				}
  1080  				return
  1081  			}
  1082  			nc.Close()
  1083  
  1084  			v := monitorGetVarzHelper(t, 8222)
  1085  			if v.OCSPResponseCache == nil {
  1086  				t.Fatalf("Expected OCSP statistics to be in varz")
  1087  			}
  1088  			if v.OCSPResponseCache.Misses != 2 || v.OCSPResponseCache.Responses != 2 {
  1089  				t.Errorf("Expected cache misses and cache items to be 2, got %d and %d", v.OCSPResponseCache.Misses, v.OCSPResponseCache.Responses)
  1090  			}
  1091  
  1092  			// Should get a cache hit now
  1093  			nc, err = nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  1094  			if test.err == nil && err != nil {
  1095  				t.Errorf("Expected to connect, got %v", err)
  1096  			} else if test.err != nil && err == nil {
  1097  				t.Errorf("Expected error on connect")
  1098  			} else if test.err != nil && err != nil {
  1099  				// Error on connect was expected
  1100  				if test.err.Error() != err.Error() {
  1101  					t.Errorf("Expected error %s, got: %s", test.err, err)
  1102  				}
  1103  				return
  1104  			}
  1105  			defer nc.Close()
  1106  			nc.Subscribe("ping", func(m *nats.Msg) {
  1107  				m.Respond([]byte("pong"))
  1108  			})
  1109  			nc.Flush()
  1110  			_, err = nc.Request("ping", []byte("ping"), 250*time.Millisecond)
  1111  			if test.rerr != nil && err == nil {
  1112  				t.Errorf("Expected error getting response")
  1113  			} else if test.rerr == nil && err != nil {
  1114  				t.Errorf("Expected response")
  1115  			}
  1116  
  1117  			v = monitorGetVarzHelper(t, 8222)
  1118  			if v.OCSPResponseCache == nil {
  1119  				t.Fatalf("Expected OCSP statistics to be in varz")
  1120  			}
  1121  			if v.OCSPResponseCache.Misses != 2 || v.OCSPResponseCache.Hits != 2 || v.OCSPResponseCache.Responses != 2 {
  1122  				t.Errorf("Expected cache misses, hits and cache items to be 2, got %d and %d and %d", v.OCSPResponseCache.Misses, v.OCSPResponseCache.Hits, v.OCSPResponseCache.Responses)
  1123  			}
  1124  		})
  1125  	}
  1126  }
  1127  
  1128  func TestOCSPPeerMonitor(t *testing.T) {
  1129  	for _, test := range []struct {
  1130  		name               string
  1131  		config             string
  1132  		NATSClient         bool
  1133  		WSClient           bool
  1134  		MQTTClient         bool
  1135  		LeafClient         bool
  1136  		LeafRemotes        bool
  1137  		NumTrueLeafRemotes int
  1138  	}{
  1139  		{
  1140  			"Monitor peer config setting on NATS client",
  1141  			`
  1142  				port: -1
  1143  				http_port: 8222
  1144  				# Default cache configuration
  1145  				tls: {
  1146  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1147  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1148  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1149  					timeout: 5
  1150  					verify: true
  1151  					# Long form configuration
  1152  					ocsp_peer: {
  1153  						verify: true
  1154  					}
  1155  				}
  1156  			`,
  1157  			true,
  1158  			false,
  1159  			false,
  1160  			false,
  1161  			false,
  1162  			0,
  1163  		},
  1164  		{
  1165  			"Monitor peer config setting on Websockets client",
  1166  			`
  1167  				port: -1
  1168  				http_port: 8222
  1169  				# Default cache configuration
  1170  				websocket: {
  1171  					port: 8443
  1172  					tls: {
  1173  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1174  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1175  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1176  						timeout: 5
  1177  						verify: true
  1178  						# Long form configuration
  1179  						ocsp_peer: {
  1180  							verify: true
  1181  						}
  1182  					}
  1183  				}
  1184  			`,
  1185  			false,
  1186  			true,
  1187  			false,
  1188  			false,
  1189  			false,
  1190  			0,
  1191  		},
  1192  		{
  1193  			"Monitor peer config setting on MQTT client",
  1194  			`
  1195  				port: -1
  1196  				http_port: 8222
  1197  				# Default cache configuration
  1198  				# Required for MQTT
  1199  				server_name: "my_mqtt_server"
  1200  				jetstream: {
  1201  					enabled: true
  1202  				}
  1203  				mqtt: {
  1204  					port: 1883
  1205  					tls: {
  1206  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1207  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1208  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1209  						timeout: 5
  1210  						verify: true
  1211  						# Long form configuration
  1212  						ocsp_peer: {
  1213  							verify: true
  1214  						}
  1215  					}
  1216  				}
  1217  			`,
  1218  			false,
  1219  			false,
  1220  			true,
  1221  			false,
  1222  			false,
  1223  			0,
  1224  		},
  1225  		{
  1226  			"Monitor peer config setting on Leaf client",
  1227  			`
  1228  				port: -1
  1229  				http_port: 8222
  1230  				# Default cache configuration
  1231  				leaf: {
  1232  					port: 7422
  1233  					tls: {
  1234  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1235  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1236  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1237  						timeout: 5
  1238  						verify: true
  1239  						# Long form configuration
  1240  						ocsp_peer: {
  1241  							verify: true
  1242  						}
  1243  					}
  1244  				}
  1245  			`,
  1246  			false,
  1247  			false,
  1248  			false,
  1249  			true,
  1250  			false,
  1251  			0,
  1252  		},
  1253  		{
  1254  			"Monitor peer config on some Leaf Remotes as well as Leaf client",
  1255  			`
  1256  				port: -1
  1257  				http_port: 8222
  1258  				# Default cache configuration
  1259  				leaf: {
  1260  					port: 7422
  1261  					tls: {
  1262  						cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1263  						key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1264  						ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1265  						timeout: 5
  1266  						verify: true
  1267  						# Long form configuration
  1268  						ocsp_peer: {
  1269  							verify: true
  1270  						}
  1271  					}
  1272  					remotes: [
  1273  						{
  1274  							url: "nats-leaf://bogus:7422"
  1275  							tls: {
  1276  								cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1277  								key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1278  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1279  								timeout: 5
  1280  								# Long form configuration
  1281  								ocsp_peer: {
  1282  									verify: true
  1283  								}
  1284  							}
  1285  						},
  1286  						{
  1287  							url: "nats-leaf://anotherbogus:7422"
  1288  							tls: {
  1289  								cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1290  								key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1291  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1292  								timeout: 5
  1293  								# Short form configuration
  1294  								ocsp_peer: true
  1295  							}
  1296  						},
  1297  						{
  1298  							url: "nats-leaf://yetanotherbogus:7422"
  1299  							tls: {
  1300  								cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1301  								key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1302  								ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1303  								timeout: 5
  1304  								# Peer not configured (default false)
  1305  							}
  1306  						}
  1307  					]
  1308  				}
  1309  			`,
  1310  			false,
  1311  			false,
  1312  			false,
  1313  			true,
  1314  			true,
  1315  			2,
  1316  		},
  1317  	} {
  1318  		t.Run(test.name, func(t *testing.T) {
  1319  			content := test.config
  1320  			conf := createConfFile(t, []byte(content))
  1321  			s, _ := RunServerWithConfig(conf)
  1322  			defer s.Shutdown()
  1323  			v := monitorGetVarzHelper(t, 8222)
  1324  			if test.NATSClient {
  1325  				if !v.TLSOCSPPeerVerify {
  1326  					t.Fatalf("Expected NATS Client TLSOCSPPeerVerify to be true, got false")
  1327  				}
  1328  			}
  1329  			if test.WSClient {
  1330  				if !v.Websocket.TLSOCSPPeerVerify {
  1331  					t.Fatalf("Expected WS Client TLSOCSPPeerVerify to be true, got false")
  1332  				}
  1333  			}
  1334  			if test.LeafClient {
  1335  				if !v.LeafNode.TLSOCSPPeerVerify {
  1336  					t.Fatalf("Expected Leaf Client TLSOCSPPeerVerify to be true, got false")
  1337  				}
  1338  			}
  1339  			if test.LeafRemotes {
  1340  				cnt := 0
  1341  				for _, r := range v.LeafNode.Remotes {
  1342  					if r.TLSOCSPPeerVerify {
  1343  						cnt++
  1344  					}
  1345  				}
  1346  				if cnt != test.NumTrueLeafRemotes {
  1347  					t.Fatalf("Expected %d Leaf Remotes with TLSOCSPPeerVerify true, got %d", test.NumTrueLeafRemotes, cnt)
  1348  				}
  1349  			}
  1350  		})
  1351  	}
  1352  }
  1353  
  1354  func TestOCSPResponseCacheMonitor(t *testing.T) {
  1355  	for _, test := range []struct {
  1356  		name   string
  1357  		config string
  1358  		expect string
  1359  	}{
  1360  		{
  1361  			"Monitor local cache enabled, explicit cache true",
  1362  			`
  1363  				port: -1
  1364  				http_port: 8222
  1365  				tls: {
  1366  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1367  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1368  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1369  					timeout: 5
  1370  					verify: true
  1371  					# Long form configuration
  1372  					ocsp_peer: {
  1373  						verify: true
  1374  					}
  1375  				}
  1376  				# Short form configuration
  1377  				ocsp_cache: true
  1378  			`,
  1379  			"local",
  1380  		},
  1381  		{
  1382  			"Monitor local cache enabled, explicit cache type local",
  1383  			`
  1384  				port: -1
  1385  				http_port: 8222
  1386  				tls: {
  1387  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1388  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1389  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1390  					timeout: 5
  1391  					verify: true
  1392  					# Long form configuration
  1393  					ocsp_peer: {
  1394  						verify: true
  1395  					}
  1396  				}
  1397  				# Long form configuration
  1398  				ocsp_cache: {
  1399  					type: local
  1400  				}
  1401  			`,
  1402  			"local",
  1403  		},
  1404  		{
  1405  			"Monitor local cache enabled, implicit default",
  1406  			`
  1407  				port: -1
  1408  				http_port: 8222
  1409  				tls: {
  1410  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1411  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1412  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1413  					timeout: 5
  1414  					verify: true
  1415  					# Long form configuration
  1416  					ocsp_peer: {
  1417  						verify: true
  1418  					}
  1419  				}
  1420  				# Short form configuration
  1421  				# ocsp_cache: true
  1422  			`,
  1423  			"local",
  1424  		},
  1425  		{
  1426  			"Monitor none cache enabled, explicit cache false (short)",
  1427  			`
  1428  				port: -1
  1429  				http_port: 8222
  1430  				tls: {
  1431  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1432  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1433  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1434  					timeout: 5
  1435  					verify: true
  1436  					# Long form configuration
  1437  					ocsp_peer: {
  1438  						verify: true
  1439  					}
  1440  				}
  1441  				# Short form configuration
  1442  				ocsp_cache: false
  1443  			`,
  1444  			"",
  1445  		},
  1446  		{
  1447  			"Monitor none cache enabled, explicit cache false (long)",
  1448  			`
  1449  				port: -1
  1450  				http_port: 8222
  1451  				tls: {
  1452  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1453  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1454  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1455  					timeout: 5
  1456  					verify: true
  1457  					# Long form configuration
  1458  					ocsp_peer: {
  1459  						verify: true
  1460  					}
  1461  				}
  1462  				# Long form configuration
  1463  				ocsp_cache: {
  1464  					type: none
  1465  				}
  1466  			`,
  1467  			"",
  1468  		},
  1469  	} {
  1470  		t.Run(test.name, func(t *testing.T) {
  1471  			deleteLocalStore(t, "")
  1472  			content := test.config
  1473  			conf := createConfFile(t, []byte(content))
  1474  			s, _ := RunServerWithConfig(conf)
  1475  			defer s.Shutdown()
  1476  			v := monitorGetVarzHelper(t, 8222)
  1477  			fmt.Println("Expect:", test.expect)
  1478  			var ct string
  1479  			if v.OCSPResponseCache != nil {
  1480  				ct = v.OCSPResponseCache.Type
  1481  			}
  1482  			if ct != test.expect {
  1483  				t.Fatalf("Expected OCSP Response Cache to be %s, got %s", test.expect, ct)
  1484  			}
  1485  		})
  1486  	}
  1487  }
  1488  
  1489  func TestOCSPResponseCacheChangeAndReload(t *testing.T) {
  1490  	deleteLocalStore(t, "")
  1491  
  1492  	// Start with ocsp cache set to none
  1493  	content := `
  1494  		port: -1
  1495  		http_port: 8222
  1496  		tls {
  1497  			cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1498  			key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1499  			ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1500  			timeout: 5
  1501  			verify: true
  1502  			# Short form configuration
  1503  			ocsp_peer: true
  1504  		}
  1505  		# Long form configuration
  1506  		ocsp_cache: {
  1507  			type: none
  1508  		}
  1509  	`
  1510  	conf := createConfFile(t, []byte(content))
  1511  	s, _ := RunServerWithConfig(conf)
  1512  	defer s.Shutdown()
  1513  	v := monitorGetVarzHelper(t, 8222)
  1514  	var ct string
  1515  	if v.OCSPResponseCache != nil {
  1516  		ct = v.OCSPResponseCache.Type
  1517  	}
  1518  	if ct != "" {
  1519  		t.Fatalf("Expected OCSP Response Cache to have empty type in varz indicating none")
  1520  	}
  1521  
  1522  	// Change to local cache
  1523  	content = `
  1524  		port: -1
  1525  		http_port: 8222
  1526  		tls {
  1527  			cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1528  			key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1529  			ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1530  			timeout: 5
  1531  			verify: true
  1532  			# Short form configuration
  1533  			ocsp_peer: true
  1534  		}
  1535  		# Long form configuration
  1536  		ocsp_cache: {
  1537  			type: local
  1538  		}
  1539  	`
  1540  	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
  1541  		t.Fatalf("Error writing config: %v", err)
  1542  	}
  1543  	if err := s.Reload(); err != nil {
  1544  		t.Fatal(err)
  1545  	}
  1546  	time.Sleep(2 * time.Second)
  1547  	v = monitorGetVarzHelper(t, 8222)
  1548  	ct = ""
  1549  	if v.OCSPResponseCache != nil {
  1550  		ct = v.OCSPResponseCache.Type
  1551  	}
  1552  	if ct != "local" {
  1553  		t.Fatalf("Expected OCSP Response Cache type to be local, got %q", ct)
  1554  	}
  1555  }
  1556  
  1557  func deleteLocalStore(t *testing.T, dir string) {
  1558  	t.Helper()
  1559  	if dir == "" {
  1560  		// default
  1561  		dir = "_rc_"
  1562  	}
  1563  	if err := os.RemoveAll(dir); err != nil {
  1564  		t.Fatalf("Error cleaning up local store: %v", err)
  1565  	}
  1566  }
  1567  
  1568  func monitorGetVarzHelper(t *testing.T, httpPort int) *server.Varz {
  1569  	t.Helper()
  1570  	url := fmt.Sprintf("http://127.0.0.1:%d/", httpPort)
  1571  	resp, err := http.Get(url + "varz")
  1572  	if err != nil {
  1573  		t.Fatalf("Expected no error: Got %v\n", err)
  1574  	}
  1575  	if resp.StatusCode != 200 {
  1576  		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
  1577  	}
  1578  	defer resp.Body.Close()
  1579  	body, err := io.ReadAll(resp.Body)
  1580  	if err != nil {
  1581  		t.Fatalf("Got an error reading the body: %v\n", err)
  1582  	}
  1583  	v := server.Varz{}
  1584  	if err := json.Unmarshal(body, &v); err != nil {
  1585  		t.Fatalf("Got an error unmarshalling the body: %v\n", err)
  1586  	}
  1587  	return &v
  1588  }
  1589  
  1590  func writeCacheFile(dir string, content []byte) error {
  1591  	if dir == "" {
  1592  		dir = "_rc_"
  1593  	}
  1594  	err := os.MkdirAll(filepath.Join(dir), os.ModePerm)
  1595  	if err != nil {
  1596  		return err
  1597  	}
  1598  	return os.WriteFile(filepath.Join(dir, "cache.json"), content, os.ModePerm)
  1599  }
  1600  
  1601  // TestOCSPPeerPreserveRevokedCacheItem is test of the preserve_revoked cache policy
  1602  func TestOCSPPeerPreserveRevokedCacheItem(t *testing.T) {
  1603  	ctx, cancel := context.WithCancel(context.Background())
  1604  	defer cancel()
  1605  
  1606  	rootCAResponder := newOCSPResponderRootCA(t)
  1607  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  1608  	defer rootCAResponder.Shutdown(ctx)
  1609  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  1610  
  1611  	for _, test := range []struct {
  1612  		name      string
  1613  		config    string
  1614  		opts      []nats.Option
  1615  		responses int64
  1616  		revokes   int64
  1617  		goods     int64
  1618  		unknowns  int64
  1619  		err       error
  1620  		rerr      error
  1621  		clean     bool
  1622  	}{
  1623  		{
  1624  			"Test expired revoked cert not actually deleted",
  1625  			`
  1626  				port: -1
  1627  				http_port: 8222
  1628  				tls: {
  1629  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1630  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1631  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1632  					timeout: 5
  1633  					verify: true
  1634  					# Turn on CA OCSP check so this revoked client should NOT be able to connect
  1635  					ocsp_peer: {
  1636  						verify: true
  1637  						ca_timeout: 0.5
  1638  					}
  1639  				}
  1640  				# preserve revoked true
  1641  				ocsp_cache: {
  1642  					type: local
  1643  					preserve_revoked: true
  1644  				}
  1645  			`,
  1646  			[]nats.Option{
  1647  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  1648  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1649  				nats.ErrorHandler(noOpErrHandler),
  1650  			},
  1651  			1,
  1652  			1,
  1653  			0,
  1654  			0,
  1655  			errors.New("remote error: tls: bad certificate"),
  1656  			errors.New("expect error"),
  1657  			true,
  1658  		},
  1659  		{
  1660  			"Test expired revoked cert replaced by current good cert",
  1661  			`
  1662  				port: -1
  1663  				http_port: 8222
  1664  				tls: {
  1665  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1666  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1667  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1668  					timeout: 5
  1669  					verify: true
  1670  					# Turn on CA OCSP check so this revoked client should NOT be able to connect
  1671  					ocsp_peer: true
  1672  				}
  1673  				# preserve revoked true
  1674  				ocsp_cache: {
  1675  					type: local
  1676  					preserve_revoked: true
  1677  				}
  1678  			`,
  1679  			[]nats.Option{
  1680  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  1681  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1682  				nats.ErrorHandler(noOpErrHandler),
  1683  			},
  1684  			2,
  1685  			0,
  1686  			2,
  1687  			0,
  1688  			nil,
  1689  			nil,
  1690  			false,
  1691  		},
  1692  	} {
  1693  		t.Run(test.name, func(t *testing.T) {
  1694  			var intermediateCA1Responder *http.Server
  1695  			// clean slate starting the test and start the leaf CA responder for first run
  1696  			if test.clean {
  1697  				deleteLocalStore(t, "")
  1698  				// establish the revoked item (expired) in cache
  1699  				c := []byte(`
  1700  				{
  1701  				 "5xL/SuHl6JN0OmxrNMpzVMTA73JVYcRfGX8+HvJinEI=": {
  1702  				  "subject": "CN=UserA1,O=Testnats,L=Tacoma,ST=WA,C=US",
  1703  				  "cached_at": "2023-05-29T17:56:45Z",
  1704  				  "resp_status": "revoked",
  1705  				  "resp_expires": "2023-05-29T17:56:49Z",
  1706  				  "resp": "/wYAAFMyc1R3TwBSBQBao1Qr1QzUMIIGUQoBAKCCBkowggZGBgkrBgEFBQcwAQEEggY3MIIGMzCB46FZMFcxCzAJBgNVBAYTAlVTEQ0gCAwCV0ExDzANAQ0wBwwGVGFjb21hMREwDwEROAoMCFRlc3RuYXRzMRcwFQET8HQDDA5PQ1NQIFJlc3BvbmRlchgPMjAyMzA1MjkxNzU2MDBaMHUwczBNMAkGBSsOAwIaBQAEFKgwn5fplwQy+DsulBg5SRpx0iaYBBS1kW5PZLcWhHb5tL6ZzmCVmBqOnQIUXKGv1Xy7Fu/Cx+ZT/JQa7SS7tBc2ZAAQNDVaoBE2dwD0QQE0OVowDQYJKoZIhvcNAQELBQADggEBAGAax/vkv3SBFNbxp2utc/N6Rje4E0ceC972sWgqYjzYrH0oc/acg+OAXaxUjwqoQWaT+dHaI4D5qoTkMx7XlWATjI2L72IUTf6Luo92jPzyDFwb10CdeFHtRtEYD54Qbi/nD4oxQ8cSoLKC3wft2l3E/mK/1I4Mxwq15CioK4MhfzTISoeGZbjDXPKgloJOG3rn9v64vFGV6dosbLgaXEs+MPcCsPQYkwhOOyazuewRmIDOBp5QSsKPhqsT8Rs20t8LGTMkvjZniFWJs90l9QL9F1m3obq5nyuxrGt+7Rf5zoj4T+0XCOGtE+b7cRCLg43tFuTbaAQG8Z+qkPzpza+gggQ1MIIEMTCCBC0wggMVoAMCAQICFCnhUo39pSqH6x3kHUds4YpYaXOrOj8BBDBaUSLaLwIIGjAYSS+oEUludGVybWVkaWF0ZSBDQSAxMB4XDTIzMDUwMTE5MjgzOVoXDTMzMDQyOA0PUasVAEkMMIIBIi4nAgABBQD0QAEPADCCAQoCggEBAKMMyuuA66EOHnGb07P5Zc5wwiEGPDHBBn6lqErhIaN0VJ9XzlDWwyk8Q7CdPlSU7o36DXFs316eATB5bLuXXa+7WwV3cp9V5mZF9OLCz3sOWNYUanYprOMwKA3uvcqqrh8e70Dzw6sX8tfsDeH7aJoJg5kRWEKU+A3Umm+fO+hW8Km3GBqRQXxD49uxAfGtCznXZZjmFbAXqVZu+4R6wMxndfz2dYQxeMVtUY/QGdMWT4fvWzO5et3+X6hq/URUAPOkplv9O2U4T4JPucS9yZpW/FTxWC/L7vQI/bfsrSgIZpv4eJgy27FW3Q4xusbjVvUCL/t2KLvEi/Nr2qodOCECAwEAAaOB7TCB6jAdBgNVHQ4EFgQUy15QYHqrL6k7HiSrAkKN7IFgSBMwHwYDVR0jBBgwFoBSyQNQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQ4YBAMCB4AwFgEeACUBEBAMMAoGCIm0sAMJMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly8xMjcuMC4wLjE6MTg4ODgvaV1WKDFfY3JsLmRlcjAzEUscAQEEJzAlMCMRWwwwAYYXWkoALhICkTnw/0hlzm2RRjA3tvJ2wELj9e7pMg5GtdWdrLDyI/U1qBxhZoHADbyku7W+R1iL8dFfc4PSmdo+owsygZakvahXjv49xJNX7wV3YMmIHC4lfurIlY2mSnPlu2zEOwEDkI0S9WkTxXmHrkXLSciQJDkwzye6MR5fW+APk4JmKDPc46Go/K1A0EgxY/ugahMYsYtZu++W+IOYbEoYNxoCrcJCHX4c3Ep3t/Wulz4X6DWWhaDkMMUDC2JVE8E/3xUbw0X3adZe9Xf8T+goOz7wLCAigXKj1hvRUmOGISIGelv0KsfluZesG1a1TGLp+W9JX0M9nOaFOvjJTDP96aqIjs8oXGk="
  1707  				 }
  1708  				}`)
  1709  				err := writeCacheFile("", c)
  1710  				if err != nil {
  1711  					t.Fatal(err)
  1712  				}
  1713  			} else {
  1714  				intermediateCA1Responder = newOCSPResponderIntermediateCA1(t)
  1715  				intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  1716  				setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
  1717  				defer intermediateCA1Responder.Shutdown(ctx)
  1718  			}
  1719  			content := test.config
  1720  			conf := createConfFile(t, []byte(content))
  1721  			s, opts := RunServerWithConfig(conf)
  1722  			defer s.Shutdown()
  1723  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  1724  			if test.err == nil && err != nil {
  1725  				t.Errorf("Expected to connect, got %v", err)
  1726  			} else if test.err != nil && err == nil {
  1727  				t.Errorf("Expected error on connect")
  1728  			} else if test.err != nil && err != nil {
  1729  				// Error on connect was expected
  1730  				if test.err.Error() != err.Error() {
  1731  					t.Errorf("Expected error %s, got: %s", test.err, err)
  1732  				}
  1733  				return
  1734  			}
  1735  			defer nc.Close()
  1736  			v := monitorGetVarzHelper(t, 8222)
  1737  			if v.OCSPResponseCache == nil {
  1738  				t.Fatalf("Expected OCSP statistics to be in varz")
  1739  			}
  1740  			responses := v.OCSPResponseCache.Responses
  1741  			revokes := v.OCSPResponseCache.Revokes
  1742  			goods := v.OCSPResponseCache.Goods
  1743  			unknowns := v.OCSPResponseCache.Unknowns
  1744  			if !(responses == test.responses && revokes == test.revokes && goods == test.goods && unknowns == test.unknowns) {
  1745  				t.Fatalf("Expected %d response, %d revoked, %d good, %d unknown; got [%d] and [%d] and [%d] and [%d]", test.responses, test.revokes, test.goods, test.unknowns, responses, revokes, goods, unknowns)
  1746  			}
  1747  		})
  1748  	}
  1749  }
  1750  
  1751  // TestOCSPStapleFeatureInterop is a test of a NATS client (AIA enabled at leaf and cert) connecting to a NATS Server
  1752  // in which both ocsp_peer is enabled on NATS client connections (verify client) and the ocsp staple is enabled such
  1753  // that the NATS Server will staple its own OCSP response and make available to the NATS client during handshake.
  1754  func TestOCSPStapleFeatureInterop(t *testing.T) {
  1755  	ctx, cancel := context.WithCancel(context.Background())
  1756  	defer cancel()
  1757  
  1758  	rootCAResponder := newOCSPResponderRootCA(t)
  1759  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  1760  	defer rootCAResponder.Shutdown(ctx)
  1761  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  1762  
  1763  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
  1764  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  1765  	defer intermediateCA1Responder.Shutdown(ctx)
  1766  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_cert.pem", ocsp.Good)
  1767  
  1768  	for _, test := range []struct {
  1769  		name      string
  1770  		config    string
  1771  		opts      []nats.Option
  1772  		err       error
  1773  		rerr      error
  1774  		configure func()
  1775  	}{
  1776  		{
  1777  			"Interop: Both Good: mTLS OCSP peer check on inbound client connection and server's OCSP staple validated at client",
  1778  			`
  1779  				port: -1
  1780  				ocsp_cache: true
  1781  				ocsp: {
  1782  					mode: always
  1783  				}
  1784  				tls: {
  1785  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1786  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1787  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1788  					timeout: 5
  1789  					verify: true
  1790  					# Long form configuration, non-default ca_timeout
  1791  					ocsp_peer: {
  1792  						verify: true
  1793  						ca_timeout: 5
  1794  						allowed_clockskew: 30
  1795  					}
  1796  				}
  1797  			`,
  1798  			[]nats.Option{
  1799  				nats.Secure(&tls.Config{
  1800  					VerifyConnection: func(s tls.ConnectionState) error {
  1801  						if s.OCSPResponse == nil {
  1802  							return fmt.Errorf("expected OCSP staple to be present")
  1803  						}
  1804  						resp, err := ocsp.ParseResponse(s.OCSPResponse, s.VerifiedChains[0][1])
  1805  						if err != nil || resp.Status != ocsp.Good {
  1806  							return fmt.Errorf("expected a valid GOOD stapled response")
  1807  						}
  1808  						return nil
  1809  					},
  1810  				}),
  1811  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  1812  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1813  				nats.ErrorHandler(noOpErrHandler),
  1814  			},
  1815  			nil,
  1816  			nil,
  1817  			func() {
  1818  				setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
  1819  			},
  1820  		},
  1821  		{
  1822  			"Interop: Bad Client: mTLS OCSP peer check on inbound client connection and server's OCSP staple validated at client",
  1823  			`
  1824  				port: -1
  1825  				ocsp_cache: true
  1826  				ocsp: {
  1827  					mode: always
  1828  				}
  1829  				tls: {
  1830  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1831  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1832  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1833  					timeout: 5
  1834  					verify: true
  1835  					# Long form configuration, non-default ca_timeout
  1836  					ocsp_peer: {
  1837  						verify: true
  1838  						ca_timeout: 5
  1839  						allowed_clockskew: 30
  1840  					}
  1841  				}
  1842  			`,
  1843  			[]nats.Option{
  1844  				nats.Secure(&tls.Config{
  1845  					VerifyConnection: func(s tls.ConnectionState) error {
  1846  						if s.OCSPResponse == nil {
  1847  							return fmt.Errorf("expected OCSP staple to be present")
  1848  						}
  1849  						resp, err := ocsp.ParseResponse(s.OCSPResponse, s.VerifiedChains[0][1])
  1850  						if err != nil || resp.Status != ocsp.Good {
  1851  							return fmt.Errorf("expected a valid GOOD stapled response")
  1852  						}
  1853  						return nil
  1854  					},
  1855  				}),
  1856  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  1857  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1858  				nats.ErrorHandler(noOpErrHandler),
  1859  			},
  1860  			fmt.Errorf("remote error: tls: bad certificate"),
  1861  			nil,
  1862  			func() {
  1863  				setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked)
  1864  			},
  1865  		},
  1866  	} {
  1867  		t.Run(test.name, func(t *testing.T) {
  1868  			deleteLocalStore(t, "")
  1869  			test.configure()
  1870  			content := test.config
  1871  			conf := createConfFile(t, []byte(content))
  1872  
  1873  			s, opts := RunServerWithConfig(conf)
  1874  			defer s.Shutdown()
  1875  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  1876  			if test.err == nil && err != nil {
  1877  				t.Errorf("Expected to connect, got %v", err)
  1878  			} else if test.err != nil && err == nil {
  1879  				t.Errorf("Expected error on connect")
  1880  			} else if test.err != nil && err != nil {
  1881  				// Error on connect was expected
  1882  				if test.err.Error() != err.Error() {
  1883  					t.Errorf("Expected error %s, got: %s", test.err, err)
  1884  				}
  1885  				return
  1886  			}
  1887  			defer nc.Close()
  1888  			nc.Subscribe("ping", func(m *nats.Msg) {
  1889  				m.Respond([]byte("pong"))
  1890  			})
  1891  			nc.Flush()
  1892  			_, err = nc.Request("ping", []byte("ping"), 250*time.Millisecond)
  1893  			if test.rerr != nil && err == nil {
  1894  				t.Errorf("Expected error getting response")
  1895  			} else if test.rerr == nil && err != nil {
  1896  				t.Errorf("Expected response")
  1897  			}
  1898  		})
  1899  	}
  1900  }
  1901  
  1902  // TestOCSPPeerWarnOnlyOption is test of NATS client that is OCSP Revoked status but allowed to pass with warn_only option
  1903  func TestOCSPPeerWarnOnlyOption(t *testing.T) {
  1904  	ctx, cancel := context.WithCancel(context.Background())
  1905  	defer cancel()
  1906  
  1907  	rootCAResponder := newOCSPResponderRootCA(t)
  1908  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  1909  	defer rootCAResponder.Shutdown(ctx)
  1910  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  1911  
  1912  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
  1913  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  1914  	defer intermediateCA1Responder.Shutdown(ctx)
  1915  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Revoked)
  1916  
  1917  	for _, test := range []struct {
  1918  		name      string
  1919  		config    string
  1920  		opts      []nats.Option
  1921  		err       error
  1922  		rerr      error
  1923  		configure func()
  1924  	}{
  1925  		{
  1926  			"Revoked NATS client with warn_only explicitly set to false",
  1927  			`
  1928  				port: -1
  1929  				# Cache configuration is default
  1930  				tls: {
  1931  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1932  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1933  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1934  					timeout: 5
  1935  					verify: true
  1936  					# Enable OCSP peer but with warn_only option set to false
  1937  					ocsp_peer: {
  1938  						verify: true
  1939  						warn_only: false
  1940  					}
  1941  				}
  1942  			`,
  1943  			[]nats.Option{
  1944  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  1945  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1946  				nats.ErrorHandler(noOpErrHandler),
  1947  			},
  1948  			errors.New("remote error: tls: bad certificate"),
  1949  			errors.New("expect error"),
  1950  			func() {},
  1951  		},
  1952  		{
  1953  			"Revoked NATS client with warn_only explicitly set to true",
  1954  			`
  1955  				port: -1
  1956  				# Cache configuration is default
  1957  				tls: {
  1958  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  1959  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  1960  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  1961  					timeout: 5
  1962  					verify: true
  1963  					# Enable OCSP peer but with warn_only option set to true
  1964  					ocsp_peer: {
  1965  						verify: true
  1966  						warn_only: true
  1967  					}
  1968  				}
  1969  			`,
  1970  			[]nats.Option{
  1971  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  1972  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  1973  				nats.ErrorHandler(noOpErrHandler),
  1974  			},
  1975  			nil,
  1976  			nil,
  1977  			func() {},
  1978  		},
  1979  	} {
  1980  		t.Run(test.name, func(t *testing.T) {
  1981  			deleteLocalStore(t, "")
  1982  			test.configure()
  1983  			content := test.config
  1984  			conf := createConfFile(t, []byte(content))
  1985  			s, opts := RunServerWithConfig(conf)
  1986  			defer s.Shutdown()
  1987  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  1988  			if test.err == nil && err != nil {
  1989  				t.Errorf("Expected to connect, got %v", err)
  1990  			} else if test.err != nil && err == nil {
  1991  				t.Errorf("Expected error on connect")
  1992  			} else if test.err != nil && err != nil {
  1993  				// Error on connect was expected
  1994  				if test.err.Error() != err.Error() {
  1995  					t.Errorf("Expected error %s, got: %s", test.err, err)
  1996  				}
  1997  				return
  1998  			}
  1999  			defer nc.Close()
  2000  		})
  2001  	}
  2002  }
  2003  
  2004  // TestOCSPPeerUnknownIsGoodOption is test of NATS client that is OCSP status Unknown from its OCSP Responder but we treat
  2005  // status Unknown as "Good"
  2006  func TestOCSPPeerUnknownIsGoodOption(t *testing.T) {
  2007  	ctx, cancel := context.WithCancel(context.Background())
  2008  	defer cancel()
  2009  
  2010  	rootCAResponder := newOCSPResponderRootCA(t)
  2011  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2012  	defer rootCAResponder.Shutdown(ctx)
  2013  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2014  
  2015  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
  2016  	defer intermediateCA1Responder.Shutdown(ctx)
  2017  
  2018  	for _, test := range []struct {
  2019  		name      string
  2020  		config    string
  2021  		opts      []nats.Option
  2022  		err       error
  2023  		rerr      error
  2024  		configure func()
  2025  	}{
  2026  		{
  2027  			"Unknown NATS client with no unknown_is_good option set (default false)",
  2028  			`
  2029  				port: -1
  2030  				# Cache configuration is default
  2031  				tls: {
  2032  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2033  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2034  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2035  					timeout: 5
  2036  					verify: true
  2037  					# Short form configuration
  2038  					ocsp_peer: true
  2039  				}
  2040  			`,
  2041  			[]nats.Option{
  2042  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2043  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2044  				nats.ErrorHandler(noOpErrHandler),
  2045  			},
  2046  			errors.New("remote error: tls: bad certificate"),
  2047  			errors.New("expect error"),
  2048  			func() {},
  2049  		},
  2050  		{
  2051  			"Unknown NATS client with unknown_is_good set to true",
  2052  			`
  2053  				port: -1
  2054  				# Cache configuration is default
  2055  				tls: {
  2056  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2057  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2058  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2059  					timeout: 5
  2060  					verify: true
  2061  					# Long form configuration
  2062  					ocsp_peer: {
  2063  						verify: true
  2064  						unknown_is_good: true
  2065  					}
  2066  				}
  2067  			`,
  2068  			[]nats.Option{
  2069  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2070  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2071  				nats.ErrorHandler(noOpErrHandler),
  2072  			},
  2073  			nil,
  2074  			nil,
  2075  			func() {},
  2076  		},
  2077  	} {
  2078  		t.Run(test.name, func(t *testing.T) {
  2079  			deleteLocalStore(t, "")
  2080  			test.configure()
  2081  			content := test.config
  2082  			conf := createConfFile(t, []byte(content))
  2083  			s, opts := RunServerWithConfig(conf)
  2084  			defer s.Shutdown()
  2085  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2086  			if test.err == nil && err != nil {
  2087  				t.Errorf("Expected to connect, got %v", err)
  2088  			} else if test.err != nil && err == nil {
  2089  				t.Errorf("Expected error on connect")
  2090  			} else if test.err != nil && err != nil {
  2091  				// Error on connect was expected
  2092  				if test.err.Error() != err.Error() {
  2093  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2094  				}
  2095  				return
  2096  			}
  2097  			defer nc.Close()
  2098  		})
  2099  	}
  2100  }
  2101  
  2102  // TestOCSPPeerAllowWhenCAUnreachableOption is test of the allow_when_ca_unreachable peer option
  2103  func TestOCSPPeerAllowWhenCAUnreachableOption(t *testing.T) {
  2104  	ctx, cancel := context.WithCancel(context.Background())
  2105  	defer cancel()
  2106  
  2107  	rootCAResponder := newOCSPResponderRootCA(t)
  2108  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2109  	defer rootCAResponder.Shutdown(ctx)
  2110  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2111  
  2112  	for _, test := range []struct {
  2113  		name           string
  2114  		config         string
  2115  		opts           []nats.Option
  2116  		cachedResponse string
  2117  		err            error
  2118  		rerr           error
  2119  	}{
  2120  		{
  2121  			"Expired Revoked response in cache for UserA1 -- should be rejected connection (expired revoke honored)",
  2122  			`
  2123  				port: -1
  2124  				http_port: 8222
  2125  				tls: {
  2126  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2127  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2128  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2129  					timeout: 5
  2130  					verify: true
  2131  					# Turn on CA OCSP check but allow when CA is unreachable
  2132  					ocsp_peer: {
  2133  						verify: true
  2134  						ca_timeout: 0.5
  2135  						allow_when_ca_unreachable: true
  2136  					}
  2137  				}
  2138  				# preserve revoked true
  2139  				ocsp_cache: {
  2140  					type: local
  2141  					preserve_revoked: true
  2142  				}
  2143  			`,
  2144  			[]nats.Option{
  2145  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2146  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2147  				nats.ErrorHandler(noOpErrHandler),
  2148  			},
  2149  			`
  2150  				{
  2151  					"5xL/SuHl6JN0OmxrNMpzVMTA73JVYcRfGX8+HvJinEI=": {
  2152  						"subject": "CN=UserA1,O=Testnats,L=Tacoma,ST=WA,C=US",
  2153  						"cached_at": "2023-05-29T17:56:45Z",
  2154  						"resp_status": "revoked",
  2155  						"resp_expires": "2023-05-29T17:56:49Z",
  2156  						"resp": "/wYAAFMyc1R3TwBSBQBao1Qr1QzUMIIGUQoBAKCCBkowggZGBgkrBgEFBQcwAQEEggY3MIIGMzCB46FZMFcxCzAJBgNVBAYTAlVTEQ0gCAwCV0ExDzANAQ0wBwwGVGFjb21hMREwDwEROAoMCFRlc3RuYXRzMRcwFQET8HQDDA5PQ1NQIFJlc3BvbmRlchgPMjAyMzA1MjkxNzU2MDBaMHUwczBNMAkGBSsOAwIaBQAEFKgwn5fplwQy+DsulBg5SRpx0iaYBBS1kW5PZLcWhHb5tL6ZzmCVmBqOnQIUXKGv1Xy7Fu/Cx+ZT/JQa7SS7tBc2ZAAQNDVaoBE2dwD0QQE0OVowDQYJKoZIhvcNAQELBQADggEBAGAax/vkv3SBFNbxp2utc/N6Rje4E0ceC972sWgqYjzYrH0oc/acg+OAXaxUjwqoQWaT+dHaI4D5qoTkMx7XlWATjI2L72IUTf6Luo92jPzyDFwb10CdeFHtRtEYD54Qbi/nD4oxQ8cSoLKC3wft2l3E/mK/1I4Mxwq15CioK4MhfzTISoeGZbjDXPKgloJOG3rn9v64vFGV6dosbLgaXEs+MPcCsPQYkwhOOyazuewRmIDOBp5QSsKPhqsT8Rs20t8LGTMkvjZniFWJs90l9QL9F1m3obq5nyuxrGt+7Rf5zoj4T+0XCOGtE+b7cRCLg43tFuTbaAQG8Z+qkPzpza+gggQ1MIIEMTCCBC0wggMVoAMCAQICFCnhUo39pSqH6x3kHUds4YpYaXOrOj8BBDBaUSLaLwIIGjAYSS+oEUludGVybWVkaWF0ZSBDQSAxMB4XDTIzMDUwMTE5MjgzOVoXDTMzMDQyOA0PUasVAEkMMIIBIi4nAgABBQD0QAEPADCCAQoCggEBAKMMyuuA66EOHnGb07P5Zc5wwiEGPDHBBn6lqErhIaN0VJ9XzlDWwyk8Q7CdPlSU7o36DXFs316eATB5bLuXXa+7WwV3cp9V5mZF9OLCz3sOWNYUanYprOMwKA3uvcqqrh8e70Dzw6sX8tfsDeH7aJoJg5kRWEKU+A3Umm+fO+hW8Km3GBqRQXxD49uxAfGtCznXZZjmFbAXqVZu+4R6wMxndfz2dYQxeMVtUY/QGdMWT4fvWzO5et3+X6hq/URUAPOkplv9O2U4T4JPucS9yZpW/FTxWC/L7vQI/bfsrSgIZpv4eJgy27FW3Q4xusbjVvUCL/t2KLvEi/Nr2qodOCECAwEAAaOB7TCB6jAdBgNVHQ4EFgQUy15QYHqrL6k7HiSrAkKN7IFgSBMwHwYDVR0jBBgwFoBSyQNQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQ4YBAMCB4AwFgEeACUBEBAMMAoGCIm0sAMJMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly8xMjcuMC4wLjE6MTg4ODgvaV1WKDFfY3JsLmRlcjAzEUscAQEEJzAlMCMRWwwwAYYXWkoALhICkTnw/0hlzm2RRjA3tvJ2wELj9e7pMg5GtdWdrLDyI/U1qBxhZoHADbyku7W+R1iL8dFfc4PSmdo+owsygZakvahXjv49xJNX7wV3YMmIHC4lfurIlY2mSnPlu2zEOwEDkI0S9WkTxXmHrkXLSciQJDkwzye6MR5fW+APk4JmKDPc46Go/K1A0EgxY/ugahMYsYtZu++W+IOYbEoYNxoCrcJCHX4c3Ep3t/Wulz4X6DWWhaDkMMUDC2JVE8E/3xUbw0X3adZe9Xf8T+goOz7wLCAigXKj1hvRUmOGISIGelv0KsfluZesG1a1TGLp+W9JX0M9nOaFOvjJTDP96aqIjs8oXGk="
  2157  					}
  2158  				}`,
  2159  			errors.New("remote error: tls: bad certificate"),
  2160  			errors.New("expect error"),
  2161  		},
  2162  		{
  2163  			"Expired Good response in cache for UserA1 -- should be allowed connection (cached item irrelevant)",
  2164  			`
  2165  				port: -1
  2166  				http_port: 8222
  2167  				tls: {
  2168  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2169  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2170  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2171  					timeout: 5
  2172  					verify: true
  2173  					# Turn on CA OCSP check but allow when CA is unreachable
  2174  					ocsp_peer: {
  2175  						verify: true
  2176  						ca_timeout: 0.5
  2177  						allow_when_ca_unreachable: true
  2178  					}
  2179  				}
  2180  				# preserve revoked true
  2181  				ocsp_cache: {
  2182  					type: local
  2183  					preserve_revoked: true
  2184  				}
  2185  			`,
  2186  			[]nats.Option{
  2187  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2188  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2189  				nats.ErrorHandler(noOpErrHandler),
  2190  			},
  2191  			`
  2192  			{
  2193  				"5xL/SuHl6JN0OmxrNMpzVMTA73JVYcRfGX8+HvJinEI=": {
  2194  					"subject": "CN=UserA1,O=Testnats,L=Tacoma,ST=WA,C=US",
  2195  					"cached_at": "2023-06-05T16:33:52Z",
  2196  					"resp_status": "good",
  2197  					"resp_expires": "2023-06-05T16:33:55Z",
  2198  					"resp": "/wYAAFMyc1R3TwBYBQBgpzMn1wzUMIIGUwoBAKCCBkwwggZIBgkrBgEFBQcwAQEEggY5MIIGNTCB5aFZMFcxCzAJBgNVBAYTAlVTEQ0gCAwCV0ExDzANAQ0wBwwGVGFjb21hMREwDwEROAoMCFRlc3RuYXRzMRcwFQET8HYDDA5PQ1NQIFJlc3BvbmRlchgPMjAyMzA2MDUxNjMzMDBaMHcwdTBNMAkGBSsOAwIaBQAEFKgwn5fplwQy+DsulBg5SRpx0iaYBBS1kW5PZLcWhHb5tL6ZzmCVmBqOnQIUXKGv1Xy7Fu/Cx+ZT/JQa7SS7tBeAADZmABA1MVqgEToTAPRAATVaMA0GCSqGSIb3DQEBCwUAA4IBAQB9csJxA2VcpQYmC5lzI0dJJnEC1zcaP1oFbBm5VsZAbWh4mIGTqyEjMkucBqANTypnhWFRYcZE5nJE8tN8Aen0EBYkhk1wfEIhincaF3zs6x5RzigxQOqTPAanO55keKH5exYnfBcyCwAQiBbQaTXLJJdjerfqiRjqgsnLW8yl2IC8+kxTCfR4GHTK34mvqVWYYhP/xbaxTLJTp35t1vf1o78ct9R+z8W5sCSO4TsMNnExZlu4Ejeon/KivMR22j7nelTEaDCuaOl03WxKh9yhw2ix8V7lvR74wh5f4fjLZria6Y0+lUjwvvrZyBRwA62W/ihe3778q8KhLECFPQSaoIIENTCCBDEwggQtMIIDFaADAgECAhQp4VKN/aUqh+sd5B1HbOGKWGlzqzo/AQQwWlEk2jECCBowGEkxqBFJbnRlcm1lZGlhdGUgQ0EgMTAeFw0yMzA1MDExOTI4MzlaFw0zMzA0MjgND1GtFQBJDDCCASIuJwIAAQUA9EABDwAwggEKAoIBAQCjDMrrgOuhDh5xm9Oz+WXOcMIhBjwxwQZ+pahK4SGjdFSfV85Q1sMpPEOwnT5UlO6N+g1xbN9engEweWy7l12vu1sFd3KfVeZmRfTiws97DljWFGp2KazjMCgN7r3Kqq4fHu9A88OrF/LX7A3h+2iaCYOZEVhClPgN1JpvnzvoVvCptxgakUF8Q+PbsQHxrQs512WY5hWwF6lWbvuEesDMZ3X89nWEMXjFbVGP0BnTFk+H71szuXrd/l+oav1EVADzpKZb/TtlOE+CT7nEvcmaVvxU8Vgvy+70CP237K0oCGab+HiYMtuxVt0OMbrG41b1Ai/7dii7xIvza9qqHTghAgMBAAGjge0wgeowHQYDVR0OBBYEFMteUGB6qy+pOx4kqwJCjeyBYEgTMB8GA1UdIwQYMBaAUssDUDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEOGAQDAgeAMBYBHgAlARAQDDAKBgiJtrADCTA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vMTI3LjAuMC4xOjE4ODg4L2ldVigxX2NybC5kZXIwMxFLHAEBBCcwJTAjEVsMMAGGF1pKAC4SAgALBQD0AQEBAEhlzm2RRjA3tvJ2wELj9e7pMg5GtdWdrLDyI/U1qBxhZoHADbyku7W+R1iL8dFfc4PSmdo+owsygZakvahXjv49xJNX7wV3YMmIHC4lfurIlY2mSnPlu2zEOwEDkI0S9WkTxXmHrkXLSciQJDkwzye6MR5fW+APk4JmKDPc46Go/K1A0EgxY/ugahMYsYtZu++W+IOYbEoYNxoCrcJCHX4c3Ep3t/Wulz4X6DWWhaDkMMUDC2JVE8E/3xUbw0X3adZe9Xf8T+goOz7wLCAigXKj1hvRUmOGISIGelv0KsfluZesG1a1TGLp+W9JX0M9nOaFOvjJTDP96aqIjs8oXGk="
  2199  				}
  2200  			}`,
  2201  			nil,
  2202  			nil,
  2203  		},
  2204  		{
  2205  			"Expired Unknown response in cache for UserA1 -- should be allowed connection (cached item irrelevant)",
  2206  			`
  2207  				port: -1
  2208  				http_port: 8222
  2209  				tls: {
  2210  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2211  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2212  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2213  					timeout: 5
  2214  					verify: true
  2215  					# Turn on CA OCSP check but allow when CA is unreachable
  2216  					ocsp_peer: {
  2217  						verify: true
  2218  						ca_timeout: 0.5
  2219  						allow_when_ca_unreachable: true
  2220  					}
  2221  				}
  2222  				# preserve revoked true
  2223  				ocsp_cache: {
  2224  					type: local
  2225  					preserve_revoked: true
  2226  				}
  2227  			`,
  2228  			[]nats.Option{
  2229  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2230  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2231  				nats.ErrorHandler(noOpErrHandler),
  2232  			},
  2233  			`
  2234  			{
  2235  				"5xL/SuHl6JN0OmxrNMpzVMTA73JVYcRfGX8+HvJinEI=": {
  2236  					"subject": "CN=UserA1,O=Testnats,L=Tacoma,ST=WA,C=US",
  2237  					"cached_at": "2023-06-05T16:45:01Z",
  2238  					"resp_status": "unknown",
  2239  					"resp_expires": "2023-06-05T16:45:05Z",
  2240  					"resp": "/wYAAFMyc1R3TwBSBQBH1aW01wzUMIIGUwoBAKCCBkwwggZIBgkrBgEFBQcwAQEEggY5MIIGNTCB5aFZMFcxCzAJBgNVBAYTAlVTEQ0gCAwCV0ExDzANAQ0wBwwGVGFjb21hMREwDwEROAoMCFRlc3RuYXRzMRcwFQET8HYDDA5PQ1NQIFJlc3BvbmRlchgPMjAyMzA2MDUxNjQ1MDBaMHcwdTBNMAkGBSsOAwIaBQAEFKgwn5fplwQy+DsulBg5SRpx0iaYBBS1kW5PZLcWhHb5tL6ZzmCVmBqOnQIUXKGv1Xy7Fu/Cx+ZT/JQa7SS7tBeCADpmAAwxWqAROhMA9EABNVowDQYJKoZIhvcNAQELBQADggEBAAzwED88ngiFj3hLzIejZ8DE/ppticX0vgAjUM8oXjDjwNXpSQ5xdXHsDk4RAYAVpNyiAfL2fapwz91g3JuZot6npp8smtZC5D0YMKK8iMjrx2aMqVyv+ai/33WG8PRWpBNzSTYaLhlBFjhUrx8HDu97ozNbmfgDWzRS1LqkJRa5YXvkyppqYTFSX73DV9R9tOVOwZ0x5WEKst9IJ+88mXsOBGyuye2Gh9RK6KsLgaOwiD9FBf18WRKIixeVM1Y/xHc/iwFPi8k3Z6hZ6gHX8NboQ/djCyzYVSWsUedTo/62uuagHPRWoYci4HQl4bSFXfcEO/EkWGnqkWBHfYZ4soigggQ1MIIEMTCCBC0wggMVoAMCAQICFCnhUo39pSqH6x3kHUds4YpYaXOrOj8BBDBaUSTaMQIIGjAYSTGoEUludGVybWVkaWF0ZSBDQSAxMB4XDTIzMDUwMTE5MjgzOVoXDTMzMDQyOA0PUa0VAEkMMIIBIi4nAgABBQD0QAEPADCCAQoCggEBAKMMyuuA66EOHnGb07P5Zc5wwiEGPDHBBn6lqErhIaN0VJ9XzlDWwyk8Q7CdPlSU7o36DXFs316eATB5bLuXXa+7WwV3cp9V5mZF9OLCz3sOWNYUanYprOMwKA3uvcqqrh8e70Dzw6sX8tfsDeH7aJoJg5kRWEKU+A3Umm+fO+hW8Km3GBqRQXxD49uxAfGtCznXZZjmFbAXqVZu+4R6wMxndfz2dYQxeMVtUY/QGdMWT4fvWzO5et3+X6hq/URUAPOkplv9O2U4T4JPucS9yZpW/FTxWC/L7vQI/bfsrSgIZpv4eJgy27FW3Q4xusbjVvUCL/t2KLvEi/Nr2qodOCECAwEAAaOB7TCB6jAdBgNVHQ4EFgQUy15QYHqrL6k7HiSrAkKN7IFgSBMwHwYDVR0jBBgwFoBSywNQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQ4YBAMCB4AwFgEeACUBEBAMMAoGCIm2sAMJMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly8xMjcuMC4wLjE6MTg4ODgvaV1WKDFfY3JsLmRlcjAzEUscAQEEJzAlMCMRWwwwAYYXWkoALhICkTnw/0hlzm2RRjA3tvJ2wELj9e7pMg5GtdWdrLDyI/U1qBxhZoHADbyku7W+R1iL8dFfc4PSmdo+owsygZakvahXjv49xJNX7wV3YMmIHC4lfurIlY2mSnPlu2zEOwEDkI0S9WkTxXmHrkXLSciQJDkwzye6MR5fW+APk4JmKDPc46Go/K1A0EgxY/ugahMYsYtZu++W+IOYbEoYNxoCrcJCHX4c3Ep3t/Wulz4X6DWWhaDkMMUDC2JVE8E/3xUbw0X3adZe9Xf8T+goOz7wLCAigXKj1hvRUmOGISIGelv0KsfluZesG1a1TGLp+W9JX0M9nOaFOvjJTDP96aqIjs8oXGk="
  2241  				}
  2242  			}`,
  2243  			nil,
  2244  			nil,
  2245  		},
  2246  		{
  2247  			"No response in cache for UserA1 -- should be allowed connection",
  2248  			`
  2249  				port: -1
  2250  				http_port: 8222
  2251  				tls: {
  2252  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2253  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2254  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2255  					timeout: 5
  2256  					verify: true
  2257  					# Turn on CA OCSP check but allow when CA is unreachable
  2258  					ocsp_peer: {
  2259  						verify: true
  2260  						ca_timeout: 0.5
  2261  						allow_when_ca_unreachable: true
  2262  					}
  2263  				}
  2264  				# preserve revoked true
  2265  				ocsp_cache: {
  2266  					type: local
  2267  					preserve_revoked: true
  2268  				}
  2269  			`,
  2270  			[]nats.Option{
  2271  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2272  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2273  				nats.ErrorHandler(noOpErrHandler),
  2274  			},
  2275  			"",
  2276  			nil,
  2277  			nil,
  2278  		},
  2279  	} {
  2280  		t.Run(test.name, func(t *testing.T) {
  2281  			deleteLocalStore(t, "")
  2282  			c := []byte(test.cachedResponse)
  2283  			err := writeCacheFile("", c)
  2284  			if err != nil {
  2285  				t.Fatal(err)
  2286  			}
  2287  			content := test.config
  2288  			conf := createConfFile(t, []byte(content))
  2289  			s, opts := RunServerWithConfig(conf)
  2290  			defer s.Shutdown()
  2291  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2292  			if test.err == nil && err != nil {
  2293  				t.Errorf("Expected to connect, got %v", err)
  2294  			} else if test.err != nil && err == nil {
  2295  				t.Errorf("Expected error on connect")
  2296  			} else if test.err != nil && err != nil {
  2297  				// Error on connect was expected
  2298  				if test.err.Error() != err.Error() {
  2299  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2300  				}
  2301  				return
  2302  			}
  2303  			defer nc.Close()
  2304  		})
  2305  	}
  2306  }
  2307  
  2308  // TestOCSPResponseCacheLocalStoreOption is test of default and non-default local_store option
  2309  func TestOCSPResponseCacheLocalStoreOpt(t *testing.T) {
  2310  	ctx, cancel := context.WithCancel(context.Background())
  2311  	defer cancel()
  2312  
  2313  	rootCAResponder := newOCSPResponderRootCA(t)
  2314  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2315  	defer rootCAResponder.Shutdown(ctx)
  2316  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2317  
  2318  	for _, test := range []struct {
  2319  		name           string
  2320  		config         string
  2321  		opts           []nats.Option
  2322  		cachedResponse string
  2323  		err            error
  2324  		rerr           error
  2325  		storeLocation  string
  2326  	}{
  2327  		{
  2328  			"Test load from non-default local store _custom_; connect will reject only if cache file found and loaded",
  2329  			`
  2330  				port: -1
  2331  				http_port: 8222
  2332  				tls: {
  2333  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2334  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2335  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2336  					timeout: 5
  2337  					verify: true
  2338  					# Turn on CA OCSP check but allow when CA is unreachable
  2339  					ocsp_peer: {
  2340  						verify: true
  2341  						ca_timeout: 0.5
  2342  						allow_when_ca_unreachable: true
  2343  					}
  2344  				}
  2345  				# preserve revoked true
  2346  				ocsp_cache: {
  2347  					type: local
  2348  					local_store: "_custom_"
  2349  					preserve_revoked: true
  2350  				}
  2351  			`,
  2352  			[]nats.Option{
  2353  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2354  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2355  				nats.ErrorHandler(noOpErrHandler),
  2356  			},
  2357  			`
  2358  				{
  2359  					"5xL/SuHl6JN0OmxrNMpzVMTA73JVYcRfGX8+HvJinEI=": {
  2360  						"subject": "CN=UserA1,O=Testnats,L=Tacoma,ST=WA,C=US",
  2361  						"cached_at": "2023-05-29T17:56:45Z",
  2362  						"resp_status": "revoked",
  2363  						"resp_expires": "2023-05-29T17:56:49Z",
  2364  						"resp": "/wYAAFMyc1R3TwBSBQBao1Qr1QzUMIIGUQoBAKCCBkowggZGBgkrBgEFBQcwAQEEggY3MIIGMzCB46FZMFcxCzAJBgNVBAYTAlVTEQ0gCAwCV0ExDzANAQ0wBwwGVGFjb21hMREwDwEROAoMCFRlc3RuYXRzMRcwFQET8HQDDA5PQ1NQIFJlc3BvbmRlchgPMjAyMzA1MjkxNzU2MDBaMHUwczBNMAkGBSsOAwIaBQAEFKgwn5fplwQy+DsulBg5SRpx0iaYBBS1kW5PZLcWhHb5tL6ZzmCVmBqOnQIUXKGv1Xy7Fu/Cx+ZT/JQa7SS7tBc2ZAAQNDVaoBE2dwD0QQE0OVowDQYJKoZIhvcNAQELBQADggEBAGAax/vkv3SBFNbxp2utc/N6Rje4E0ceC972sWgqYjzYrH0oc/acg+OAXaxUjwqoQWaT+dHaI4D5qoTkMx7XlWATjI2L72IUTf6Luo92jPzyDFwb10CdeFHtRtEYD54Qbi/nD4oxQ8cSoLKC3wft2l3E/mK/1I4Mxwq15CioK4MhfzTISoeGZbjDXPKgloJOG3rn9v64vFGV6dosbLgaXEs+MPcCsPQYkwhOOyazuewRmIDOBp5QSsKPhqsT8Rs20t8LGTMkvjZniFWJs90l9QL9F1m3obq5nyuxrGt+7Rf5zoj4T+0XCOGtE+b7cRCLg43tFuTbaAQG8Z+qkPzpza+gggQ1MIIEMTCCBC0wggMVoAMCAQICFCnhUo39pSqH6x3kHUds4YpYaXOrOj8BBDBaUSLaLwIIGjAYSS+oEUludGVybWVkaWF0ZSBDQSAxMB4XDTIzMDUwMTE5MjgzOVoXDTMzMDQyOA0PUasVAEkMMIIBIi4nAgABBQD0QAEPADCCAQoCggEBAKMMyuuA66EOHnGb07P5Zc5wwiEGPDHBBn6lqErhIaN0VJ9XzlDWwyk8Q7CdPlSU7o36DXFs316eATB5bLuXXa+7WwV3cp9V5mZF9OLCz3sOWNYUanYprOMwKA3uvcqqrh8e70Dzw6sX8tfsDeH7aJoJg5kRWEKU+A3Umm+fO+hW8Km3GBqRQXxD49uxAfGtCznXZZjmFbAXqVZu+4R6wMxndfz2dYQxeMVtUY/QGdMWT4fvWzO5et3+X6hq/URUAPOkplv9O2U4T4JPucS9yZpW/FTxWC/L7vQI/bfsrSgIZpv4eJgy27FW3Q4xusbjVvUCL/t2KLvEi/Nr2qodOCECAwEAAaOB7TCB6jAdBgNVHQ4EFgQUy15QYHqrL6k7HiSrAkKN7IFgSBMwHwYDVR0jBBgwFoBSyQNQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQ4YBAMCB4AwFgEeACUBEBAMMAoGCIm0sAMJMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly8xMjcuMC4wLjE6MTg4ODgvaV1WKDFfY3JsLmRlcjAzEUscAQEEJzAlMCMRWwwwAYYXWkoALhICkTnw/0hlzm2RRjA3tvJ2wELj9e7pMg5GtdWdrLDyI/U1qBxhZoHADbyku7W+R1iL8dFfc4PSmdo+owsygZakvahXjv49xJNX7wV3YMmIHC4lfurIlY2mSnPlu2zEOwEDkI0S9WkTxXmHrkXLSciQJDkwzye6MR5fW+APk4JmKDPc46Go/K1A0EgxY/ugahMYsYtZu++W+IOYbEoYNxoCrcJCHX4c3Ep3t/Wulz4X6DWWhaDkMMUDC2JVE8E/3xUbw0X3adZe9Xf8T+goOz7wLCAigXKj1hvRUmOGISIGelv0KsfluZesG1a1TGLp+W9JX0M9nOaFOvjJTDP96aqIjs8oXGk="
  2365  					}
  2366  				}`,
  2367  			errors.New("remote error: tls: bad certificate"),
  2368  			errors.New("expect error"),
  2369  			"_custom_",
  2370  		},
  2371  		{
  2372  			"Test load from default local store when \"\" set; connect will reject only if cache file found and loaded",
  2373  			`
  2374  				port: -1
  2375  				http_port: 8222
  2376  				tls: {
  2377  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2378  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2379  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2380  					timeout: 5
  2381  					verify: true
  2382  					# Turn on CA OCSP check but allow when CA is unreachable
  2383  					ocsp_peer: {
  2384  						verify: true
  2385  						ca_timeout: 0.5
  2386  						allow_when_ca_unreachable: true
  2387  					}
  2388  				}
  2389  				# preserve revoked true
  2390  				ocsp_cache: {
  2391  					type: local
  2392  					local_store: ""
  2393  					preserve_revoked: true
  2394  				}
  2395  			`,
  2396  			[]nats.Option{
  2397  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2398  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2399  				nats.ErrorHandler(noOpErrHandler),
  2400  			},
  2401  			`
  2402  				{
  2403  					"5xL/SuHl6JN0OmxrNMpzVMTA73JVYcRfGX8+HvJinEI=": {
  2404  						"subject": "CN=UserA1,O=Testnats,L=Tacoma,ST=WA,C=US",
  2405  						"cached_at": "2023-05-29T17:56:45Z",
  2406  						"resp_status": "revoked",
  2407  						"resp_expires": "2023-05-29T17:56:49Z",
  2408  						"resp": "/wYAAFMyc1R3TwBSBQBao1Qr1QzUMIIGUQoBAKCCBkowggZGBgkrBgEFBQcwAQEEggY3MIIGMzCB46FZMFcxCzAJBgNVBAYTAlVTEQ0gCAwCV0ExDzANAQ0wBwwGVGFjb21hMREwDwEROAoMCFRlc3RuYXRzMRcwFQET8HQDDA5PQ1NQIFJlc3BvbmRlchgPMjAyMzA1MjkxNzU2MDBaMHUwczBNMAkGBSsOAwIaBQAEFKgwn5fplwQy+DsulBg5SRpx0iaYBBS1kW5PZLcWhHb5tL6ZzmCVmBqOnQIUXKGv1Xy7Fu/Cx+ZT/JQa7SS7tBc2ZAAQNDVaoBE2dwD0QQE0OVowDQYJKoZIhvcNAQELBQADggEBAGAax/vkv3SBFNbxp2utc/N6Rje4E0ceC972sWgqYjzYrH0oc/acg+OAXaxUjwqoQWaT+dHaI4D5qoTkMx7XlWATjI2L72IUTf6Luo92jPzyDFwb10CdeFHtRtEYD54Qbi/nD4oxQ8cSoLKC3wft2l3E/mK/1I4Mxwq15CioK4MhfzTISoeGZbjDXPKgloJOG3rn9v64vFGV6dosbLgaXEs+MPcCsPQYkwhOOyazuewRmIDOBp5QSsKPhqsT8Rs20t8LGTMkvjZniFWJs90l9QL9F1m3obq5nyuxrGt+7Rf5zoj4T+0XCOGtE+b7cRCLg43tFuTbaAQG8Z+qkPzpza+gggQ1MIIEMTCCBC0wggMVoAMCAQICFCnhUo39pSqH6x3kHUds4YpYaXOrOj8BBDBaUSLaLwIIGjAYSS+oEUludGVybWVkaWF0ZSBDQSAxMB4XDTIzMDUwMTE5MjgzOVoXDTMzMDQyOA0PUasVAEkMMIIBIi4nAgABBQD0QAEPADCCAQoCggEBAKMMyuuA66EOHnGb07P5Zc5wwiEGPDHBBn6lqErhIaN0VJ9XzlDWwyk8Q7CdPlSU7o36DXFs316eATB5bLuXXa+7WwV3cp9V5mZF9OLCz3sOWNYUanYprOMwKA3uvcqqrh8e70Dzw6sX8tfsDeH7aJoJg5kRWEKU+A3Umm+fO+hW8Km3GBqRQXxD49uxAfGtCznXZZjmFbAXqVZu+4R6wMxndfz2dYQxeMVtUY/QGdMWT4fvWzO5et3+X6hq/URUAPOkplv9O2U4T4JPucS9yZpW/FTxWC/L7vQI/bfsrSgIZpv4eJgy27FW3Q4xusbjVvUCL/t2KLvEi/Nr2qodOCECAwEAAaOB7TCB6jAdBgNVHQ4EFgQUy15QYHqrL6k7HiSrAkKN7IFgSBMwHwYDVR0jBBgwFoBSyQNQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQ4YBAMCB4AwFgEeACUBEBAMMAoGCIm0sAMJMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly8xMjcuMC4wLjE6MTg4ODgvaV1WKDFfY3JsLmRlcjAzEUscAQEEJzAlMCMRWwwwAYYXWkoALhICkTnw/0hlzm2RRjA3tvJ2wELj9e7pMg5GtdWdrLDyI/U1qBxhZoHADbyku7W+R1iL8dFfc4PSmdo+owsygZakvahXjv49xJNX7wV3YMmIHC4lfurIlY2mSnPlu2zEOwEDkI0S9WkTxXmHrkXLSciQJDkwzye6MR5fW+APk4JmKDPc46Go/K1A0EgxY/ugahMYsYtZu++W+IOYbEoYNxoCrcJCHX4c3Ep3t/Wulz4X6DWWhaDkMMUDC2JVE8E/3xUbw0X3adZe9Xf8T+goOz7wLCAigXKj1hvRUmOGISIGelv0KsfluZesG1a1TGLp+W9JX0M9nOaFOvjJTDP96aqIjs8oXGk="
  2409  					}
  2410  				}`,
  2411  			errors.New("remote error: tls: bad certificate"),
  2412  			errors.New("expect error"),
  2413  			"_rc_",
  2414  		},
  2415  	} {
  2416  		t.Run(test.name, func(t *testing.T) {
  2417  			deleteLocalStore(t, test.storeLocation)
  2418  			c := []byte(test.cachedResponse)
  2419  			err := writeCacheFile(test.storeLocation, c)
  2420  			if err != nil {
  2421  				t.Fatal(err)
  2422  			}
  2423  			content := test.config
  2424  			conf := createConfFile(t, []byte(content))
  2425  			s, opts := RunServerWithConfig(conf)
  2426  			defer s.Shutdown()
  2427  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2428  			if test.err == nil && err != nil {
  2429  				t.Errorf("Expected to connect, got %v", err)
  2430  			} else if test.err != nil && err == nil {
  2431  				t.Errorf("Expected error on connect")
  2432  			} else if test.err != nil && err != nil {
  2433  				// Error on connect was expected
  2434  				if test.err.Error() != err.Error() {
  2435  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2436  				}
  2437  				return
  2438  			}
  2439  			defer nc.Close()
  2440  		})
  2441  	}
  2442  }
  2443  
  2444  // TestOCSPPeerIncrementalSaveLocalCache is test of timer-based response cache save as new entries added
  2445  func TestOCSPPeerIncrementalSaveLocalCache(t *testing.T) {
  2446  	ctx, cancel := context.WithCancel(context.Background())
  2447  	defer cancel()
  2448  
  2449  	rootCAResponder := newOCSPResponderRootCA(t)
  2450  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2451  	defer rootCAResponder.Shutdown(ctx)
  2452  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2453  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate2/intermediate2_cert.pem", ocsp.Good)
  2454  
  2455  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
  2456  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  2457  	defer intermediateCA1Responder.Shutdown(ctx)
  2458  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
  2459  
  2460  	intermediateCA2Responder := newOCSPResponderIntermediateCA2(t)
  2461  	intermediateCA2ResponderURL := fmt.Sprintf("http://%s", intermediateCA2Responder.Addr)
  2462  	defer intermediateCA2Responder.Shutdown(ctx)
  2463  	setOCSPStatus(t, intermediateCA2ResponderURL, "configs/certs/ocsp_peer/mini-ca/client2/UserB1_cert.pem", ocsp.Good)
  2464  
  2465  	var fi os.FileInfo
  2466  	var err error
  2467  
  2468  	for _, test := range []struct {
  2469  		name      string
  2470  		config    string
  2471  		opts      [][]nats.Option
  2472  		err       error
  2473  		rerr      error
  2474  		configure func()
  2475  	}{
  2476  		{
  2477  			"Default cache, short form: mTLS OCSP peer check on inbound client connection, UserA1 client of intermediate CA 1",
  2478  			`
  2479  				port: -1
  2480  				http_port: 8222
  2481  				tls: {
  2482  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2483  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2484  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2485  					timeout: 5
  2486  					verify: true
  2487  					# Long form configuration
  2488  					ocsp_peer: {
  2489  						verify: true
  2490  						ca_timeout: 5
  2491  						allowed_clockskew: 30
  2492  					}
  2493  				}
  2494  				# Local cache with custom save_interval for testability
  2495  				ocsp_cache: {
  2496  					type: local
  2497  					# Save if dirty ever 1 second
  2498  					save_interval: 1
  2499  				}
  2500  			`,
  2501  			[][]nats.Option{
  2502  				{
  2503  					nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2504  					nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2505  					nats.ErrorHandler(noOpErrHandler),
  2506  				},
  2507  				{
  2508  					nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client2/UserB1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client2/private/UserB1_keypair.pem"),
  2509  					nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2510  					nats.ErrorHandler(noOpErrHandler),
  2511  				},
  2512  			},
  2513  			nil,
  2514  			nil,
  2515  			func() {},
  2516  		},
  2517  	} {
  2518  		t.Run(test.name, func(t *testing.T) {
  2519  			// Cleanup any previous test that saved a local cache
  2520  			deleteLocalStore(t, "")
  2521  			fi, err = statCacheFile("")
  2522  			if err != nil && fi != nil && fi.Size() != 0 {
  2523  				t.Fatalf("Expected no local cache file, got a FileInfo with size %d", fi.Size())
  2524  			}
  2525  			test.configure()
  2526  			content := test.config
  2527  			conf := createConfFile(t, []byte(content))
  2528  			s, opts := RunServerWithConfig(conf)
  2529  			defer s.Shutdown()
  2530  
  2531  			// Connect with UserA1 client and get a CA Response
  2532  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts[0]...)
  2533  			if test.err == nil && err != nil {
  2534  				t.Errorf("Expected to connect, got %v", err)
  2535  			} else if test.err != nil && err == nil {
  2536  				t.Errorf("Expected error on connect")
  2537  			} else if test.err != nil && err != nil {
  2538  				// Error on connect was expected
  2539  				if test.err.Error() != err.Error() {
  2540  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2541  				}
  2542  				return
  2543  			}
  2544  			nc.Close()
  2545  			time.Sleep(2 * time.Second)
  2546  			fi, err = statCacheFile("")
  2547  			if err == nil && fi != nil && fi.Size() > 0 {
  2548  				// good
  2549  			} else {
  2550  				if err != nil {
  2551  					t.Fatalf("Expected an extant local cache file, got error: %v", err)
  2552  				}
  2553  				if fi != nil {
  2554  					t.Fatalf("Expected non-zero size local cache file, got a FileInfo with size %d", fi.Size())
  2555  				}
  2556  			}
  2557  			firstFi := fi
  2558  			// Connect with UserB1 client and get another CA Response
  2559  			nc, err = nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts[1]...)
  2560  			if test.err == nil && err != nil {
  2561  				t.Errorf("Expected to connect, got %v", err)
  2562  			} else if test.err != nil && err == nil {
  2563  				t.Errorf("Expected error on connect")
  2564  			} else if test.err != nil && err != nil {
  2565  				// Error on connect was expected
  2566  				if test.err.Error() != err.Error() {
  2567  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2568  				}
  2569  				return
  2570  			}
  2571  			nc.Close()
  2572  			time.Sleep(2 * time.Second)
  2573  			fi, err = statCacheFile("")
  2574  			if err == nil && fi != nil && fi.Size() > firstFi.Size() {
  2575  				// good
  2576  			} else {
  2577  				if err != nil {
  2578  					t.Fatalf("Expected an extant local cache file, got error: %v", err)
  2579  				}
  2580  				if fi != nil {
  2581  					t.Fatalf("Expected non-zero size local cache file with more bytes, got a FileInfo with size %d", fi.Size())
  2582  				}
  2583  			}
  2584  		})
  2585  	}
  2586  }
  2587  
  2588  func statCacheFile(dir string) (os.FileInfo, error) {
  2589  	if dir == "" {
  2590  		dir = "_rc_"
  2591  	}
  2592  	return os.Stat(filepath.Join(dir, "cache.json"))
  2593  }
  2594  
  2595  // TestOCSPPeerUndelegatedCAResponseSigner
  2596  func TestOCSPPeerUndelegatedCAResponseSigner(t *testing.T) {
  2597  	ctx, cancel := context.WithCancel(context.Background())
  2598  	defer cancel()
  2599  
  2600  	rootCAResponder := newOCSPResponderRootCA(t)
  2601  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2602  	defer rootCAResponder.Shutdown(ctx)
  2603  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2604  
  2605  	intermediateCA1Responder := newOCSPResponderIntermediateCA1Undelegated(t)
  2606  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  2607  	defer intermediateCA1Responder.Shutdown(ctx)
  2608  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
  2609  
  2610  	for _, test := range []struct {
  2611  		name      string
  2612  		config    string
  2613  		opts      []nats.Option
  2614  		err       error
  2615  		rerr      error
  2616  		configure func()
  2617  	}{
  2618  		{
  2619  			"mTLS OCSP peer check on inbound client connection, responder is CA (undelegated)",
  2620  			`
  2621  				port: -1
  2622  				# Cache configuration is default
  2623  				tls: {
  2624  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2625  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2626  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2627  					timeout: 5
  2628  					verify: true
  2629  					# Turn on CA OCSP check so unvalidated clients can't connect
  2630  					ocsp_peer: true
  2631  				}
  2632  			`,
  2633  			[]nats.Option{
  2634  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2635  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2636  				nats.ErrorHandler(noOpErrHandler),
  2637  			},
  2638  			nil,
  2639  			nil,
  2640  			func() {},
  2641  		},
  2642  	} {
  2643  		t.Run(test.name, func(t *testing.T) {
  2644  			deleteLocalStore(t, "")
  2645  			test.configure()
  2646  			content := test.config
  2647  			conf := createConfFile(t, []byte(content))
  2648  			s, opts := RunServerWithConfig(conf)
  2649  			defer s.Shutdown()
  2650  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2651  			if test.err == nil && err != nil {
  2652  				t.Errorf("Expected to connect, got %v", err)
  2653  			} else if test.err != nil && err == nil {
  2654  				t.Errorf("Expected error on connect")
  2655  			} else if test.err != nil && err != nil {
  2656  				// Error on connect was expected
  2657  				if test.err.Error() != err.Error() {
  2658  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2659  				}
  2660  				return
  2661  			}
  2662  			defer nc.Close()
  2663  		})
  2664  	}
  2665  }
  2666  
  2667  // TestOCSPPeerDelegatedCAResponseSigner
  2668  func TestOCSPPeerDelegatedCAResponseSigner(t *testing.T) {
  2669  	ctx, cancel := context.WithCancel(context.Background())
  2670  	defer cancel()
  2671  
  2672  	rootCAResponder := newOCSPResponderRootCA(t)
  2673  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2674  	defer rootCAResponder.Shutdown(ctx)
  2675  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2676  
  2677  	intermediateCA1Responder := newOCSPResponderIntermediateCA1(t)
  2678  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  2679  	defer intermediateCA1Responder.Shutdown(ctx)
  2680  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
  2681  
  2682  	for _, test := range []struct {
  2683  		name      string
  2684  		config    string
  2685  		opts      []nats.Option
  2686  		err       error
  2687  		rerr      error
  2688  		configure func()
  2689  	}{
  2690  		{
  2691  			"mTLS OCSP peer check on inbound client connection, responder is CA (undelegated)",
  2692  			`
  2693  				port: -1
  2694  				# Cache configuration is default
  2695  				tls: {
  2696  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2697  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2698  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2699  					timeout: 5
  2700  					verify: true
  2701  					# Turn on CA OCSP check so unvalidated clients can't connect
  2702  					ocsp_peer: true
  2703  				}
  2704  			`,
  2705  			[]nats.Option{
  2706  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2707  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2708  				nats.ErrorHandler(noOpErrHandler),
  2709  			},
  2710  			nil,
  2711  			nil,
  2712  			func() {},
  2713  		},
  2714  	} {
  2715  		t.Run(test.name, func(t *testing.T) {
  2716  			deleteLocalStore(t, "")
  2717  			test.configure()
  2718  			content := test.config
  2719  			conf := createConfFile(t, []byte(content))
  2720  			s, opts := RunServerWithConfig(conf)
  2721  			defer s.Shutdown()
  2722  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2723  			if test.err == nil && err != nil {
  2724  				t.Errorf("Expected to connect, got %v", err)
  2725  			} else if test.err != nil && err == nil {
  2726  				t.Errorf("Expected error on connect")
  2727  			} else if test.err != nil && err != nil {
  2728  				// Error on connect was expected
  2729  				if test.err.Error() != err.Error() {
  2730  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2731  				}
  2732  				return
  2733  			}
  2734  			defer nc.Close()
  2735  		})
  2736  	}
  2737  }
  2738  
  2739  // TestOCSPPeerBadDelegatedCAResponseSigner
  2740  func TestOCSPPeerBadDelegatedCAResponseSigner(t *testing.T) {
  2741  	ctx, cancel := context.WithCancel(context.Background())
  2742  	defer cancel()
  2743  
  2744  	rootCAResponder := newOCSPResponderRootCA(t)
  2745  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2746  	defer rootCAResponder.Shutdown(ctx)
  2747  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2748  
  2749  	intermediateCA1Responder := newOCSPResponderBadDelegateIntermediateCA1(t)
  2750  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  2751  	defer intermediateCA1Responder.Shutdown(ctx)
  2752  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
  2753  
  2754  	for _, test := range []struct {
  2755  		name      string
  2756  		config    string
  2757  		opts      []nats.Option
  2758  		err       error
  2759  		rerr      error
  2760  		configure func()
  2761  	}{
  2762  		{
  2763  			"mTLS OCSP peer check on inbound client connection, responder is not a legal delegate",
  2764  			`
  2765  				port: -1
  2766  				# Cache configuration is default
  2767  				tls: {
  2768  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2769  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2770  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2771  					timeout: 5
  2772  					verify: true
  2773  					# Turn on CA OCSP check so unvalidated clients can't connect
  2774  					ocsp_peer: true
  2775  				}
  2776  			`,
  2777  			[]nats.Option{
  2778  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2779  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2780  				nats.ErrorHandler(noOpErrHandler),
  2781  			},
  2782  			errors.New("remote error: tls: bad certificate"),
  2783  			errors.New("expect error"),
  2784  			func() {},
  2785  		},
  2786  	} {
  2787  		t.Run(test.name, func(t *testing.T) {
  2788  			deleteLocalStore(t, "")
  2789  			test.configure()
  2790  			content := test.config
  2791  			conf := createConfFile(t, []byte(content))
  2792  			s, opts := RunServerWithConfig(conf)
  2793  			defer s.Shutdown()
  2794  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2795  			if test.err == nil && err != nil {
  2796  				t.Errorf("Expected to connect, got %v", err)
  2797  			} else if test.err != nil && err == nil {
  2798  				t.Errorf("Expected error on connect")
  2799  			} else if test.err != nil && err != nil {
  2800  				// Error on connect was expected
  2801  				if test.err.Error() != err.Error() {
  2802  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2803  				}
  2804  				return
  2805  			}
  2806  			defer nc.Close()
  2807  		})
  2808  	}
  2809  }
  2810  
  2811  // TestOCSPPeerNextUpdateUnset is test of scenario when responder does not set NextUpdate and cache TTL option is used
  2812  func TestOCSPPeerNextUpdateUnset(t *testing.T) {
  2813  	ctx, cancel := context.WithCancel(context.Background())
  2814  	defer cancel()
  2815  
  2816  	rootCAResponder := newOCSPResponderRootCA(t)
  2817  	rootCAResponderURL := fmt.Sprintf("http://%s", rootCAResponder.Addr)
  2818  	defer rootCAResponder.Shutdown(ctx)
  2819  	setOCSPStatus(t, rootCAResponderURL, "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem", ocsp.Good)
  2820  
  2821  	respCertPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/ocsp1_bundle.pem"
  2822  	respKeyPEM := "configs/certs/ocsp_peer/mini-ca/ocsp1/private/ocsp1_keypair.pem"
  2823  	issuerCertPEM := "configs/certs/ocsp_peer/mini-ca/intermediate1/intermediate1_cert.pem"
  2824  	intermediateCA1Responder := newOCSPResponderBase(t, issuerCertPEM, respCertPEM, respKeyPEM, true, "127.0.0.1:18888", 0, "")
  2825  	intermediateCA1ResponderURL := fmt.Sprintf("http://%s", intermediateCA1Responder.Addr)
  2826  	defer intermediateCA1Responder.Shutdown(ctx)
  2827  	setOCSPStatus(t, intermediateCA1ResponderURL, "configs/certs/ocsp_peer/mini-ca/client1/UserA1_cert.pem", ocsp.Good)
  2828  
  2829  	for _, test := range []struct {
  2830  		name           string
  2831  		config         string
  2832  		opts           []nats.Option
  2833  		err            error
  2834  		rerr           error
  2835  		expectedMisses int64
  2836  		configure      func()
  2837  	}{
  2838  		{
  2839  			"TTL set to 4 seconds with second client connection leveraging cache from first client connect",
  2840  			`
  2841  				port: -1
  2842  				http_port: 8222
  2843  				tls: {
  2844  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2845  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2846  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2847  					timeout: 5
  2848  					verify: true
  2849  					# Long form configuration
  2850  					ocsp_peer: {
  2851  						verify: true
  2852  						ca_timeout: 5
  2853  						allowed_clockskew: 0
  2854  						cache_ttl_when_next_update_unset: 4
  2855  					}
  2856  				}
  2857  				# Short form configuration, local as default
  2858  				ocsp_cache: true
  2859  			`,
  2860  			[]nats.Option{
  2861  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2862  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2863  				nats.ErrorHandler(noOpErrHandler),
  2864  			},
  2865  			nil,
  2866  			nil,
  2867  			2,
  2868  			func() {},
  2869  		},
  2870  		{
  2871  			"TTL set to 1 seconds with second client connection not leveraging cache items from first client connect",
  2872  			`
  2873  				port: -1
  2874  				http_port: 8222
  2875  				tls: {
  2876  					cert_file: "configs/certs/ocsp_peer/mini-ca/server1/TestServer1_bundle.pem"
  2877  					key_file: "configs/certs/ocsp_peer/mini-ca/server1/private/TestServer1_keypair.pem"
  2878  					ca_file: "configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"
  2879  					timeout: 5
  2880  					verify: true
  2881  					# Long form configuration
  2882  					ocsp_peer: {
  2883  						verify: true
  2884  						ca_timeout: 5
  2885  						allowed_clockskew: 0
  2886  						cache_ttl_when_next_update_unset: 1
  2887  					}
  2888  				}
  2889  				# Short form configuration, local as default
  2890  				ocsp_cache: true
  2891  			`,
  2892  			[]nats.Option{
  2893  				nats.ClientCert("./configs/certs/ocsp_peer/mini-ca/client1/UserA1_bundle.pem", "./configs/certs/ocsp_peer/mini-ca/client1/private/UserA1_keypair.pem"),
  2894  				nats.RootCAs("./configs/certs/ocsp_peer/mini-ca/root/root_cert.pem"),
  2895  				nats.ErrorHandler(noOpErrHandler),
  2896  			},
  2897  			nil,
  2898  			nil,
  2899  			3,
  2900  			func() {},
  2901  		},
  2902  	} {
  2903  		t.Run(test.name, func(t *testing.T) {
  2904  			// Cleanup any previous test that saved a local cache
  2905  			deleteLocalStore(t, "")
  2906  			test.configure()
  2907  			content := test.config
  2908  			conf := createConfFile(t, []byte(content))
  2909  			s, opts := RunServerWithConfig(conf)
  2910  			defer s.Shutdown()
  2911  			nc, err := nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2912  			if test.err == nil && err != nil {
  2913  				t.Errorf("Expected to connect, got %v", err)
  2914  			} else if test.err != nil && err == nil {
  2915  				t.Errorf("Expected error on connect")
  2916  			} else if test.err != nil && err != nil {
  2917  				// Error on connect was expected
  2918  				if test.err.Error() != err.Error() {
  2919  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2920  				}
  2921  				return
  2922  			}
  2923  			nc.Close()
  2924  
  2925  			// Wait interval shorter than first test, and longer than second test
  2926  			time.Sleep(2 * time.Second)
  2927  
  2928  			nc, err = nats.Connect(fmt.Sprintf("tls://localhost:%d", opts.Port), test.opts...)
  2929  			if test.err == nil && err != nil {
  2930  				t.Errorf("Expected to connect, got %v", err)
  2931  			} else if test.err != nil && err == nil {
  2932  				t.Errorf("Expected error on connect")
  2933  			} else if test.err != nil && err != nil {
  2934  				// Error on connect was expected
  2935  				if test.err.Error() != err.Error() {
  2936  					t.Errorf("Expected error %s, got: %s", test.err, err)
  2937  				}
  2938  				return
  2939  			}
  2940  			defer nc.Close()
  2941  
  2942  			v := monitorGetVarzHelper(t, 8222)
  2943  			if v.OCSPResponseCache == nil {
  2944  				t.Fatalf("Expected OCSP statistics to be in varz")
  2945  			}
  2946  			if v.OCSPResponseCache.Misses != test.expectedMisses || v.OCSPResponseCache.Responses != 2 {
  2947  				t.Errorf("Expected cache misses to be %d and cache items to be 2, got %d and %d", test.expectedMisses, v.OCSPResponseCache.Misses, v.OCSPResponseCache.Responses)
  2948  			}
  2949  		})
  2950  	}
  2951  }