Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(pkg/server): tls configuration is moved in command package from server #735

Merged
merged 5 commits into from
May 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions cmd/immudb/command/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func DefaultTestOptions() (o *server.Options) {
o.Pidfile = "tmp/immudbtest/immudbtest.pid"
o.Logfile = "immudbtest.log"
o.Dir = "tmp/immudbtest/data"
o.MTLs = false
return o
}

Expand All @@ -55,12 +54,12 @@ func TestImmudbCommandFlagParser(t *testing.T) {
},
}
cl := Commandline{}
cl.setupFlags(cmd, server.DefaultOptions(), server.DefaultMTLsOptions())
cl.setupFlags(cmd, server.DefaultOptions())

err = viper.BindPFlags(cmd.Flags())
assert.Nil(t, err)

setupDefaults(server.DefaultOptions(), server.DefaultMTLsOptions())
setupDefaults(server.DefaultOptions())

_, err = executeCommand(cmd, "--logfile="+o.Logfile)
assert.NoError(t, err)
Expand Down Expand Up @@ -91,12 +90,12 @@ func TestImmudbCommandFlagParserPriority(t *testing.T) {
return nil
},
}
cl.setupFlags(cmd, server.DefaultOptions(), server.DefaultMTLsOptions())
cl.setupFlags(cmd, server.DefaultOptions())

err = viper.BindPFlags(cmd.Flags())
assert.Nil(t, err)

setupDefaults(server.DefaultOptions(), server.DefaultMTLsOptions())
setupDefaults(server.DefaultOptions())

// 4. config file
_, err = executeCommand(cmd)
Expand Down Expand Up @@ -175,6 +174,9 @@ func TestImmudbMtls(t *testing.T) {
cmd := &cobra.Command{}
cmd.Flags().StringVar(&config, "config", "", "test")
viper.Set("mtls", true)
viper.Set("pkey", "../../../test/mtls_certs/ca.key.pem")
viper.Set("certificate", "../../../test/mtls_certs/ca.cert.pem")
viper.Set("clientcas", "../../../test/mtls_certs/ca-chain.cert.pem")

cl := Commandline{}

Expand Down
120 changes: 120 additions & 0 deletions cmd/immudb/command/init_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// +build linux darwin freebsd

/*
Copyright 2021 CodeNotary, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package immudb

import (
c "github.com/codenotary/immudb/cmd/helper"
"github.com/codenotary/immudb/pkg/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func parseOptions() (options *server.Options, err error) {
dir := viper.GetString("dir")
port := viper.GetInt("port")
address := viper.GetString("address")
pidfile := viper.GetString("pidfile")
logfile := viper.GetString("logfile")
mtls := viper.GetBool("mtls")
auth := viper.GetBool("auth")
maxRecvMsgSize := viper.GetInt("max-recv-msg-size")
noHistograms := viper.GetBool("no-histograms")
detached := viper.GetBool("detached")
certificate := viper.GetString("certificate")
pkey := viper.GetString("pkey")
clientcas := viper.GetString("clientcas")
devMode := viper.GetBool("devmode")
adminPassword := viper.GetString("admin-password")
maintenance := viper.GetBool("maintenance")
signingKey := viper.GetString("signingKey")
synced := viper.GetBool("synced")
tokenExpTime := viper.GetInt("token-expiry-time")

storeOpts := server.DefaultStoreOptions().WithSynced(synced)

tlsConfig, err := setUpTLS(pkey, certificate, clientcas, mtls)
if err != nil {
return options, err
}

options = server.
DefaultOptions().
WithDir(dir).
WithPort(port).
WithAddress(address).
WithPidfile(pidfile).
WithLogfile(logfile).
WithTLS(tlsConfig).
WithAuth(auth).
WithMaxRecvMsgSize(maxRecvMsgSize).
WithNoHistograms(noHistograms).
WithDetached(detached).
WithDevMode(devMode).
WithAdminPassword(adminPassword).
WithMaintenance(maintenance).
WithSigningKey(signingKey).
WithStoreOptions(storeOpts).
WithTokenExpiryTime(tokenExpTime)

return options, nil
}

func (cl *Commandline) setupFlags(cmd *cobra.Command, options *server.Options) {
cmd.Flags().String("dir", options.Dir, "data folder")
cmd.Flags().IntP("port", "p", options.Port, "port number")
cmd.Flags().StringP("address", "a", options.Address, "bind address")
cmd.PersistentFlags().StringVar(&cl.config.CfgFn, "config", "", "config file (default path are configs or $HOME. Default filename is immudb.toml)")
cmd.Flags().String("pidfile", options.Pidfile, "pid path with filename. E.g. /var/run/immudb.pid")
cmd.Flags().String("logfile", options.Logfile, "log path with filename. E.g. /tmp/immudb/immudb.log")
cmd.Flags().BoolP("mtls", "m", false, "enable mutual tls")
cmd.Flags().BoolP("auth", "s", false, "enable auth")
cmd.Flags().Int("max-recv-msg-size", options.MaxRecvMsgSize, "max message size in bytes the server can receive")
cmd.Flags().Bool("no-histograms", false, "disable collection of histogram metrics like query durations")
cmd.Flags().BoolP(c.DetachedFlag, c.DetachedShortFlag, options.Detached, "run immudb in background")
cmd.Flags().String("certificate", "", "server certificate file path")
cmd.Flags().String("pkey", "", "server private key path")
cmd.Flags().String("clientcas", "", "clients certificates list. Aka certificate authority")
cmd.Flags().Bool("devmode", options.DevMode, "enable dev mode: accept remote connections without auth")
cmd.Flags().String("admin-password", options.AdminPassword, "admin password (default is 'immudb') as plain-text or base64 encoded (must be prefixed with 'enc:' if it is encoded)")
cmd.Flags().Bool("maintenance", options.GetMaintenance(), "override the authentication flag")
cmd.Flags().String("signingKey", options.SigningKey, "signature private key path. If a valid one is provided, it enables the cryptographic signature of the root. E.g. \"./../test/signer/ec3.key\"")
cmd.Flags().Bool("synced", false, "synced mode prevents data lost under unexpected crashes but affects performance")
cmd.Flags().Int("token-expiry-time", options.TokenExpiryTimeMin, "client authentication token expiration time. Minutes")
}

func setupDefaults(options *server.Options) {
viper.SetDefault("dir", options.Dir)
viper.SetDefault("port", options.Port)
viper.SetDefault("address", options.Address)
viper.SetDefault("pidfile", options.Pidfile)
viper.SetDefault("logfile", options.Logfile)
viper.SetDefault("mtls", false)
viper.SetDefault("auth", options.GetAuth())
viper.SetDefault("max-recv-msg-size", options.MaxRecvMsgSize)
viper.SetDefault("no-histograms", options.NoHistograms)
viper.SetDefault("detached", options.Detached)
viper.SetDefault("certificate", "")
viper.SetDefault("pkey", "")
viper.SetDefault("clientcas", "")
viper.SetDefault("devmode", options.DevMode)
viper.SetDefault("admin-password", options.AdminPassword)
viper.SetDefault("maintenance", options.GetMaintenance())
viper.SetDefault("synced", false)
viper.SetDefault("token-expiry-time", options.TokenExpiryTimeMin)
}
44 changes: 20 additions & 24 deletions cmd/immudb/command/init.go → cmd/immudb/command/init_windows.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// +build windows
/*
Copyright 2021 CodeNotary, Inc. All rights reserved.

Expand Down Expand Up @@ -30,9 +31,7 @@ func parseOptions() (options *server.Options, err error) {
}
port := viper.GetInt("port")
address := viper.GetString("address")
if err != nil {
return options, err
}

pidfile, err := c.ResolvePath(viper.GetString("pidfile"), true)
if err != nil {
return options, err
Expand Down Expand Up @@ -68,14 +67,19 @@ func parseOptions() (options *server.Options, err error) {

storeOpts := server.DefaultStoreOptions().WithSynced(synced)

tlsConfig, err := setUpTLS(pkey, certificate, clientcas, mtls)
if err != nil {
return options, err
}

options = server.
DefaultOptions().
WithDir(dir).
WithPort(port).
WithAddress(address).
WithPidfile(pidfile).
WithLogfile(logfile).
WithMTLs(mtls).
WithTLS(tlsConfig).
WithAuth(auth).
WithMaxRecvMsgSize(maxRecvMsgSize).
WithNoHistograms(noHistograms).
Expand All @@ -87,32 +91,24 @@ func parseOptions() (options *server.Options, err error) {
WithStoreOptions(storeOpts).
WithTokenExpiryTime(tokenExpTime)

if mtls {
// todo https://golang.org/src/crypto/x509/root_linux.go
options.MTLsOptions = server.DefaultMTLsOptions().
WithCertificate(certificate).
WithPkey(pkey).
WithClientCAs(clientcas)
}

return options, nil
}

func (cl *Commandline) setupFlags(cmd *cobra.Command, options *server.Options, mtlsOptions *server.MTLsOptions) {
func (cl *Commandline) setupFlags(cmd *cobra.Command, options *server.Options) {
cmd.Flags().String("dir", options.Dir, "data folder")
cmd.Flags().IntP("port", "p", options.Port, "port number")
cmd.Flags().StringP("address", "a", options.Address, "bind address")
cmd.PersistentFlags().StringVar(&cl.config.CfgFn, "config", "", "config file (default path are configs or $HOME. Default filename is immudb.toml)")
cmd.Flags().String("pidfile", options.Pidfile, "pid path with filename. E.g. /var/run/immudb.pid")
cmd.Flags().String("logfile", options.Logfile, "log path with filename. E.g. /tmp/immudb/immudb.log")
cmd.Flags().BoolP("mtls", "m", options.MTLs, "enable mutual tls")
cmd.Flags().BoolP("auth", "s", options.MTLs, "enable auth")
cmd.Flags().BoolP("mtls", "m", false, "enable mutual tls")
cmd.Flags().BoolP("auth", "s", false, "enable auth")
cmd.Flags().Int("max-recv-msg-size", options.MaxRecvMsgSize, "max message size in bytes the server can receive")
cmd.Flags().Bool("no-histograms", options.MTLs, "disable collection of histogram metrics like query durations")
cmd.Flags().Bool("no-histograms", false, "disable collection of histogram metrics like query durations")
cmd.Flags().BoolP(c.DetachedFlag, c.DetachedShortFlag, options.Detached, "run immudb in background")
cmd.Flags().String("certificate", mtlsOptions.Certificate, "server certificate file path")
cmd.Flags().String("pkey", mtlsOptions.Pkey, "server private key path")
cmd.Flags().String("clientcas", mtlsOptions.ClientCAs, "clients certificates list. Aka certificate authority")
cmd.Flags().String("certificate", "", "server certificate file path")
cmd.Flags().String("pkey", "", "server private key path")
cmd.Flags().String("clientcas", "", "clients certificates list. Aka certificate authority")
cmd.Flags().Bool("devmode", options.DevMode, "enable dev mode: accept remote connections without auth")
cmd.Flags().String("admin-password", options.AdminPassword, "admin password (default is 'immudb') as plain-text or base64 encoded (must be prefixed with 'enc:' if it is encoded)")
cmd.Flags().Bool("maintenance", options.GetMaintenance(), "override the authentication flag")
Expand All @@ -121,20 +117,20 @@ func (cl *Commandline) setupFlags(cmd *cobra.Command, options *server.Options, m
cmd.Flags().Int("token-expiry-time", options.TokenExpiryTimeMin, "client authentication token expiration time. Minutes")
}

func setupDefaults(options *server.Options, mtlsOptions *server.MTLsOptions) {
func setupDefaults(options *server.Options) {
viper.SetDefault("dir", options.Dir)
viper.SetDefault("port", options.Port)
viper.SetDefault("address", options.Address)
viper.SetDefault("pidfile", options.Pidfile)
viper.SetDefault("logfile", options.Logfile)
viper.SetDefault("mtls", options.MTLs)
viper.SetDefault("mtls", false)
viper.SetDefault("auth", options.GetAuth())
viper.SetDefault("max-recv-msg-size", options.MaxRecvMsgSize)
viper.SetDefault("no-histograms", options.NoHistograms)
viper.SetDefault("detached", options.Detached)
viper.SetDefault("certificate", mtlsOptions.Certificate)
viper.SetDefault("pkey", mtlsOptions.Pkey)
viper.SetDefault("clientcas", mtlsOptions.ClientCAs)
viper.SetDefault("certificate", "")
viper.SetDefault("pkey", "")
viper.SetDefault("clientcas", "")
viper.SetDefault("devmode", options.DevMode)
viper.SetDefault("admin-password", options.AdminPassword)
viper.SetDefault("maintenance", options.GetMaintenance())
Expand Down
10 changes: 5 additions & 5 deletions cmd/immudb/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ Environment variables:
IMMUDB_MAX_RECV_MSG_SIZE=4194304
IMMUDB_DETACHED=false
IMMUDB_CONSISTENCY_CHECK=true
IMMUDB_PKEY=./tools/mtls/3_application/private/localhost.key.pem
IMMUDB_CERTIFICATE=./tools/mtls/3_application/certs/localhost.cert.pem
IMMUDB_CLIENTCAS=./tools/mtls/2_intermediate/certs/ca-chain.cert.pem
IMMUDB_PKEY=
IMMUDB_CERTIFICATE=
IMMUDB_CLIENTCAS=
IMMUDB_DEVMODE=true
IMMUDB_MAINTENANCE=false
IMMUDB_ADMIN_PASSWORD=immudb
Expand All @@ -59,13 +59,13 @@ Environment variables:
PersistentPreRunE: cl.ConfigChain(nil),
}

cl.setupFlags(cmd, server.DefaultOptions(), server.DefaultMTLsOptions())
cl.setupFlags(cmd, server.DefaultOptions())

if err := viper.BindPFlags(cmd.Flags()); err != nil {
return nil, err
}

setupDefaults(server.DefaultOptions(), server.DefaultMTLsOptions())
setupDefaults(server.DefaultOptions())

return cmd, nil
}
Expand Down
62 changes: 62 additions & 0 deletions cmd/immudb/command/tls_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright 2021 CodeNotary, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package immudb

import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
)

func setUpTLS(pkey, cert, ca string, mtls bool) (*tls.Config, error) {
var c *tls.Config

if cert != "" && pkey != "" {
certs, err := tls.LoadX509KeyPair(cert, pkey)
if err != nil {
return nil, errors.New(fmt.Sprintf("failed to read client certificate or private key: %v", err))
}
c = &tls.Config{
Certificates: []tls.Certificate{certs},
ClientAuth: tls.VerifyClientCertIfGiven,
}
}

if mtls && (cert == "" || pkey == "") {
return nil, errors.New("in order to enable MTLS a certificate and private key are required")
}

// if CA is not provided there is an automatic load of local CA in os
if mtls && ca != "" {
certPool := x509.NewCertPool()
// Trusted store, contain the list of trusted certificates. client has to use one of this certificate to be trusted by this server
bs, err := ioutil.ReadFile(ca)
if err != nil {
return nil, errors.New(fmt.Sprintf("failed to read client ca cert: %v", err))
}

ok := certPool.AppendCertsFromPEM(bs)
if !ok {
return nil, errors.New(fmt.Sprintf("failed to append client certs: %v", err))
}
c.ClientCAs = certPool
}

return c, nil
}
6 changes: 3 additions & 3 deletions configs/immuadmin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ immudb-port = 3322
tokenfile = "token_admin"
mtls = false
servername = "localhost"
pkey = "./tools/mtls/4_client/private/localhost.key.pem"
certificate = "./tools/mtls/4_client/certs/localhost.cert.pem"
clientcas = "./tools/mtls/2_intermediate/certs/ca-chain.cert.pem"
pkey = ""
certificate = ""
clientcas = ""
6 changes: 3 additions & 3 deletions configs/immuclient.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ auth = true
tokenfile = "token-0.7.0"
mtls = false
servername = "localhost"
pkey = "./tools/mtls/4_client/private/localhost.key.pem"
certificate = "./tools/mtls/4_client/certs/localhost.cert.pem"
clientcas = "./tools/mtls/2_intermediate/certs/ca-chain.cert.pem"
pkey = ""
certificate = ""
clientcas = ""
audit-signature = "ignore"
server-signing-pub-key = "" #used to verify signatures
6 changes: 3 additions & 3 deletions configs/immudb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ detached = false
auth = true
no-histograms = false
consistency-check = true
pkey = "./tools/mtls/3_application/private/localhost.key.pem"
certificate = "./tools/mtls/3_application/certs/localhost.cert.pem"
clientcas = "./tools/mtls/2_intermediate/certs/ca-chain.cert.pem"
pkey = ""
certificate = ""
clientcas = ""
devmode = true
admin-password = "immudb" # this password is only used once to initialize immudb and can be ignored
maintenance = false
Expand Down
Loading