@ -2,8 +2,10 @@ package postgres
import (
"database/sql"
"fmt"
"net/url"
"strconv"
"strings"
"github.com/grafana/grafana/pkg/setting"
@ -20,8 +22,13 @@ func init() {
func newPostgresQueryEndpoint ( datasource * models . DataSource ) ( tsdb . TsdbQueryEndpoint , error ) {
logger := log . New ( "tsdb.postgres" )
logger . Debug ( "Creating Postgres query endpoint" )
cnnstr , err := generateConnectionString ( datasource , logger )
if err != nil {
return nil , err
}
cnnstr := generateConnectionString ( datasource )
if setting . Env == setting . DEV {
logger . Debug ( "getEngine" , "connection" , cnnstr )
}
@ -39,19 +46,51 @@ func newPostgresQueryEndpoint(datasource *models.DataSource) (tsdb.TsdbQueryEndp
timescaledb := datasource . JsonData . Get ( "timescaledb" ) . MustBool ( false )
return sqleng . NewSqlQueryEndpoint ( & config , & queryResultTransformer , newPostgresMacroEngine ( timescaledb ) , logger )
endpoint , err := sqleng . NewSqlQueryEndpoint ( & config , & queryResultTransformer , newPostgresMacroEngine ( timescaledb ) , logger )
if err == nil {
logger . Debug ( "Successfully connected to Postgres" )
} else {
logger . Debug ( "Failed connecting to Postgres" , "err" , err )
}
return endpoint , err
}
func generateConnectionString ( datasource * models . DataSource ) string {
sslmode := datasource . JsonData . Get ( "sslmode" ) . MustString ( "verify-full" )
func generateConnectionString ( datasource * models . DataSource , logger log . Logger ) ( string , error ) {
sslMode := strings . TrimSpace ( strings . ToLower ( datasource . JsonData . Get ( "sslmode" ) . MustString ( "verify-full" ) ) )
isSSLDisabled := sslMode == "disable"
// Always pass SSL mode
sslOpts := fmt . Sprintf ( "sslmode=%s" , url . QueryEscape ( sslMode ) )
if isSSLDisabled {
logger . Debug ( "Postgres SSL is disabled" )
} else {
logger . Debug ( "Postgres SSL is enabled" , "sslMode" , sslMode )
// Attach root certificate if provided
if sslRootCert := datasource . JsonData . Get ( "sslRootCertFile" ) . MustString ( "" ) ; sslRootCert != "" {
logger . Debug ( "Setting server root certificate" , "sslRootCert" , sslRootCert )
sslOpts = fmt . Sprintf ( "%s&sslrootcert=%s" , sslOpts , url . QueryEscape ( sslRootCert ) )
}
// Attach client certificate and key if both are provided
sslCert := datasource . JsonData . Get ( "sslCertFile" ) . MustString ( "" )
sslKey := datasource . JsonData . Get ( "sslKeyFile" ) . MustString ( "" )
if sslCert != "" && sslKey != "" {
logger . Debug ( "Setting SSL client auth" , "sslCert" , sslCert , "sslKey" , sslKey )
sslOpts = fmt . Sprintf ( "%s&sslcert=%s&sslkey=%s" , sslOpts , url . QueryEscape ( sslCert ) , url . QueryEscape ( sslKey ) )
} else if sslCert != "" || sslKey != "" {
return "" , fmt . Errorf ( "SSL client certificate and key must both be specified" )
}
}
u := & url . URL {
Scheme : "postgres" ,
User : url . UserPassword ( datasource . User , datasource . DecryptedPassword ( ) ) ,
Host : datasource . Url , Path : datasource . Database ,
RawQuery : "sslmode=" + url . QueryEscape ( sslmode ) ,
RawQuery : sslOpts ,
}
return u . String ( )
return u . String ( ) , nil
}
type postgresQueryResultTransformer struct {