Skip to content

Commit 0733e7c

Browse files
committed
tt: move ssl logic from go-tarantool
To disable SSL by default we want to transfer OpenSslDialer and any other ssl logic to the go-openssl repository. Moved all ssl code from go-tarantool, some test helpers. Added dependency to go-tarantool. Part of tarantool/go-tarantool#301
1 parent 336ca93 commit 0733e7c

20 files changed

+1658
-0
lines changed

.github/workflows/go-test.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,20 @@ jobs:
99
strategy:
1010
fail-fast: false
1111
matrix:
12+
sdk-path:
13+
- 'release/linux/x86_64/1.10/'
14+
sdk-version:
15+
- 'sdk-1.10.15-0-r598'
1216
os: [ "ubuntu", "macos" ]
1317
go: [ "1.18.x", "1.19.x" ]
18+
tnt_ssl: [false]
19+
include:
20+
- sdk-path: 'release/linux/x86_64/2.10/'
21+
sdk-version: 'sdk-gc64-2.10.8-0-r598.linux.x86_64'
22+
tnt_ssl: true
23+
- sdk-path: 'release/linux/x86_64/2.11/'
24+
sdk-version: 'sdk-gc64-2.11.1-0-r598.linux.x86_64'
25+
tnt_ssl: true
1426
env:
1527
COVERAGES: ""
1628
runs-on: ${{ format('{0}-latest', matrix.os) }}
@@ -22,6 +34,16 @@ jobs:
2234
- uses: actions/setup-go@v3
2335
with:
2436
go-version: ${{ matrix.go }}
37+
- name: Setup Tarantool ${{ matrix.sdk-version }}
38+
if: ${{ matrix.os == 'ubuntu' }}
39+
run: |
40+
ARCHIVE_NAME=tarantool-enterprise-${{ matrix.sdk-version }}.tar.gz
41+
curl -O -L https://${{ secrets.SDK_DOWNLOAD_TOKEN }}@download.tarantool.io/enterprise/${{ matrix.sdk-path }}${ARCHIVE_NAME}
42+
tar -xzf ${ARCHIVE_NAME}
43+
rm -f ${ARCHIVE_NAME}
44+
- name: Setup Tarantool for macos
45+
if: ${{ matrix.os == 'macos' }}
46+
run: brew install tarantool
2547
- name: Go information
2648
run: |
2749
go version
@@ -31,6 +53,8 @@ jobs:
3153
if: hashFiles('./.github/actions/go-test-setup') != ''
3254
- name: Run tests
3355
uses: protocol/[email protected]
56+
env:
57+
TEST_TNT_SSL: ${{ matrix.tnt_ssl }}
3458
with:
3559
# Use -coverpkg=./..., so that we include cross-package coverage.
3660
# If package ./A imports ./B, and ./A's tests also cover ./B,

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ module github.com/tarantool/go-openssl
33
require (
44
github.com/mattn/go-pointer v0.0.1
55
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572
6+
github.com/stretchr/testify v1.7.1
7+
github.com/tarantool/go-iproto v1.0.0
8+
github.com/tarantool/go-tarantool/v2 v2.0.0-20240131003940-1a49b281a97e
69
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb // indirect
710
)
811

go.sum

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
4+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
5+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
16
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
27
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
8+
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
9+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11+
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
312
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
413
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
14+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
15+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16+
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
17+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
18+
github.com/tarantool/go-iproto v1.0.0 h1:quC4hdFhCuFYaCqOFgUxH2foRkhAy+TlEy7gQLhdVjw=
19+
github.com/tarantool/go-iproto v1.0.0/go.mod h1:LNCtdyZxojUed8SbOiYHoc3v9NvaZTB7p96hUySMlIo=
20+
github.com/tarantool/go-openssl v0.0.8-0.20231004103608-336ca939d2ca/go.mod h1:M7H4xYSbzqpW/ZRBMyH0eyqQBsnhAMfsYk5mv0yid7A=
21+
github.com/tarantool/go-tarantool/v2 v2.0.0-20240130131506-70383596d128/go.mod h1:fGJBRxbkZmNQap9VxQ7xQHlDhRiHFnqP3gK4ghtlro0=
22+
github.com/tarantool/go-tarantool/v2 v2.0.0-20240131003940-1a49b281a97e h1:M8wYDUTrchX2/7cVf2xtzjxW5QesxCe5OmCvGyZ4ybE=
23+
github.com/tarantool/go-tarantool/v2 v2.0.0-20240131003940-1a49b281a97e/go.mod h1:fGJBRxbkZmNQap9VxQ7xQHlDhRiHFnqP3gK4ghtlro0=
24+
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
25+
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
26+
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
27+
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
528
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
629
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
30+
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
31+
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
32+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
33+
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
34+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
35+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

