neoneo-go/cli/server/cli_server_mtls_test.go
Evgenii Stratonikov c8531e85a4 cli/server: Write end2end tests for mTLS
Signed-off-by: Evgenii Stratonikov <fyfyrchik@runbox.com>
2024-06-11 15:38:32 +03:00

113 lines
2.9 KiB
Go

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()
}