package server_test import ( "context" "crypto/tls" "path/filepath" "testing" "github.com/nspcc-dev/neo-go/internal/testcli" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/stretchr/testify/require" ) const certDir = "../../mtlstestdata/certs" type tlsConfig struct { ca string cert string key string } func TestServerMTLS(t *testing.T) { t.Run("http", func(t *testing.T) { testServerMTLS(t, testServerMTLSHttp) }) t.Run("websocket", func(t *testing.T) { testServerMTLS(t, testServerMTLSWebSocket) }) } func testServerMTLS(t *testing.T, test func(*testing.T, tlsConfig, tlsConfig) error) { configs := map[string]map[string]tlsConfig{} for _, ca := range []string{"CA1", "CA2"} { configs[ca] = make(map[string]tlsConfig) for _, peer := range []string{"1", "2"} { configs[ca][peer] = tlsConfig{ ca: filepath.Join(certDir, ca+"_cert.pem"), cert: filepath.Join(certDir, "peer"+ca+"_"+peer+"_cert.pem"), key: filepath.Join(certDir, "peer"+ca+"_"+peer+"_key.pem"), } } } t.Run("good", func(t *testing.T) { require.NoError(t, test(t, configs["CA1"]["1"], configs["CA1"]["2"])) }) t.Run("wrong cert", func(t *testing.T) { var verificationError *tls.CertificateVerificationError err := test(t, configs["CA1"]["1"], configs["CA2"]["2"]) require.ErrorAs(t, err, &verificationError) }) } func testServerMTLSHttp(t *testing.T, server, client tlsConfig) error { e := testcli.NewExecutorWithConfig(t, true, true, func(c *config.Config) { rpc := &c.ApplicationConfiguration.RPC rpc.Addresses = nil cc := &rpc.TLSConfig cc.Addresses = []string{"127.0.0.1:0"} cc.Enabled = true cc.RootCA = []string{server.ca} cc.CertFile = server.cert cc.KeyFile = server.key }) cfg, err := rpcclient.TLSClientConfig([]string{client.ca}, client.cert, client.key) require.NoError(t, err) endpoint := "https://" + e.RPC.Addresses()[0] c, err := rpcclient.New(context.Background(), endpoint, rpcclient.Options{ TLSClientConfig: cfg, }) require.NoError(t, err) defer c.Close() return c.Init() } func testServerMTLSWebSocket(t *testing.T, server, client tlsConfig) error { e := testcli.NewExecutorWithConfig(t, true, true, func(c *config.Config) { rpc := &c.ApplicationConfiguration.RPC rpc.Addresses = nil cc := &rpc.TLSConfig cc.Addresses = []string{"127.0.0.1:0"} cc.Enabled = true cc.RootCA = []string{server.ca} cc.CertFile = server.cert cc.KeyFile = server.key }) cfg, err := rpcclient.TLSClientConfig([]string{client.ca}, client.cert, client.key) require.NoError(t, err) endpoint := "wss://" + e.RPC.Addresses()[0] + "/ws" c, err := rpcclient.NewWS(context.Background(), endpoint, rpcclient.WSOptions{ Options: rpcclient.Options{ TLSClientConfig: cfg, }, }) if err != nil { // For the websocket client, NewWS() creates a connection, // so TLS handshake error will be returned from there. return err } defer c.Close() return c.Init() }