tt/connection.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package tt
2+
3+
import (
4+
"errors"
5+
"io"
6+
"net"
7+
8+
"github.com/tarantool/go-tarantool/v2"
9+
)
10+
11+
type tntConn struct {
12+
net net.Conn
13+
reader io.Reader
14+
writer writeFlusher
15+
}
16+
17+
// writeFlusher is the interface that groups the basic Write and Flush methods.
18+
type writeFlusher interface {
19+
io.Writer
20+
Flush() error
21+
}
22+
23+
// Addr makes tntConn satisfy the Conn interface.
24+
func (c *tntConn) Addr() net.Addr {
25+
return c.net.RemoteAddr()
26+
}
27+
28+
// Read makes tntConn satisfy the Conn interface.
29+
func (c *tntConn) Read(p []byte) (int, error) {
30+
return c.reader.Read(p)
31+
}
32+
33+
// Write makes tntConn satisfy the Conn interface.
34+
func (c *tntConn) Write(p []byte) (int, error) {
35+
if l, err := c.writer.Write(p); err != nil {
36+
return l, err
37+
} else if l != len(p) {
38+
return l, errors.New("wrong length written")
39+
} else {
40+
return l, nil
41+
}
42+
}
43+
44+
// Flush makes tntConn satisfy the Conn interface.
45+
func (c *tntConn) Flush() error {
46+
return c.writer.Flush()
47+
}
48+
49+
// Close makes tntConn satisfy the Conn interface.
50+
func (c *tntConn) Close() error {
51+
return c.net.Close()
52+
}
53+
54+
// Greeting makes tntConn satisfy the Conn interface.
55+
func (c *tntConn) Greeting() tarantool.Greeting {
56+
return tarantool.Greeting{}
57+
}
58+
59+
// ProtocolInfo makes tntConn satisfy the Conn interface.
60+
func (c *tntConn) ProtocolInfo() tarantool.ProtocolInfo {
61+
return tarantool.ProtocolInfo{}
62+
}

tt/deadline_io.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package tt
2+
3+
import (
4+
"net"
5+
"time"
6+
)
7+
8+
type deadlineIO struct {
9+
to time.Duration
10+
c net.Conn
11+
}
12+
13+
func (d *deadlineIO) Write(b []byte) (n int, err error) {
14+
if d.to > 0 {
15+
d.c.SetWriteDeadline(time.Now().Add(d.to))
16+
}
17+
n, err = d.c.Write(b)
18+
return
19+
}
20+
21+
func (d *deadlineIO) Read(b []byte) (n int, err error) {
22+
if d.to > 0 {
23+
d.c.SetReadDeadline(time.Now().Add(d.to))
24+
}
25+
n, err = d.c.Read(b)
26+
return
27+
}

