From df9254cc11c75fc2cc2ddafbb9dbb9d5ba39f700 Mon Sep 17 00:00:00 2001 From: DerekBum Date: Sat, 3 Feb 2024 21:44:15 +0300 Subject: [PATCH] api: remove ssl `OpenSslDialer` and all of its helper functions and tests were rellocated to the `go-tlsdialer` [1] package (and renamed to `OpenSSLDialer`). So now we can safely remove all the copy-pasted code from `go-tarantool`. This way, in order to use SSL, user should import the `go-tlsdialer` package and call functions from there. 1. https://github.com/tarantool/go-tlsdialer/ Part of #301 --- .github/workflows/testing.yml | 23 - CHANGELOG.md | 2 +- CONTRIBUTING.md | 14 - README.md | 66 ++- dial.go | 109 ----- dial_test.go | 48 ++- example_test.go | 18 - export_test.go | 13 - go.mod | 4 - go.sum | 17 +- ssl.go | 30 -- ssl_disable.go | 19 - ssl_enable.go | 144 ------- ssl_test.go | 780 ---------------------------------- tarantool_test.go | 20 + testdata/ca.crt | 20 - testdata/empty | 0 testdata/generate.sh | 38 -- testdata/invalidpasswords | 1 - testdata/localhost.crt | 22 - testdata/localhost.enc.key | 30 -- testdata/localhost.key | 28 -- testdata/passwords | 2 - 23 files changed, 119 insertions(+), 1329 deletions(-) delete mode 100644 ssl.go delete mode 100644 ssl_disable.go delete mode 100644 ssl_enable.go delete mode 100644 ssl_test.go delete mode 100644 testdata/ca.crt delete mode 100644 testdata/empty delete mode 100755 testdata/generate.sh delete mode 100644 testdata/invalidpasswords delete mode 100644 testdata/localhost.crt delete mode 100644 testdata/localhost.enc.key delete mode 100644 testdata/localhost.key delete mode 100644 testdata/passwords diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index cba02c6ab..3cf0d2808 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -103,11 +103,6 @@ jobs: make test make testrace - - name: Run regression tests with disabled SSL - run: | - make test TAGS="go_tarantool_ssl_disable" - make testrace TAGS="go_tarantool_ssl_disable" - - name: Run fuzzing tests if: ${{ matrix.fuzzing }} run: make fuzzing TAGS="go_tarantool_decimal_fuzzing" @@ -149,16 +144,13 @@ jobs: - 'sdk-1.10.15-0-r598' coveralls: [false] fuzzing: [false] - ssl: [false] include: - sdk-path: 'release/linux/x86_64/2.10/' sdk-version: 'sdk-gc64-2.10.8-0-r598.linux.x86_64' coveralls: false - ssl: true - sdk-path: 'release/linux/x86_64/2.11/' sdk-version: 'sdk-gc64-2.11.1-0-r598.linux.x86_64' coveralls: true - ssl: true steps: - name: Clone the connector @@ -195,14 +187,6 @@ jobs: source tarantool-enterprise/env.sh make test make testrace - env: - TEST_TNT_SSL: ${{matrix.ssl}} - - - name: Run regression tests with disabled SSL - run: | - source tarantool-enterprise/env.sh - make test TAGS="go_tarantool_ssl_disable" - make testrace TAGS="go_tarantool_ssl_disable" - name: Run fuzzing tests if: ${{ matrix.fuzzing }} @@ -212,7 +196,6 @@ jobs: if: ${{ matrix.coveralls }} env: COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TEST_TNT_SSL: ${{matrix.ssl}} run: | source tarantool-enterprise/env.sh make coveralls @@ -376,12 +359,6 @@ jobs: make test make testrace - - name: Run regression tests with disabled SSL - run: | - cd "${SRCDIR}" - make test TAGS="go_tarantool_ssl_disable" - make testrace TAGS="go_tarantool_ssl_disable" - - name: Run fuzzing tests if: ${{ matrix.fuzzing }} run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c3b026ec..c71a63146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,6 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release. - IsNullable flag for Field (#302) - More linters on CI (#310) - Meaningful description for read/write socket errors (#129) -- Support password and password file to decrypt private SSL key file (#319) - Support `operation_data` in `crud.Error` (#330) - Support `fetch_latest_metadata` option for crud requests with metadata (#335) - Support `noreturn` option for data change crud requests (#335) @@ -127,6 +126,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release. - Code() method from the Request interface (#158) - `Schema` field from the `Connection` struct (#7) - `OkCode` and `PushCode` constants (#237) +- SSL support (#301) ### Fixed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fdfcc67a2..f3ffe4d96 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,20 +34,6 @@ make testrace The tests set up all required `tarantool` processes before run and clean up afterwards. -If you want to run the tests with specific build tags: -```bash -make test TAGS=go_tarantool_ssl_disable -make testrace TAGS=go_tarantool_ssl_disable -``` - -If you have Tarantool Enterprise Edition 2.10 or newer, you can run additional -SSL tests. To do this, you need to set an environment variable 'TEST_TNT_SSL': - -```bash -TEST_TNT_SSL=true make test -TEST_TNT_SSL=true make testrace -``` - If you want to run the tests for a specific package: ```bash make test- diff --git a/README.md b/README.md index c025cfce8..85ca776a1 100644 --- a/README.md +++ b/README.md @@ -68,11 +68,7 @@ We define multiple [build tags](https://pkg.go.dev/go/build#hdr-Build_Constraint This allows us to introduce new features without losing backward compatibility. -1. To disable SSL support and linking with OpenSSL, you can use the tag: - ``` - go_tarantool_ssl_disable - ``` -2. To run fuzz tests with decimals, you can use the build tag: +1. To run fuzz tests with decimals, you can use the build tag: ``` go_tarantool_decimal_fuzzing ``` @@ -169,6 +165,60 @@ otherwise it will have a description which can be retrieved with `err.Error()`. by the method `Do` of object `conn` which is the object that was returned by `Connect()`. +### Example with encrypting traffic + +For SSL-enabled connections, use `OpenSSLDialer` from the [`go-tlsdialer`](https://github.com/tarantool/go-tlsdialer) +package. + +Here is small example with importing `go-tlsdialer` and using the +`OpenSSLDialer`: + +```go +package tarantool + +import ( + "context" + "fmt" + "time" + + "github.com/tarantool/go-tarantool/v2" + "github.com/tarantool/go-tlsdialer" +) + +func main() { + sslDialer := tlsdialer.OpenSSLDialer{ + Address: "127.0.0.1:3013", + User: "test", + Password: "test", + SslKeyFile: "testdata/localhost.key", + SslCertFile: "testdata/localhost.crt", + SslCaFile: "testdata/ca.crt", + } + opts := tarantool.Opts{ + Timeout: time.Second, + } + + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + conn, err := tarantool.Connect(ctx, sslDialer, opts) + if err != nil { + fmt.Printf("Connection refused: %s", err) + } + + data, err := conn.Do(tarantool.NewInsertRequest(999). + Tuple([]interface{}{99999, "BB"}), + ).Get() + if err != nil { + fmt.Printf("Error: %s", err) + } else { + fmt.Printf("Data: %v", data) + } +} +``` + +Note that [traffic encryption](https://www.tarantool.io/en/doc/latest/enterprise/security/#encrypting-traffic) +is only available in Tarantool Enterprise Edition 2.10 or newer. + ### Migration to v2 The article describes migration from go-tarantool to go-tarantool/v2. @@ -315,8 +365,10 @@ and user may cancel it in process. Now you need to pass `Dialer` as the second argument instead of URI. If you were using a non-SSL connection, you need to create `NetDialer`. -For SSL-enabled connections, use `OpenSslDialer`. Please note that the options -for creating a connection are now stored in corresponding `Dialer`, not in `Opts`. +For SSL-enabled connections, use `OpenSSLDialer` from the `go-tlsdialer` +package. +Please note that the options for creating a connection are now stored in +corresponding `Dialer`, not in `Opts`. #### Connection schema diff --git a/dial.go b/dial.go index c1f319549..ac1919030 100644 --- a/dial.go +++ b/dial.go @@ -205,115 +205,6 @@ func (d NetDialer) Dial(ctx context.Context, opts DialOpts) (Conn, error) { return dialer.Dial(ctx, opts) } -type openSslDialer struct { - address string - sslKeyFile string - sslCertFile string - sslCaFile string - sslCiphers string - sslPassword string - sslPasswordFile string -} - -func (d openSslDialer) Dial(ctx context.Context, opts DialOpts) (Conn, error) { - var err error - conn := new(tntConn) - - network, address := parseAddress(d.address) - conn.net, err = sslDialContext(ctx, network, address, sslOpts{ - KeyFile: d.sslKeyFile, - CertFile: d.sslCertFile, - CaFile: d.sslCaFile, - Ciphers: d.sslCiphers, - Password: d.sslPassword, - PasswordFile: d.sslPasswordFile, - }) - if err != nil { - return nil, fmt.Errorf("failed to dial: %w", err) - } - - dc := &deadlineIO{to: opts.IoTimeout, c: conn.net} - conn.reader = bufio.NewReaderSize(dc, bufSize) - conn.writer = bufio.NewWriterSize(dc, bufSize) - - return conn, nil -} - -// OpenSslDialer allows to use SSL transport for connection. -type OpenSslDialer struct { - // Address is an address to connect. - // It could be specified in following ways: - // - // - TCP connections (tcp://192.168.1.1:3013, tcp://my.host:3013, - // tcp:192.168.1.1:3013, tcp:my.host:3013, 192.168.1.1:3013, my.host:3013) - // - // - Unix socket, first '/' or '.' indicates Unix socket - // (unix:///abs/path/tnt.sock, unix:path/tnt.sock, /abs/path/tnt.sock, - // ./rel/path/tnt.sock, unix/:path/tnt.sock) - Address string - // Auth is an authentication method. - Auth Auth - // Username for logging in to Tarantool. - User string - // User password for logging in to Tarantool. - Password string - // RequiredProtocol contains minimal protocol version and - // list of protocol features that should be supported by - // Tarantool server. By default, there are no restrictions. - RequiredProtocolInfo ProtocolInfo - // SslKeyFile is a path to a private SSL key file. - SslKeyFile string - // SslCertFile is a path to an SSL certificate file. - SslCertFile string - // SslCaFile is a path to a trusted certificate authorities (CA) file. - SslCaFile string - // SslCiphers is a colon-separated (:) list of SSL cipher suites the connection - // can use. - // - // We don't provide a list of supported ciphers. This is what OpenSSL - // does. The only limitation is usage of TLSv1.2 (because other protocol - // versions don't seem to support the GOST cipher). To add additional - // ciphers (GOST cipher), you must configure OpenSSL. - // - // See also - // - // * https://www.openssl.org/docs/man1.1.1/man1/ciphers.html - SslCiphers string - // SslPassword is a password for decrypting the private SSL key file. - // The priority is as follows: try to decrypt with SslPassword, then - // try SslPasswordFile. - SslPassword string - // SslPasswordFile is a path to the list of passwords for decrypting - // the private SSL key file. The connection tries every line from the - // file as a password. - SslPasswordFile string -} - -// Dial makes OpenSslDialer satisfy the Dialer interface. -func (d OpenSslDialer) Dial(ctx context.Context, opts DialOpts) (Conn, error) { - dialer := AuthDialer{ - Dialer: ProtocolDialer{ - Dialer: GreetingDialer{ - Dialer: openSslDialer{ - address: d.Address, - sslKeyFile: d.SslKeyFile, - sslCertFile: d.SslCertFile, - sslCaFile: d.SslCaFile, - sslCiphers: d.SslCiphers, - sslPassword: d.SslPassword, - sslPasswordFile: d.SslPasswordFile, - }, - }, - RequiredProtocolInfo: d.RequiredProtocolInfo, - }, - Auth: d.Auth, - Username: d.User, - Password: d.Password, - } - - return dialer.Dial(ctx, opts) -} - type fdAddr struct { Fd uintptr } diff --git a/dial_test.go b/dial_test.go index b41a504df..abfdf0d4f 100644 --- a/dial_test.go +++ b/dial_test.go @@ -442,7 +442,6 @@ type testDialOpts struct { isErrGreeting bool isErrId bool isIdUnsupported bool - isPapSha256Auth bool isErrAuth bool isEmptyAuth bool } @@ -485,9 +484,7 @@ func testDialAccept(opts testDialOpts, l net.Listener) chan dialServerActual { // Read Auth request. authRequestExpected := authRequestExpectedChapSha1 - if opts.isPapSha256Auth { - authRequestExpected = authRequestExpectedPapSha256 - } else if opts.isEmptyAuth { + if opts.isEmptyAuth { authRequestExpected = []byte{} } authRequestActual := make([]byte, len(authRequestExpected)) @@ -530,9 +527,7 @@ func testDialer(t *testing.T, l net.Listener, dialer tarantool.Dialer, require.Equal(t, idRequestExpected, actual.IdRequest) authRequestExpected := authRequestExpectedChapSha1 - if opts.isPapSha256Auth { - authRequestExpected = authRequestExpectedPapSha256 - } else if opts.isEmptyAuth { + if opts.isEmptyAuth { authRequestExpected = []byte{} } require.Equal(t, authRequestExpected, actual.AuthRequest) @@ -749,11 +744,44 @@ func TestAuthDialer_Dial(t *testing.T) { conn.Close() } - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, conn) assert.Equal(t, authRequestExpectedChapSha1[:41], dialer.conn.writebuf.Bytes()[:41]) } +func TestAuthDialer_Dial_PapSha256Auth(t *testing.T) { + salt := fmt.Sprintf("%s", testDialSalt) + salt = base64.StdEncoding.EncodeToString([]byte(salt)) + dialer := mockIoDialer{ + init: func(conn *mockIoConn) { + conn.greeting.Salt = salt + conn.writeWgDelay = 1 + conn.readWgDelay = 2 + conn.readbuf.Write(okResponse) + }, + } + defer func() { + dialer.conn.writeWg.Done() + }() + + authDialer := tarantool.AuthDialer{ + Dialer: &dialer, + Username: "test", + Password: "test", + Auth: tarantool.PapSha256Auth, + } + ctx, cancel := test_helpers.GetConnectContext() + defer cancel() + conn, err := authDialer.Dial(ctx, tarantool.DialOpts{}) + if conn != nil { + conn.Close() + } + + assert.NoError(t, err) + assert.NotNil(t, conn) + assert.Equal(t, authRequestExpectedPapSha256[:41], dialer.conn.writebuf.Bytes()[:41]) +} + func TestProtocolDialer_Dial_DialerError(t *testing.T) { dialer := tarantool.ProtocolDialer{ Dialer: mockErrorDialer{ @@ -847,7 +875,7 @@ func TestProtocolDialer_Dial(t *testing.T) { conn.Close() } - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, conn) assert.Equal(t, protoInfo, conn.ProtocolInfo()) } @@ -913,7 +941,7 @@ func TestGreetingDialer_Dial(t *testing.T) { conn.Close() } - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, conn) assert.Equal(t, string(testDialVersion[:]), conn.Greeting().Version) assert.Equal(t, string(testDialSalt[:44]), conn.Greeting().Salt) diff --git a/example_test.go b/example_test.go index 965c25a82..ec07b657b 100644 --- a/example_test.go +++ b/example_test.go @@ -31,24 +31,6 @@ func exampleConnect(dialer tarantool.Dialer, opts tarantool.Opts) *tarantool.Con return conn } -// Example demonstrates how to use SSL transport. -func ExampleOpenSslDialer() { - sslDialer := tarantool.OpenSslDialer{ - Address: "127.0.0.1:3013", - User: "test", - Password: "test", - SslKeyFile: "testdata/localhost.key", - SslCertFile: "testdata/localhost.crt", - SslCaFile: "testdata/ca.crt", - } - ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) - defer cancel() - _, err := tarantool.Connect(ctx, sslDialer, opts) - if err != nil { - panic("Connection is not established: " + err.Error()) - } -} - func ExampleIntKey() { conn := exampleConnect(dialer, opts) defer conn.Close() diff --git a/export_test.go b/export_test.go index e92ce9bd9..ab3784b3b 100644 --- a/export_test.go +++ b/export_test.go @@ -6,19 +6,6 @@ import ( "github.com/vmihailenco/msgpack/v5" ) -type SslTestOpts struct { - KeyFile string - CertFile string - CaFile string - Ciphers string - Password string - PasswordFile string -} - -func SslCreateContext(opts SslTestOpts) (ctx interface{}, err error) { - return sslCreateContext(sslOpts(opts)) -} - // RefImplPingBody is reference implementation for filling of a ping // request's body. func RefImplPingBody(enc *msgpack.Encoder) error { diff --git a/go.mod b/go.mod index f1a6af3b0..4f97af1a6 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,8 @@ go 1.11 require ( github.com/google/uuid v1.3.0 - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.7.1 github.com/tarantool/go-iproto v1.0.0 - github.com/tarantool/go-openssl v0.0.8-0.20231004103608-336ca939d2ca github.com/vmihailenco/msgpack/v5 v5.3.5 - golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect ) diff --git a/go.sum b/go.sum index 752c1029c..ff942aa8f 100644 --- a/go.sum +++ b/go.sum @@ -2,36 +2,21 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= -github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tarantool/go-iproto v1.0.0 h1:quC4hdFhCuFYaCqOFgUxH2foRkhAy+TlEy7gQLhdVjw= github.com/tarantool/go-iproto v1.0.0/go.mod h1:LNCtdyZxojUed8SbOiYHoc3v9NvaZTB7p96hUySMlIo= -github.com/tarantool/go-openssl v0.0.8-0.20231004103608-336ca939d2ca h1:oOrBh73tDDyooIXajfr+0pfnM+89404ClAhJpTTHI7E= -github.com/tarantool/go-openssl v0.0.8-0.20231004103608-336ca939d2ca/go.mod h1:M7H4xYSbzqpW/ZRBMyH0eyqQBsnhAMfsYk5mv0yid7A= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ssl.go b/ssl.go deleted file mode 100644 index 39cc57bd0..000000000 --- a/ssl.go +++ /dev/null @@ -1,30 +0,0 @@ -package tarantool - -type sslOpts struct { - // KeyFile is a path to a private SSL key file. - KeyFile string - // CertFile is a path to an SSL certificate file. - CertFile string - // CaFile is a path to a trusted certificate authorities (CA) file. - CaFile string - // Ciphers is a colon-separated (:) list of SSL cipher suites the connection - // can use. - // - // We don't provide a list of supported ciphers. This is what OpenSSL - // does. The only limitation is usage of TLSv1.2 (because other protocol - // versions don't seem to support the GOST cipher). To add additional - // ciphers (GOST cipher), you must configure OpenSSL. - // - // See also - // - // * https://www.openssl.org/docs/man1.1.1/man1/ciphers.html - Ciphers string - // Password is a password for decrypting the private SSL key file. - // The priority is as follows: try to decrypt with Password, then - // try PasswordFile. - Password string - // PasswordFile is a path to the list of passwords for decrypting - // the private SSL key file. The connection tries every line from the - // file as a password. - PasswordFile string -} diff --git a/ssl_disable.go b/ssl_disable.go deleted file mode 100644 index 21550b61a..000000000 --- a/ssl_disable.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build go_tarantool_ssl_disable -// +build go_tarantool_ssl_disable - -package tarantool - -import ( - "context" - "errors" - "net" -) - -func sslDialContext(ctx context.Context, network, address string, - opts sslOpts) (connection net.Conn, err error) { - return nil, errors.New("SSL support is disabled.") -} - -func sslCreateContext(opts sslOpts) (ctx interface{}, err error) { - return nil, errors.New("SSL support is disabled.") -} diff --git a/ssl_enable.go b/ssl_enable.go deleted file mode 100644 index a56dac1cc..000000000 --- a/ssl_enable.go +++ /dev/null @@ -1,144 +0,0 @@ -//go:build !go_tarantool_ssl_disable -// +build !go_tarantool_ssl_disable - -package tarantool - -import ( - "bufio" - "context" - "errors" - "io/ioutil" - "net" - "os" - "strings" - - "github.com/tarantool/go-openssl" -) - -func sslDialContext(ctx context.Context, network, address string, - opts sslOpts) (connection net.Conn, err error) { - var sslCtx interface{} - if sslCtx, err = sslCreateContext(opts); err != nil { - return - } - - return openssl.DialContext(ctx, network, address, sslCtx.(*openssl.Ctx), 0) -} - -// interface{} is a hack. It helps to avoid dependency of go-openssl in build -// of tests with the tag 'go_tarantool_ssl_disable'. -func sslCreateContext(opts sslOpts) (ctx interface{}, err error) { - var sslCtx *openssl.Ctx - - // Require TLSv1.2, because other protocol versions don't seem to - // support the GOST cipher. - if sslCtx, err = openssl.NewCtxWithVersion(openssl.TLSv1_2); err != nil { - return - } - ctx = sslCtx - sslCtx.SetMaxProtoVersion(openssl.TLS1_2_VERSION) - sslCtx.SetMinProtoVersion(openssl.TLS1_2_VERSION) - - if opts.CertFile != "" { - if err = sslLoadCert(sslCtx, opts.CertFile); err != nil { - return - } - } - - if opts.KeyFile != "" { - if err = sslLoadKey(sslCtx, opts.KeyFile, opts.Password, opts.PasswordFile); err != nil { - return - } - } - - if opts.CaFile != "" { - if err = sslCtx.LoadVerifyLocations(opts.CaFile, ""); err != nil { - return - } - verifyFlags := openssl.VerifyPeer | openssl.VerifyFailIfNoPeerCert - sslCtx.SetVerify(verifyFlags, nil) - } - - if opts.Ciphers != "" { - sslCtx.SetCipherList(opts.Ciphers) - } - - return -} - -func sslLoadCert(ctx *openssl.Ctx, certFile string) (err error) { - var certBytes []byte - if certBytes, err = ioutil.ReadFile(certFile); err != nil { - return - } - - certs := openssl.SplitPEM(certBytes) - if len(certs) == 0 { - err = errors.New("No PEM certificate found in " + certFile) - return - } - first, certs := certs[0], certs[1:] - - var cert *openssl.Certificate - if cert, err = openssl.LoadCertificateFromPEM(first); err != nil { - return - } - if err = ctx.UseCertificate(cert); err != nil { - return - } - - for _, pem := range certs { - if cert, err = openssl.LoadCertificateFromPEM(pem); err != nil { - break - } - if err = ctx.AddChainCertificate(cert); err != nil { - break - } - } - return -} - -func sslLoadKey(ctx *openssl.Ctx, keyFile string, password string, - passwordFile string) error { - var keyBytes []byte - var err, firstDecryptErr error - - if keyBytes, err = ioutil.ReadFile(keyFile); err != nil { - return err - } - - // If the key is encrypted and password is not provided, - // openssl.LoadPrivateKeyFromPEM(keyBytes) asks to enter PEM pass phrase - // interactively. On the other hand, - // openssl.LoadPrivateKeyFromPEMWithPassword(keyBytes, password) works fine - // for non-encrypted key with any password, including empty string. If - // the key is encrypted, we fast fail with password error instead of - // requesting the pass phrase interactively. - passwords := []string{password} - if passwordFile != "" { - file, err := os.Open(passwordFile) - if err == nil { - defer file.Close() - - scanner := bufio.NewScanner(file) - // Tarantool itself tries each password file line. - for scanner.Scan() { - password = strings.TrimSpace(scanner.Text()) - passwords = append(passwords, password) - } - } else { - firstDecryptErr = err - } - } - - for _, password := range passwords { - key, err := openssl.LoadPrivateKeyFromPEMWithPassword(keyBytes, password) - if err == nil { - return ctx.UsePrivateKey(key) - } else if firstDecryptErr == nil { - firstDecryptErr = err - } - } - - return firstDecryptErr -} diff --git a/ssl_test.go b/ssl_test.go deleted file mode 100644 index f161b98f0..000000000 --- a/ssl_test.go +++ /dev/null @@ -1,780 +0,0 @@ -//go:build !go_tarantool_ssl_disable -// +build !go_tarantool_ssl_disable - -package tarantool_test - -import ( - "context" - "fmt" - "net" - "os" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/tarantool/go-iproto" - "github.com/tarantool/go-openssl" - - . "github.com/tarantool/go-tarantool/v2" - "github.com/tarantool/go-tarantool/v2/test_helpers" -) - -const tntHost = "127.0.0.1:3014" - -func serverTnt(serverOpts SslTestOpts, auth Auth) (test_helpers.TarantoolInstance, error) { - listen := tntHost + "?transport=ssl&" - - key := serverOpts.KeyFile - if key != "" { - listen += fmt.Sprintf("ssl_key_file=%s&", key) - } - - cert := serverOpts.CertFile - if cert != "" { - listen += fmt.Sprintf("ssl_cert_file=%s&", cert) - } - - ca := serverOpts.CaFile - if ca != "" { - listen += fmt.Sprintf("ssl_ca_file=%s&", ca) - } - - ciphers := serverOpts.Ciphers - if ciphers != "" { - listen += fmt.Sprintf("ssl_ciphers=%s&", ciphers) - } - - password := serverOpts.Password - if password != "" { - listen += fmt.Sprintf("ssl_password=%s&", password) - } - - passwordFile := serverOpts.PasswordFile - if passwordFile != "" { - listen += fmt.Sprintf("ssl_password_file=%s&", passwordFile) - } - - listen = listen[:len(listen)-1] - - return test_helpers.StartTarantool( - test_helpers.StartOpts{ - Dialer: OpenSslDialer{ - Address: tntHost, - Auth: auth, - User: "test", - Password: "test", - SslKeyFile: serverOpts.KeyFile, - SslCertFile: serverOpts.CertFile, - SslCaFile: serverOpts.CaFile, - SslCiphers: serverOpts.Ciphers, - SslPassword: serverOpts.Password, - SslPasswordFile: serverOpts.PasswordFile, - }, - Auth: auth, - InitScript: "config.lua", - Listen: listen, - SslCertsDir: "testdata", - WaitStart: 100 * time.Millisecond, - ConnectRetry: 10, - RetryTimeout: 500 * time.Millisecond, - }, - ) -} - -func serverTntStop(inst test_helpers.TarantoolInstance) { - test_helpers.StopTarantoolWithCleanup(inst) -} - -func checkTntConn(dialer Dialer) error { - ctx, cancel := test_helpers.GetConnectContext() - defer cancel() - conn, err := Connect(ctx, dialer, Opts{ - Timeout: 500 * time.Millisecond, - SkipSchema: true, - }) - if err != nil { - return err - } - conn.Close() - return nil -} - -func assertConnectionTntFail(t testing.TB, serverOpts SslTestOpts, dialer OpenSslDialer) { - t.Helper() - - inst, err := serverTnt(serverOpts, AutoAuth) - defer serverTntStop(inst) - if err != nil { - t.Fatalf("An unexpected server error %q", err.Error()) - } - - err = checkTntConn(dialer) - if err == nil { - t.Errorf("An unexpected connection to the server") - } -} - -func assertConnectionTntOk(t testing.TB, serverOpts SslTestOpts, dialer OpenSslDialer) { - t.Helper() - - inst, err := serverTnt(serverOpts, AutoAuth) - defer serverTntStop(inst) - if err != nil { - t.Fatalf("An unexpected server error %q", err.Error()) - } - - err = checkTntConn(dialer) - if err != nil { - t.Errorf("An unexpected connection error %q", err.Error()) - } -} - -type sslTest struct { - name string - ok bool - serverOpts SslTestOpts - clientOpts SslTestOpts -} - -/* -Requirements from Tarantool Enterprise Edition manual: -https://www.tarantool.io/ru/enterprise_doc/security/#configuration - -For a server: -KeyFile - mandatory -CertFile - mandatory -CaFile - optional -Ciphers - optional - -For a client: -KeyFile - optional, mandatory if server.CaFile set -CertFile - optional, mandatory if server.CaFile set -CaFile - optional, -Ciphers - optional -*/ -var sslTests = []sslTest{ - { - "key_crt_server", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }, - SslTestOpts{}, - }, - { - "key_crt_server_and_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }, - }, - { - "key_crt_ca_server", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{}, - }, - { - "key_crt_ca_server_key_crt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }, - }, - { - "key_crt_ca_server_and_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - }, - { - "key_crt_ca_server_and_client_invalid_path_key", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "any_invalid_path", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - }, - { - "key_crt_ca_server_and_client_invalid_path_crt", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "any_invalid_path", - CaFile: "testdata/ca.crt", - }, - }, - { - "key_crt_ca_server_and_client_invalid_path_ca", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "any_invalid_path", - }, - }, - { - "key_crt_ca_server_and_client_empty_key", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/empty", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - }, - { - "key_crt_ca_server_and_client_empty_crt", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/empty", - CaFile: "testdata/ca.crt", - }, - }, - { - "key_crt_ca_server_and_client_empty_ca", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/empty", - }, - }, - { - "key_crt_server_and_key_crt_ca_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - }, - { - "key_crt_ca_ciphers_server_key_crt_ca_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - }, - { - "key_crt_ca_ciphers_server_and_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - }, - }, - { - "non_equal_ciphers_client", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "TLS_AES_128_GCM_SHA256", - }, - }, - { - "pass_key_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", - }, - }, - { - "passfile_key_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - PasswordFile: "testdata/passwords", - }, - }, - { - "pass_and_passfile_key_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", - PasswordFile: "testdata/passwords", - }, - }, - { - "inv_pass_and_passfile_key_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "invalidpassword", - PasswordFile: "testdata/passwords", - }, - }, - { - "pass_and_inv_passfile_key_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", - PasswordFile: "testdata/invalidpasswords", - }, - }, - { - "pass_and_not_existing_passfile_key_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "mysslpassword", - PasswordFile: "testdata/notafile", - }, - }, - { - "inv_pass_and_inv_passfile_key_encrypt_client", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - Password: "invalidpassword", - PasswordFile: "testdata/invalidpasswords", - }, - }, - { - "not_existing_passfile_key_encrypt_client", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - PasswordFile: "testdata/notafile", - }, - }, - { - "no_pass_key_encrypt_client", - false, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.enc.key", - CertFile: "testdata/localhost.crt", - }, - }, - { - "pass_key_non_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - Password: "invalidpassword", - }, - }, - { - "passfile_key_non_encrypt_client", - true, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - }, - SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - PasswordFile: "testdata/invalidpasswords", - }, - }, -} - -func isTestTntSsl() bool { - testTntSsl, exists := os.LookupEnv("TEST_TNT_SSL") - return exists && - (testTntSsl == "1" || strings.ToUpper(testTntSsl) == "TRUE") -} - -func makeOpenSslDialer(opts SslTestOpts) OpenSslDialer { - return OpenSslDialer{ - Address: tntHost, - User: "test", - Password: "test", - SslKeyFile: opts.KeyFile, - SslCertFile: opts.CertFile, - SslCaFile: opts.CaFile, - SslCiphers: opts.Ciphers, - SslPassword: opts.Password, - SslPasswordFile: opts.PasswordFile, - } -} - -func TestSslOpts(t *testing.T) { - isTntSsl := isTestTntSsl() - - for _, test := range sslTests { - if !isTntSsl { - continue - } - dialer := makeOpenSslDialer(test.clientOpts) - if test.ok { - t.Run("ok_tnt_"+test.name, func(t *testing.T) { - assertConnectionTntOk(t, test.serverOpts, dialer) - }) - } else { - t.Run("fail_tnt_"+test.name, func(t *testing.T) { - assertConnectionTntFail(t, test.serverOpts, dialer) - }) - } - } -} - -func TestOpts_PapSha256Auth(t *testing.T) { - isTntSsl := isTestTntSsl() - if !isTntSsl { - t.Skip("TEST_TNT_SSL is not set") - } - - isLess, err := test_helpers.IsTarantoolVersionLess(2, 11, 0) - if err != nil { - t.Fatalf("Could not check Tarantool version: %s", err) - } - if isLess { - t.Skip("Skipping test for Tarantool without pap-sha256 support") - } - - sslOpts := SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - } - - inst, err := serverTnt(sslOpts, PapSha256Auth) - defer serverTntStop(inst) - if err != nil { - t.Fatalf("An unexpected server error %q", err.Error()) - } - - client := OpenSslDialer{ - Address: tntHost, - Auth: PapSha256Auth, - User: "test", - Password: "test", - RequiredProtocolInfo: ProtocolInfo{}, - SslKeyFile: sslOpts.KeyFile, - SslCertFile: sslOpts.CertFile, - } - - conn := test_helpers.ConnectWithValidation(t, client, opts) - conn.Close() - - client.Auth = AutoAuth - conn = test_helpers.ConnectWithValidation(t, client, opts) - conn.Close() -} - -func createSslListener(t *testing.T, opts SslTestOpts) net.Listener { - ctx, err := SslCreateContext(opts) - require.NoError(t, err) - l, err := openssl.Listen("tcp", "127.0.0.1:0", ctx.(*openssl.Ctx)) - require.NoError(t, err) - return l -} - -func TestOpenSslDialer_Dial_opts(t *testing.T) { - for _, test := range sslTests { - t.Run(test.name, func(t *testing.T) { - l := createSslListener(t, test.serverOpts) - defer l.Close() - addr := l.Addr().String() - - dialer := OpenSslDialer{ - Address: addr, - User: testDialUser, - Password: testDialPass, - SslKeyFile: test.clientOpts.KeyFile, - SslCertFile: test.clientOpts.CertFile, - SslCaFile: test.clientOpts.CaFile, - SslCiphers: test.clientOpts.Ciphers, - SslPassword: test.clientOpts.Password, - SslPasswordFile: test.clientOpts.PasswordFile, - } - testDialer(t, l, dialer, testDialOpts{ - wantErr: !test.ok, - expectedProtocolInfo: idResponseTyped.Clone(), - }) - }) - } -} - -func TestOpenSslDialer_Dial_basic(t *testing.T) { - l := createSslListener(t, SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }) - - defer l.Close() - addr := l.Addr().String() - - dialer := OpenSslDialer{ - Address: addr, - User: testDialUser, - Password: testDialPass, - } - - cases := []testDialOpts{ - { - name: "all is ok", - expectedProtocolInfo: idResponseTyped.Clone(), - }, - { - name: "id request unsupported", - expectedProtocolInfo: ProtocolInfo{}, - isIdUnsupported: true, - }, - { - name: "greeting response error", - wantErr: true, - expectedErr: "failed to read greeting", - isErrGreeting: true, - }, - { - name: "id response error", - wantErr: true, - expectedErr: "failed to identify", - isErrId: true, - }, - { - name: "auth response error", - wantErr: true, - expectedErr: "failed to authenticate", - isErrAuth: true, - }, - } - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - testDialer(t, l, dialer, tc) - }) - } -} - -func TestOpenSslDialer_Dial_requirements(t *testing.T) { - l := createSslListener(t, SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }) - - defer l.Close() - addr := l.Addr().String() - - dialer := OpenSslDialer{ - Address: addr, - User: testDialUser, - Password: testDialPass, - RequiredProtocolInfo: ProtocolInfo{ - Features: []iproto.Feature{42}, - }, - } - - testDialAccept(testDialOpts{}, l) - ctx, cancel := test_helpers.GetConnectContext() - defer cancel() - conn, err := dialer.Dial(ctx, DialOpts{}) - if err == nil { - conn.Close() - } - require.Error(t, err) - require.Contains(t, err.Error(), "invalid server protocol") -} - -func TestOpenSslDialer_Dial_papSha256Auth(t *testing.T) { - l := createSslListener(t, SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - }) - - defer l.Close() - addr := l.Addr().String() - - dialer := OpenSslDialer{ - Address: addr, - User: testDialUser, - Password: testDialPass, - Auth: PapSha256Auth, - } - - // Response from the server. - protocol := idResponseTyped.Clone() - protocol.Auth = ChapSha1Auth - - testDialer(t, l, dialer, testDialOpts{ - expectedProtocolInfo: protocol, - isPapSha256Auth: true, - }) -} - -func TestOpenSslDialer_Dial_ctx_cancel(t *testing.T) { - serverOpts := SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - } - clientOpts := SslTestOpts{ - KeyFile: "testdata/localhost.key", - CertFile: "testdata/localhost.crt", - CaFile: "testdata/ca.crt", - Ciphers: "ECDHE-RSA-AES256-GCM-SHA384", - } - - l := createSslListener(t, serverOpts) - defer l.Close() - addr := l.Addr().String() - testDialAccept(testDialOpts{}, l) - - dialer := OpenSslDialer{ - Address: addr, - User: testDialUser, - Password: testDialPass, - SslKeyFile: clientOpts.KeyFile, - SslCertFile: clientOpts.CertFile, - SslCaFile: clientOpts.CaFile, - SslCiphers: clientOpts.Ciphers, - SslPassword: clientOpts.Password, - SslPasswordFile: clientOpts.PasswordFile, - } - - ctx, cancel := context.WithCancel(context.Background()) - cancel() - conn, err := dialer.Dial(ctx, DialOpts{}) - if err == nil { - conn.Close() - } - require.Error(t, err) -} diff --git a/tarantool_test.go b/tarantool_test.go index c4db04cb3..0bd3f394b 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -790,6 +790,26 @@ func TestNetDialer_BadUser(t *testing.T) { } } +// NetDialer does not work with PapSha256Auth, no matter the Tarantool version +// and edition. +func TestNetDialer_PapSha256Auth(t *testing.T) { + authDialer := AuthDialer{ + Dialer: dialer, + Username: "test", + Password: "test", + Auth: PapSha256Auth, + } + ctx, cancel := test_helpers.GetConnectContext() + defer cancel() + conn, err := authDialer.Dial(ctx, DialOpts{}) + if conn != nil { + conn.Close() + t.Fatalf("Connection created successfully") + } + + assert.ErrorContains(t, err, "failed to authenticate") +} + func TestFutureMultipleGetGetTyped(t *testing.T) { conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() diff --git a/testdata/ca.crt b/testdata/ca.crt deleted file mode 100644 index 2fa1a12ff..000000000 --- a/testdata/ca.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDLzCCAhegAwIBAgIUMMZTmNkhr4qOfSwInVk2dAJvoBEwDQYJKoZIhvcNAQEL -BQAwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD0V4YW1wbGUtUm9vdC1DQTAeFw0y -MjA1MjYwNjE3NDBaFw00NDEwMjkwNjE3NDBaMCcxCzAJBgNVBAYTAlVTMRgwFgYD -VQQDDA9FeGFtcGxlLVJvb3QtQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQCRq/eaA3I6CB8t770H2XDdzcp1yuC/+TZOxV5o0LuRkogTvL2kYULBrfx1 -rVZu8zQJTx1fmSRj1cN8j+IrmXN5goZ3mYFTnnIOgkyi+hJysVlo5s0Kp0qtLLGM -OuaVbxw2oAy75if5X3pFpiDaMvFBtJKsh8+SkncBIC5bbKC5AoLdFANLmPiH0CGr -Mv3rL3ycnbciI6J4uKHcWnYGGiMjBomaZ7jd/cOjcjmGfpI5d0nq13G11omkyEyR -wNX0eJRL02W+93Xu7tD+FEFMxFvak+70GvX+XWomwYw/Pjlio8KbTAlJxhfK2Lh6 -H798k17VfxIrOk0KjzZS7+a20hZ/AgMBAAGjUzBRMB0GA1UdDgQWBBT2f5o8r75C -PWST36akpkKRRTbhvjAfBgNVHSMEGDAWgBT2f5o8r75CPWST36akpkKRRTbhvjAP -BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA9pb75p6mnqp2MQHSr -5SKRf2UV4wQIUtXgF6V9vNfvVzJii+Lzrqir1YMk5QgavCzD96KlJcqJCcH559RY -5743AxI3tdWfA3wajBctoy35oYnT4M30qbkryYLTUlv7PmeNWvrksTURchyyDt5/ -3T73yj5ZalmzKN6+xLfUDdnudspfWlUMutKU50MU1iuQESf4Fwd53vOg9jMcWJ2E -vAgfVI0XAvYdU3ybJrUvBq5zokYR2RzGv14uHxwVPnLBjrBEHRnbrXvLZJhuIS2b -xZ3CqwWi+9bvNqHz09HvhkU2b6fCGweKaAUGSo8OfQ5FRkjTUomMI/ZLs/qtJ6JR -zzVt ------END CERTIFICATE----- diff --git a/testdata/empty b/testdata/empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/testdata/generate.sh b/testdata/generate.sh deleted file mode 100755 index 4b8cf3630..000000000 --- a/testdata/generate.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash -set -xeuo pipefail -# An example how-to re-generate testing certificates (because usually -# TLS certificates have expiration dates and some day they will expire). -# -# The instruction is valid for: -# -# $ openssl version -# OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022) - -cat < domains.ext -authorityKeyIdentifier=keyid,issuer -basicConstraints=CA:FALSE -keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment -subjectAltName = @alt_names -[alt_names] -DNS.1 = localhost -IP.1 = 127.0.0.1 -EOF - -openssl req -x509 -nodes -new -sha256 -days 8192 -newkey rsa:2048 -keyout ca.key -out ca.pem -subj "/C=US/CN=Example-Root-CA" -openssl x509 -outform pem -in ca.pem -out ca.crt - -openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost" -openssl x509 -req -sha256 -days 8192 -in localhost.csr -CA ca.pem -CAkey ca.key -CAcreateserial -extfile domains.ext -out localhost.crt -password=mysslpassword - -# Tarantool tries every line from the password file. -cat < passwords -unusedpassword -$password -EOF - -cat < invalidpasswords -unusedpassword1 -EOF - -openssl rsa -aes256 -passout "pass:${password}" -in localhost.key -out localhost.enc.key diff --git a/testdata/invalidpasswords b/testdata/invalidpasswords deleted file mode 100644 index b09d795aa..000000000 --- a/testdata/invalidpasswords +++ /dev/null @@ -1 +0,0 @@ -unusedpassword1 diff --git a/testdata/localhost.crt b/testdata/localhost.crt deleted file mode 100644 index fd04b9900..000000000 --- a/testdata/localhost.crt +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIUAvSBJ3nSv7kdKw1IQ7AjchzI7T8wDQYJKoZIhvcNAQEL -BQAwJzELMAkGA1UEBhMCVVMxGDAWBgNVBAMMD0V4YW1wbGUtUm9vdC1DQTAeFw0y -MjA1MjYwNjE3NDBaFw00NDEwMjkwNjE3NDBaMGcxCzAJBgNVBAYTAlVTMRIwEAYD -VQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MR0wGwYDVQQKDBRFeGFt -cGxlLUNlcnRpZmljYXRlczESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnbFY+BMqlddktbitgaZICws4Zyj8LFy9QzO+ -AYSQyqFuTCI+cGqbP5r6Qf4f3xHNGykHJGn18brpiFWhNMaVkkgU3dycU8fFayVN -hLEJAXd4acWP1h5/aH4cOZgl+xJlmU2iLHtP/TLYEDDiVkfqL/MgUIMxbndIaiU0 -/e81v+2gi8ydyI6aElN8KbAaFPzXCZ28/RmO/0m36YzF+FSMVD1Hx8xO5V+Q9N1q -dsyrMdh0nCxDDXGdBgDrKt5+U1uJkDpTHfjMAkf7oBoRd8DJ8O74bpue03W5WxKQ -NjNfvHSgkBaQSdnxR93FSCr/Gs6WcUd50Y8z+ZCTNkup0KROTwIDAQABo3YwdDAf -BgNVHSMEGDAWgBT2f5o8r75CPWST36akpkKRRTbhvjAJBgNVHRMEAjAAMAsGA1Ud -DwQEAwIE8DAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwHQYDVR0OBBYEFOwH -aHK6QrEfltP7wwldUWrQJ9viMA0GCSqGSIb3DQEBCwUAA4IBAQAGHGuloGJqLoPZ -2iRnb/NaiArowLnUz4Z3ENKMB2KbZFGijMJSXO9i9ZLCFL+O93vCTspKGtHqVX2o -dxcrF7EZ9EaHIijWjKGEp1PszunBIca+Te+zyRg9Z+F9gwRsJYB8ctBGjIhe4qEv -ZSlRY489UVNKLTcHcl6nlUled9hciBJHpXuitiiNhzUareP38hROyiUhrAy8L21L -t7Ww5YGRuSTxM5LQfPZcCy40++TlyvXs0DCQ8ZuUbqZv64bNHbaLOyxIqKfPypXa -nS3AYZzUJjHj7vZwHoL1SyvBjx/DQAsWaEv137d8FlMqCsWLXfCsuNpKeQYZOyDS -7ploP9Gl ------END CERTIFICATE----- diff --git a/testdata/localhost.enc.key b/testdata/localhost.enc.key deleted file mode 100644 index b881820a3..000000000 --- a/testdata/localhost.enc.key +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIm+0WC9xe38cCAggA -MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBBNOE4KD+yauMfsnOiNAaaZBIIE -0DtXaHGpacJ8MjjL6zciYhgJOD9SJHE4vwPxpNDWuS9mf6wk/cdBNFMqnYwJmlYw -J/eQ+Z8MsZUqjnhDQz9YXXd8JftexAAa1bHnmfv2N/czJCx57dAHVdmJzgibfp18 -GCpqR23tklEO2Nj2HCbR59rh7IsnW9mD6jh+mVtkOix5HMCUSxwc3bEUutIQE80P -JHG2BsEfAeeHZa+QgG3Y15c6uSXD6wY73ldPPOgZ3NFOqcw/RDqYf1zsohx7auxi -Y6zHA7LdYtQjbNJ5slIfxPhAh75Fws0g4QvWbAwqqdEOVmlamYYjAOdVBBxTvcRs -/63ZN55VTQ8rYhShNA3BVFOLHaRD4mnlKE5Xh7gJXltCED7EHdpHdT9K3uM9U7nW -b2JSylt2RzY+LDsio2U0xsQp9jHzRRw81p8P1jmo5alP8jPACMsE8nnNNSDF4p43 -fG7hNNBq/dhq80iOnaArY05TIBMsD079tB0VKrYyyfaL0RbsAdgtCEmF9bCpnsTM -y9ExcJGQQJx9WNAHkSyjdzJd0jR6Zc0MrgRuj26nJ3Ahq58zaQKdfFO9RfGWd38n -MH3jshEtAuF+jXFbMcM4rVdIBPSuhYgHzYIC6yteziy7+6hittpWeNGLKpC5oZ8R -oEwH3MVsjCbd6Pp3vdcR412vLMgy1ZUOraDoY08FXC82RBJViVX6LLltIJu96kiX -WWUcRZAwzlJsTvh1EGmDcNNKCgmvWQaojqTNgTjxjJ3SzD2/TV6uQrSLgZ6ulyNl -7vKWt/YMTvIgoJA9JeH8Aik/XNd4bRXL+VXfUHpLTgn+WKiq2irVYd9R/yITDunP -a/kzqxitjU4OGdf/LOtYxfxfoGvFw5ym4KikoHKVg4ILcIQ+W4roOQQlu4/yezAK -fwYCrMVJWq4ESuQh3rn7eFR+eyBV6YcNBLm4iUcQTMhnXMMYxQ3TnDNga5eYhmV1 -ByYx+nFQDrbDolXo5JfXs3x6kXhoT/7wMHgsXtmRSd5PSBbaeJTrbMGA0Op6YgWr -EpvX3Yt863s4h+JgDpg9ouH+OJGgn7LGGye+TjjuDds8CStFdcFDDOayBS3EH4Cr -jgJwzvTdTZl+1YLYJXB67M4zmVPRRs5H88+fZYYA9bhZACL/rQBj2wDq/sIxvrIM -SCjOhSJ4z5Sm3XaBKnRG2GBBt67MeHB0+T3HR3VHKR+zStbCnsbOLythsE/CIA8L -fBNXMvnWa5bLgaCaEcK6Q3LOamJiKaigbmhI+3U3NUdb9cT1GhE0rtx6/IO9eapz -IUDOrtX9U+1o6iW2dahezxwLo9ftRwQ7qwG4qOk/Co/1c2WuuQ+d4YPpj/JOO5mf -LanA35mQjQrr2MZII91psznx05ffb5xMp2pqNbC6DVuZq8ZlhvVHGk+wM9RK3kYP -/ITwpbUvLmmN892kvZgLAXadSupBV8R/L5ZjDUO9U2all9p4eGfWZBk/yiivOLmh -VQxKCqAmThTO1hRa56+AjgzRJO6cY85ra+4Mm3FhhdR4gYvap2QTq0o2Vn0WlCHh -1SIeaDKfw9v4aGBbhqyQU2mPlXO5JiLktO+lZ5styVq9Qm+b0ROZxHzL1lRUNbRA -VfQO4fRnINKPgyzgH3tNxJTzw4pLkrkBD/g+zxDZVqkx ------END ENCRYPTED PRIVATE KEY----- diff --git a/testdata/localhost.key b/testdata/localhost.key deleted file mode 100644 index ed0f55876..000000000 --- a/testdata/localhost.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCdsVj4EyqV12S1 -uK2BpkgLCzhnKPwsXL1DM74BhJDKoW5MIj5waps/mvpB/h/fEc0bKQckafXxuumI -VaE0xpWSSBTd3JxTx8VrJU2EsQkBd3hpxY/WHn9ofhw5mCX7EmWZTaIse0/9MtgQ -MOJWR+ov8yBQgzFud0hqJTT97zW/7aCLzJ3IjpoSU3wpsBoU/NcJnbz9GY7/Sbfp -jMX4VIxUPUfHzE7lX5D03Wp2zKsx2HScLEMNcZ0GAOsq3n5TW4mQOlMd+MwCR/ug -GhF3wMnw7vhum57TdblbEpA2M1+8dKCQFpBJ2fFH3cVIKv8azpZxR3nRjzP5kJM2 -S6nQpE5PAgMBAAECggEAFv81l9wHsll6pOu9VfJ/gCjPPXAjMn8F1OaXV5ZTHVHk -iXLXA0LwyBpcU8JxOHFapZLaqUtQpEObahf+zfkF+BLOBDr3i1pPZpxGjUraIt4e -7+HxY4sIDp+Rky6mn1JkAbLqKy2CkUzYaKgQYf/T3dFJjaRMUa1QoLYzX7MCdi5B -GnBICzi2UVsn3HU934l/gJKV+SlprdbrGJ+fRklP2AxLey3EOrwooUViy+k3+w5E -dzBH2HpLL0XuIHaBXQ01J6Mu3ud9ApFLC+Rh+2UFTW/WPnNe+B6BO5CGNN52Pfdr -Q5l+VzmRkXXo2fio+w4z/az8axT/DdhKGT2oBlp35QKBgQDZVGdKjkalH3QH2pdy -CWJIiybzY1R0CpimfgDLIdqEsps9qqgLXsUFB5yTcCRmg8RSWWHvhMVMyJtBcsdY -xGhmHxsFBxuray60UljxBcRQTwqvAX7mP8WEv8t80kbhyaxvOfkg8JD1n2hS7NjL -dOIG9Mh8L0YSOCRkbfv90OnYXQKBgQC5wGs35Ksnqi2swX5MLYfcBaImzoNde86n -cXJ0yyF82O1pk8DkmU2EDcUoQfkKxr3ANvVDG4vYaguIhYsJqPg/t8XQt/epDz/O -WZhqogn0ysaTv2FHrWcgPAkq82hpNII5NfPP8aRaYh8OUSfh4WHkW84m6+usqwjI -wbOq36qmmwKBgGMFFdreYEmzvwYlDoOiyukKncCfLUeB3HNfTbU/w3RafGjobJBh -qZrVEP4MRkl/F9/9YaXj9JE7haGYTkOfmYGOAp2T04OS3kDClEucuQluOgvqvorh -23jUej5xAGK3pJ046M2dTi7bZokB6PUqWCGbPg127JI4ijxH8FyA50rxAoGAQO2d -jMAFg6vco1JPT1lq7+GYOHBfQsIQDj99fo2yeu1or0rSVhWwHsShcdz9rGKj2Rhc -ysRKMa9/sIzdeNbzT3JxVu+3RgTqjLqMqFlTmZl3qBVxb5iRP5c8rSLAEGYmTtEp -FDqm9GDv8hU0F6SsjyH4AWrdylFOlL4Ai237PJkCgYBDC1wAwBD8WXJqRrYVGj7X -l4TQQ0hO7La/zgbasSgLNaJcYu32nut6D0O8IlmcQ2nO0BGPjQmJFGp6xawjViRu -np7fEkJQEf1pK0yeA8A3urjXccuUXEA9kKeqaSZYDzICPFaOlezPPPpW0hbkhnPe -dQn3DcoY6e6o0K5ltt1RvQ== ------END PRIVATE KEY----- diff --git a/testdata/passwords b/testdata/passwords deleted file mode 100644 index 58530047f..000000000 --- a/testdata/passwords +++ /dev/null @@ -1,2 +0,0 @@ -unusedpassword -mysslpassword