This package allows creating a TLS dialer for
go-tarantool.
It serves as an interlayer between go-tarantool and a pluggable TLS engine
(a tlsdialer.Backend).
The TLS handshake is delegated to a tlsdialer.Backend, which must be provided.
The cgo OpenSSL engine lives in its own, cgo-only sub-package
github.com/tarantool/go-tlsdialer/backend/openssl (openssl.New()). See
Backends.
To run a default set of tests:
go test -v ./...User can create a dialer by filling the struct:
// 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/tt.sock, unix:path/tt.sock, /abs/path/tt.sock,
// ./rel/path/tt.sock, unix/:path/tt.sock)
Address string
// Auth is an authentication method.
Auth tarantool.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 tarantool.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
}To create a connection from the created dialer a Dial function could be used:
package tarantool
import (
"context"
"fmt"
"time"
"github.com/tarantool/go-tarantool/v2"
"github.com/tarantool/go-tlsdialer"
"github.com/tarantool/go-tlsdialer/backend/openssl"
)
func main() {
dialer := tlsdialer.OpenSSLDialer{
Address: "127.0.0.1:3301",
User: "guest",
Backend: openssl.New(),
}
opts := tarantool.Opts{
Timeout: 5 * time.Second,
}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
conn, err := tarantool.Connect(ctx, dialer, opts)
if err != nil {
fmt.Printf("Failed to create an example connection: %s", err)
return
}
// Use the connection.
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)
}
}The TLS handshake is performed by a tlsdialer.Backend — an interface with a
single DialTLS method. OpenSSLDialer does not link a TLS engine itself; it
delegates to whichever tlsdialer.Backend is set. The dialer's Ssl* fields are
translated into a tlsdialer.Opts value and handed to that backend, so the
same configuration drives every engine.
Backend is required: import the cgo OpenSSL engine and pass openssl.New(),
or supply your own implementation.
import "github.com/tarantool/go-tlsdialer/backend/openssl"
dialer := tlsdialer.OpenSSLDialer{Address: addr, Backend: openssl.New()}A dialer with no Backend set returns an error from Dial. Because the root
tlsdialer package imports no engine, it does not pull in cgo on its own — a
program opts into OpenSSL/cgo only by importing backend/openssl.
The backend/openssl package links the system OpenSSL library through
github.com/tarantool/go-openssl, so every file in it carries a //go:build cgo
constraint, and so does anything that imports it. Building it with
CGO_ENABLED=0 compiles a single stub instead, which fails the build with a
readable message rather than a confusing undefined: New:
$ CGO_ENABLED=0 go build ./...
# github.com/tarantool/go-tlsdialer/backend/openssl
backend/openssl/nocgo.go:13:22: undefined: This_package_requires_CGO_ENABLED_1In other words, using the OpenSSL backend requires cgo and a linkable OpenSSL (see Application build below).
Since the OpenSSL backend uses OpenSSL for connection to the Tarantool-EE, Cgo should be enabled while building and OpenSSL libraries and includes should be available in build time.
Build your application using the command:
- Static build.
CGO_ENABLED=1 go build -ldflags "-linkmode external -extldflags '-static -lssl -lcrypto'" -o myapp main.go - Dynamic build.
CGO_ENABLED=1 go build -o myapp main.go
OpenSSL could be build in two ways. Both of them require downloading the source code of OpenSSL. It could be done from the official website or from the GitHub repository.
- Static build. Run this command from the installation directory to configure
the OpenSSL:
./config no-shared --prefix=/tmp/openssl/
- Dynamic build. Run this command from the installation directory to configure
the OpenSSL:
After configuring, run this command to install and build OpenSSL:
./config --prefix=/tmp/openssl/
make install
And then build your application using the command:
- Static build.
CGO_ENABLED=1 CGO_CFLAGS="-I/tmp/openssl/include" CGO_LDFLAGS="-L/tmp/openssl/lib" PKG_CONFIG_PATH="/tmp/openssl/lib/pkgconfig" go build -ldflags "-linkmode=external -extldflags '-static -lssl -lcrypto'" -o myapp main.go
- Dynamic build.
CGO_ENABLED=1 CGO_CFLAGS="-I/tmp/openssl/include" CGO_LDFLAGS="-L/tmp/openssl/lib" PKG_CONFIG_PATH="/tmp/openssl/lib/pkgconfig" go build -o myapp main.go
After compiling your Go application, you can run it as usual.