tt/dialer.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package tt
2+
3+
import (
4+
"bufio"
5+
"context"
6+
"fmt"
7+
8+
"github.com/tarantool/go-tarantool/v2"
9+
)
10+
11+
const bufSize = 128 * 1024
12+
13+
type openSslDialer struct {
14+
address string
15+
sslKeyFile string
16+
sslCertFile string
17+
sslCaFile string
18+
sslCiphers string
19+
sslPassword string
20+
sslPasswordFile string
21+
}
22+
23+
func (d openSslDialer) Dial(ctx context.Context,
24+
opts tarantool.DialOpts) (tarantool.Conn, error) {
25+
var err error
26+
conn := new(tntConn)
27+
28+
network, address := parseAddress(d.address)
29+
conn.net, err = sslDialContext(ctx, network, address, sslOpts{
30+
KeyFile: d.sslKeyFile,
31+
CertFile: d.sslCertFile,
32+
CaFile: d.sslCaFile,
33+
Ciphers: d.sslCiphers,
34+
Password: d.sslPassword,
35+
PasswordFile: d.sslPasswordFile,
36+
})
37+
if err != nil {
38+
return nil, fmt.Errorf("failed to dial: %w", err)
39+
}
40+
41+
dc := &deadlineIO{to: opts.IoTimeout, c: conn.net}
42+
conn.reader = bufio.NewReaderSize(dc, bufSize)
43+
conn.writer = bufio.NewWriterSize(dc, bufSize)
44+
45+
return conn, nil
46+
}
47+
48+
// OpenSslDialer allows to use SSL transport for connection.
49+
type OpenSslDialer struct {
50+
// Address is an address to connect.
51+
// It could be specified in following ways:
52+
//
53+
// - TCP connections (tcp://192.168.1.1:3013, tcp://my.host:3013,
54+
// tcp:192.168.1.1:3013, tcp:my.host:3013, 192.168.1.1:3013, my.host:3013)
55+
//
56+
// - Unix socket, first '/' or '.' indicates Unix socket
57+
// (unix:///abs/path/tnt.sock, unix:path/tnt.sock, /abs/path/tnt.sock,
58+
// ./rel/path/tnt.sock, unix/:path/tnt.sock)
59+
Address string
60+
// Auth is an authentication method.
61+
Auth tarantool.Auth
62+
// Username for logging in to Tarantool.
63+
User string
64+
// User password for logging in to Tarantool.
65+
Password string
66+
// RequiredProtocol contains minimal protocol version and
67+
// list of protocol features that should be supported by
68+
// Tarantool server. By default, there are no restrictions.
69+
RequiredProtocolInfo tarantool.ProtocolInfo
70+
// SslKeyFile is a path to a private SSL key file.
71+
SslKeyFile string
72+
// SslCertFile is a path to an SSL certificate file.
73+
SslCertFile string
74+
// SslCaFile is a path to a trusted certificate authorities (CA) file.
75+
SslCaFile string
76+
// SslCiphers is a colon-separated (:) list of SSL cipher suites the connection
77+
// can use.
78+
//
79+
// We don't provide a list of supported ciphers. This is what OpenSSL
80+
// does. The only limitation is usage of TLSv1.2 (because other protocol
81+
// versions don't seem to support the GOST cipher). To add additional
82+
// ciphers (GOST cipher), you must configure OpenSSL.
83+
//
84+
// See also
85+
//
86+
// * https://www.openssl.org/docs/man1.1.1/man1/ciphers.html
87+
SslCiphers string
88+
// SslPassword is a password for decrypting the private SSL key file.
89+
// The priority is as follows: try to decrypt with SslPassword, then
90+
// try SslPasswordFile.
91+
SslPassword string
92+
// SslPasswordFile is a path to the list of passwords for decrypting
93+
// the private SSL key file. The connection tries every line from the
94+
// file as a password.
95+
SslPasswordFile string
96+
}
97+
98+
// Dial makes OpenSslDialer satisfy the Dialer interface.
99+
func (d OpenSslDialer) Dial(ctx context.Context,
100+
opts tarantool.DialOpts) (tarantool.Conn, error) {
101+
if d.Auth != tarantool.AutoAuth {
102+
d.RequiredProtocolInfo.Auth = d.Auth
103+
}
104+
105+
dialer := tarantool.AuthDialer{
106+
Dialer: tarantool.ProtocolDialer{
107+
Dialer: openSslDialer{
108+
address: d.Address,
109+
sslKeyFile: d.SslKeyFile,
110+
sslCertFile: d.SslCertFile,
111+
sslCaFile: d.SslCaFile,
112+
sslCiphers: d.SslCiphers,
113+
sslPassword: d.SslPassword,
114+
sslPasswordFile: d.SslPasswordFile,
115+
},
116+
RequiredProtocolInfo: d.RequiredProtocolInfo,
117+
},
118+
Auth: d.Auth,
119+
Username: d.User,
120+
Password: d.Password,
121+
}
122+
123+
return dialer.Dial(ctx, opts)
124+
}
125+
126+
// parseAddress split address into network and address parts.
127+
func parseAddress(address string) (string, string) {
128+
network := "tcp"
129+
addrLen := len(address)
130+
131+
if addrLen > 0 && (address[0] == '.' || address[0] == '/') {
132+
network = "unix"
133+
} else if addrLen >= 7 && address[0:7] == "unix://" {
134+
network = "unix"
135+
address = address[7:]
136+
} else if addrLen >= 5 && address[0:5] == "unix:" {
137+
network = "unix"
138+
address = address[5:]
139+
} else if addrLen >= 6 && address[0:6] == "unix/:" {
140+
network = "unix"
141+
address = address[6:]
142+
} else if addrLen >= 6 && address[0:6] == "tcp://" {
143+
address = address[6:]
144+
} else if addrLen >= 4 && address[0:4] == "tcp:" {
145+
address = address[4:]
146+
}
147+
148+
return network, address
149+
}

tt/export_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package tt
2+
3+
type SslTestOpts struct {
4+
KeyFile string
5+
CertFile string
6+
CaFile string
7+
Ciphers string
8+
Password string
9+
PasswordFile string
10+
}
11+
12+
func SslCreateContext(opts SslTestOpts) (ctx interface{}, err error) {
13+
return sslCreateContext(sslOpts(opts))
14+
}

0 commit comments

Comments
 (0)