Add remote data store connections with SSL
This commit is contained in:
parent
804fabc6c0
commit
7b03d6f05e
5 changed files with 147 additions and 7 deletions
49
cli/setup.go
49
cli/setup.go
|
@ -45,6 +45,55 @@ func setup() {
|
||||||
log.Fatal("Specify a valid data store configuration path")
|
log.Fatal("Specify a valid data store configuration path")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(opts.DB.Cert.CA, "-----") {
|
||||||
|
var err error
|
||||||
|
var doc *os.File
|
||||||
|
if doc, err = os.Create("db.ca"); err != nil {
|
||||||
|
log.Fatal("Can not decode PEM encoded CA into db.ca")
|
||||||
|
}
|
||||||
|
doc.Write([]byte(opts.DB.Cert.CA))
|
||||||
|
doc.Close()
|
||||||
|
opts.Cert.Crt = "db.ca"
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(opts.DB.Cert.Crt, "-----") {
|
||||||
|
var err error
|
||||||
|
var doc *os.File
|
||||||
|
if doc, err = os.Create("db.key"); err != nil {
|
||||||
|
log.Fatal("Can not decode PEM encoded certificate into db.crt")
|
||||||
|
}
|
||||||
|
doc.Write([]byte(opts.DB.Cert.Crt))
|
||||||
|
doc.Close()
|
||||||
|
opts.Cert.Crt = "db.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(opts.DB.Cert.Key, "-----") {
|
||||||
|
var err error
|
||||||
|
var doc *os.File
|
||||||
|
if doc, err = os.Create("db.crt"); err != nil {
|
||||||
|
log.Fatal("Can not decode PEM encoded private key into db.key")
|
||||||
|
}
|
||||||
|
doc.Write([]byte(opts.DB.Cert.Key))
|
||||||
|
doc.Close()
|
||||||
|
opts.Cert.Crt = "db.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.DB.Cert.CA != "" || opts.DB.Cert.Crt != "" || opts.DB.Cert.Key != "" {
|
||||||
|
opts.DB.Cert.SSL = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.DB.Cert.CA == "" && opts.DB.Cert.SSL {
|
||||||
|
log.Fatal("Specify a valid PEM encoded CA file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.DB.Cert.Crt == "" && opts.DB.Cert.SSL {
|
||||||
|
log.Fatal("Specify a valid PEM encoded certificate file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.DB.Cert.Key == "" && opts.DB.Cert.SSL {
|
||||||
|
log.Fatal("Specify a valid PEM encoded private key file.")
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Auth
|
// Auth
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
|
@ -72,6 +72,9 @@ func init() {
|
||||||
|
|
||||||
startCmd.PersistentFlags().StringVar(&opts.DB.Base, "db-base", "", flag("db-base"))
|
startCmd.PersistentFlags().StringVar(&opts.DB.Base, "db-base", "", flag("db-base"))
|
||||||
startCmd.PersistentFlags().StringVar(&opts.DB.Path, "db-path", "", flag("db-path"))
|
startCmd.PersistentFlags().StringVar(&opts.DB.Path, "db-path", "", flag("db-path"))
|
||||||
|
startCmd.PersistentFlags().StringVar(&opts.DB.Cert.CA, "db-ca", "", "Path to the CA file used to connect to the remote database.")
|
||||||
|
startCmd.PersistentFlags().StringVar(&opts.DB.Cert.Crt, "db-crt", "", "Path to the certificate file used to connect to the remote database.")
|
||||||
|
startCmd.PersistentFlags().StringVar(&opts.DB.Cert.Key, "db-key", "", "Path to the private key file used to connect to the remote database.")
|
||||||
|
|
||||||
startCmd.PersistentFlags().IntVar(&opts.Port.Tcp, "port-tcp", 0, flag("port-tcp"))
|
startCmd.PersistentFlags().IntVar(&opts.Port.Tcp, "port-tcp", 0, flag("port-tcp"))
|
||||||
startCmd.PersistentFlags().IntVar(&opts.Port.Web, "port-web", 0, flag("port-web"))
|
startCmd.PersistentFlags().IntVar(&opts.Port.Web, "port-web", 0, flag("port-web"))
|
||||||
|
|
|
@ -23,6 +23,12 @@ type Options struct {
|
||||||
Host string // Surreal host to connect to
|
Host string // Surreal host to connect to
|
||||||
Port string // Surreal port to connect to
|
Port string // Surreal port to connect to
|
||||||
Base string // Base key to use in KV stores
|
Base string // Base key to use in KV stores
|
||||||
|
Cert struct {
|
||||||
|
CA string
|
||||||
|
Crt string
|
||||||
|
Key string
|
||||||
|
SSL bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Port struct {
|
Port struct {
|
||||||
|
|
|
@ -15,10 +15,15 @@
|
||||||
package mysql
|
package mysql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
"github.com/go-sql-driver/mysql"
|
||||||
|
|
||||||
"github.com/abcum/surreal/cnf"
|
"github.com/abcum/surreal/cnf"
|
||||||
"github.com/abcum/surreal/kvs"
|
"github.com/abcum/surreal/kvs"
|
||||||
|
@ -32,9 +37,12 @@ func New(opts *cnf.Options) (ds kvs.DS, err error) {
|
||||||
|
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
|
|
||||||
path := strings.TrimLeft(opts.DB.Path, "mysql://")
|
opts.DB.Path, err = config(opts)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
db, err = sql.Open("mysql", path)
|
db, err = sql.Open("mysql", opts.DB.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -42,3 +50,49 @@ func New(opts *cnf.Options) (ds kvs.DS, err error) {
|
||||||
return &DS{db: db, ck: opts.DB.Key}, err
|
return &DS{db: db, ck: opts.DB.Key}, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func config(opts *cnf.Options) (path string, err error) {
|
||||||
|
|
||||||
|
re := regexp.MustCompile(`^mysql://` +
|
||||||
|
`((?:(?P<user>.*?)(?::(?P<passwd>.*))?@))?` +
|
||||||
|
`(?:(?:(?P<addr>[^\/]*))?)?` +
|
||||||
|
`\/(?P<dbname>.*?)` +
|
||||||
|
`(?:\?(?P<params>[^\?]*))?$`)
|
||||||
|
|
||||||
|
ma := re.FindStringSubmatch(opts.DB.Path)
|
||||||
|
|
||||||
|
if len(ma) == 0 || ma[4] == "" || ma[5] == "" {
|
||||||
|
err = fmt.Errorf("Specify a valid data store configuration path. Use the help command for further instructions.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.DB.Cert.SSL {
|
||||||
|
pool := x509.NewCertPool()
|
||||||
|
pem, err := ioutil.ReadFile(opts.DB.Cert.CA)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Could not read file %s", opts.DB.Cert.CA)
|
||||||
|
}
|
||||||
|
if ok := pool.AppendCertsFromPEM(pem); !ok {
|
||||||
|
return "", fmt.Errorf("Could not read file %s", opts.DB.Cert.CA)
|
||||||
|
}
|
||||||
|
cert := make([]tls.Certificate, 0, 1)
|
||||||
|
pair, err := tls.LoadX509KeyPair(opts.DB.Cert.Crt, opts.DB.Cert.Key)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
cert = append(cert, pair)
|
||||||
|
mysql.RegisterTLSConfig("custom", &tls.Config{
|
||||||
|
RootCAs: pool,
|
||||||
|
Certificates: cert,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.DB.Cert.SSL {
|
||||||
|
path += fmt.Sprintf("%stcp(%s)/%s?tls=custom", ma[1], ma[4], ma[5])
|
||||||
|
} else {
|
||||||
|
path += fmt.Sprintf("%stcp(%s)/%s", ma[1], ma[4], ma[5])
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
package pgsql
|
package pgsql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
@ -32,9 +33,12 @@ func New(opts *cnf.Options) (ds kvs.DS, err error) {
|
||||||
|
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
|
|
||||||
path := strings.TrimLeft(opts.DB.Path, "pgsql://")
|
opts.DB.Path, err = config(opts)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
db, err = sql.Open("postgres", path)
|
db, err = sql.Open("postgres", opts.DB.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -42,3 +46,27 @@ func New(opts *cnf.Options) (ds kvs.DS, err error) {
|
||||||
return &DS{db: db, ck: opts.DB.Key}, err
|
return &DS{db: db, ck: opts.DB.Key}, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func config(opts *cnf.Options) (path string, err error) {
|
||||||
|
|
||||||
|
re := regexp.MustCompile(`^mysql://` +
|
||||||
|
`((?:(?P<user>.*?)(?::(?P<passwd>.*))?@))?` +
|
||||||
|
`(?:(?:(?P<addr>[^\/]*))?)?` +
|
||||||
|
`\/(?P<dbname>.*?)` +
|
||||||
|
`(?:\?(?P<params>[^\?]*))?$`)
|
||||||
|
|
||||||
|
ma := re.FindStringSubmatch(opts.DB.Path)
|
||||||
|
|
||||||
|
if len(ma) == 0 || ma[4] == "" || ma[5] == "" {
|
||||||
|
err = fmt.Errorf("Specify a valid data store configuration path. Use the help command for further instructions.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.DB.Cert.SSL {
|
||||||
|
path += fmt.Sprintf("postgres://%s%s/%s?sslmode=verify-ca&sslrootcert=%s&sslcert=%s&sslkey=%s", ma[1], ma[4], ma[5], opts.DB.Cert.CA, opts.DB.Cert.Crt, opts.DB.Cert.Key)
|
||||||
|
} else {
|
||||||
|
path += fmt.Sprintf("postgres://%s%s/%s", ma[1], ma[4], ma[5])
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue