diff --git a/cmd/cpu.go b/cmd/cpu.go index 5b317f3..bfb239d 100644 --- a/cmd/cpu.go +++ b/cmd/cpu.go @@ -48,7 +48,7 @@ func queryCPU() { check.ExitError(err) } - dbConnection := internal.DBConnection(host, port, username, password, database) + dbConnection := internal.DBConnection(host, port, username, password, database, useTLS, caCertPath, clientCertPath, clientCertKey) err = dbConnection.QueryRow( `SELECT hqs.overall_cpu_usage, diff --git a/cmd/datastore.go b/cmd/datastore.go index 30e34c8..3b963f2 100644 --- a/cmd/datastore.go +++ b/cmd/datastore.go @@ -57,7 +57,7 @@ func queryDatastore() { check.ExitError(err) } - dbConnection := internal.DBConnection(host, port, username, password, database) + dbConnection := internal.DBConnection(host, port, username, password, database, useTLS, caCertPath, clientCertPath, clientCertKey) err = dbConnection.QueryRow(`SELECT ds.capacity, ds.free_space FROM datastore ds @@ -102,7 +102,7 @@ func queryDatastores() { } // Collect query results. - dbConnection := internal.DBConnection(host, port, username, password, database) + dbConnection := internal.DBConnection(host, port, username, password, database, useTLS, caCertPath, clientCertPath, clientCertKey) rows, err := dbConnection.Query(`SELECT o.object_name, ds.capacity, ds.free_space FROM datastore ds diff --git a/cmd/hba.go b/cmd/hba.go index 20c3c78..6e69278 100644 --- a/cmd/hba.go +++ b/cmd/hba.go @@ -46,7 +46,7 @@ func queryHba() { check.ExitError(err) } - dbConnection := internal.DBConnection(host, port, username, password, database) + dbConnection := internal.DBConnection(host, port, username, password, database, useTLS, caCertPath, clientCertPath, clientCertKey) err = dbConnection.QueryRow(`SELECT hardware_num_hba FROM host_system diff --git a/cmd/memory.go b/cmd/memory.go index a7d8307..9259151 100644 --- a/cmd/memory.go +++ b/cmd/memory.go @@ -48,7 +48,7 @@ func queryMemory() { check.ExitError(err) } - dbConnection := internal.DBConnection(host, port, username, password, database) + dbConnection := internal.DBConnection(host, port, username, password, database, useTLS, caCertPath, clientCertPath, clientCertKey) err = dbConnection.QueryRow( `SELECT hqs.overall_memory_usage_mb, diff --git a/cmd/nic.go b/cmd/nic.go index 82d2408..a83129d 100644 --- a/cmd/nic.go +++ b/cmd/nic.go @@ -46,7 +46,7 @@ func queryNic() { check.ExitError(err) } - dbConnection := internal.DBConnection(host, port, username, password, database) + dbConnection := internal.DBConnection(host, port, username, password, database, useTLS, caCertPath, clientCertPath, clientCertKey) err = dbConnection.QueryRow(`SELECT hardware_num_nic FROM host_system diff --git a/cmd/root.go b/cmd/root.go index f183135..9f20c6d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,6 +16,11 @@ var username string var password string var credentialsFile string +var useTLS bool +var caCertPath string +var clientCertPath string +var clientCertKey string + var pl check.PerfdataList var rootCmd = &cobra.Command{ @@ -57,4 +62,8 @@ func init() { rootCmd.PersistentFlags().StringVarP(&username, "username", "u", "vspheredb", "Database username") rootCmd.PersistentFlags().StringVarP(&password, "password", "P", "vspheredb", "Database password") rootCmd.PersistentFlags().StringVarP(&credentialsFile, "credentials-file", "f", "", "Path to the credentials file") + rootCmd.PersistentFlags().BoolVar(&useTLS, "tls", false, "Use TLS to connect to the database") + rootCmd.PersistentFlags().StringVar(&caCertPath, "ca-cert", "", "CA certificate (file path)") + rootCmd.PersistentFlags().StringVar(&clientCertPath, "client-cert", "", "Client certificate (file path)") + rootCmd.PersistentFlags().StringVar(&clientCertKey, "client-key", "", "Client certificate key (file path)") } diff --git a/cmd/temperature.go b/cmd/temperature.go index 815d4d3..f4ad04c 100644 --- a/cmd/temperature.go +++ b/cmd/temperature.go @@ -48,7 +48,7 @@ func queryTemperature() { check.ExitError(err) } - dbConnection := internal.DBConnection(host, port, username, password, database) + dbConnection := internal.DBConnection(host, port, username, password, database, useTLS, caCertPath, clientCertPath, clientCertKey) defer dbConnection.Close() rows, err := dbConnection.Query(`SELECT se.name, se.current_reading diff --git a/internal/utils.go b/internal/utils.go index 8cfbf69..5729aaf 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -2,14 +2,18 @@ package internal import ( "context" + "crypto/tls" + "crypto/x509" "database/sql" "encoding/json" + "errors" "fmt" "os" "time" "github.com/NETWAYS/go-check" + "github.com/go-sql-driver/mysql" // needed to use the MySQL driver for the sql module. _ "github.com/go-sql-driver/mysql" ) @@ -53,8 +57,56 @@ func ParseCredentialsFile(credentialsFile string, username *string, password *st } // DBConnection establishes and checks DB connection and returns the connection. -func DBConnection(host string, port int16, username string, password string, database string) *sql.DB { - connStr := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", username, password, host, port, database) +func DBConnection(host string, port int16, username string, password string, database string, usetls bool, cacertPath string, clientCertPath string, clientKeyPath string) *sql.DB { + var connStr string + + if usetls { //nolint:nestif + TLSConfig := tls.Config{} + complexConfig := false + + if cacertPath != "" { + rootCertPool := x509.NewCertPool() + + pem, err := os.ReadFile(cacertPath) + if err != nil { + check.ExitError(err) + } + + if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { + check.ExitError(errors.New("failed to append PEM")) + } + + TLSConfig.RootCAs = rootCertPool + complexConfig = true + } + + if clientCertPath != "" && clientKeyPath != "" { + clientCert := make([]tls.Certificate, 0, 1) + + certs, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath) + if err != nil { + check.ExitError(err) + } + + clientCert = append(clientCert, certs) + + TLSConfig.Certificates = clientCert + complexConfig = true + } + + err := mysql.RegisterTLSConfig("custom", &TLSConfig) + if err != nil { + check.ExitError(err) + } + + if complexConfig { + connStr = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?tls=custom", username, password, host, port, database) + } else { + connStr = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?tls=true", username, password, host, port, database) + } + } else { + connStr = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", username, password, host, port, database) + } // Open connection. db, err := sql.Open("mysql", connStr)