Commit 7126a919 by Arve Knudsen Committed by GitHub

Postgres: Be consistent about TLS/SSL terminology (#30532)

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
parent 6692e1c3
...@@ -62,8 +62,8 @@ func escape(input string) string { ...@@ -62,8 +62,8 @@ func escape(input string) string {
} }
func generateConnectionString(datasource *models.DataSource, logger log.Logger) (string, error) { func generateConnectionString(datasource *models.DataSource, logger log.Logger) (string, error) {
sslMode := strings.TrimSpace(strings.ToLower(datasource.JsonData.Get("sslmode").MustString("verify-full"))) tlsMode := strings.TrimSpace(strings.ToLower(datasource.JsonData.Get("sslmode").MustString("verify-full")))
isSSLDisabled := sslMode == "disable" isTLSDisabled := tlsMode == "disable"
var host string var host string
var port int var port int
...@@ -88,29 +88,29 @@ func generateConnectionString(datasource *models.DataSource, logger log.Logger) ...@@ -88,29 +88,29 @@ func generateConnectionString(datasource *models.DataSource, logger log.Logger)
connStr := fmt.Sprintf("user='%s' password='%s' host='%s' dbname='%s' sslmode='%s'", connStr := fmt.Sprintf("user='%s' password='%s' host='%s' dbname='%s' sslmode='%s'",
escape(datasource.User), escape(datasource.DecryptedPassword()), escape(host), escape(datasource.Database), escape(datasource.User), escape(datasource.DecryptedPassword()), escape(host), escape(datasource.Database),
escape(sslMode)) escape(tlsMode))
if port > 0 { if port > 0 {
connStr += fmt.Sprintf(" port=%d", port) connStr += fmt.Sprintf(" port=%d", port)
} }
if isSSLDisabled { if isTLSDisabled {
logger.Debug("Postgres SSL is disabled") logger.Debug("Postgres TLS/SSL is disabled")
} else { } else {
logger.Debug("Postgres SSL is enabled", "sslMode", sslMode) logger.Debug("Postgres TLS/SSL is enabled", "tlsMode", tlsMode)
// Attach root certificate if provided // Attach root certificate if provided
if sslRootCert := datasource.JsonData.Get("sslRootCertFile").MustString(""); sslRootCert != "" { if tlsRootCert := datasource.JsonData.Get("sslRootCertFile").MustString(""); tlsRootCert != "" {
logger.Debug("Setting server root certificate", "sslRootCert", sslRootCert) logger.Debug("Setting server root certificate", "tlsRootCert", tlsRootCert)
connStr += fmt.Sprintf(" sslrootcert='%s'", sslRootCert) connStr += fmt.Sprintf(" sslrootcert='%s'", tlsRootCert)
} }
// Attach client certificate and key if both are provided // Attach client certificate and key if both are provided
sslCert := datasource.JsonData.Get("sslCertFile").MustString("") tlsCert := datasource.JsonData.Get("sslCertFile").MustString("")
sslKey := datasource.JsonData.Get("sslKeyFile").MustString("") tlsKey := datasource.JsonData.Get("sslKeyFile").MustString("")
if sslCert != "" && sslKey != "" { if tlsCert != "" && tlsKey != "" {
logger.Debug("Setting SSL client auth", "sslCert", sslCert, "sslKey", sslKey) logger.Debug("Setting TLS/SSL client auth", "tlsCert", tlsCert, "tlsKey", tlsKey)
connStr += fmt.Sprintf(" sslcert='%s' sslkey='%s'", sslCert, sslKey) connStr += fmt.Sprintf(" sslcert='%s' sslkey='%s'", tlsCert, tlsKey)
} else if sslCert != "" || sslKey != "" { } else if tlsCert != "" || tlsKey != "" {
return "", fmt.Errorf("SSL client certificate and key must both be specified") return "", fmt.Errorf("TLS/SSL client certificate and key must both be specified")
} }
} }
......
...@@ -36,7 +36,7 @@ func TestGenerateConnectionString(t *testing.T) { ...@@ -36,7 +36,7 @@ func TestGenerateConnectionString(t *testing.T) {
user string user string
password string password string
database string database string
sslMode string tlsMode string
expConnStr string expConnStr string
expErr string expErr string
}{ }{
...@@ -80,20 +80,20 @@ func TestGenerateConnectionString(t *testing.T) { ...@@ -80,20 +80,20 @@ func TestGenerateConnectionString(t *testing.T) {
expConnStr: `user='user' password='p\'\\assword' host='host' dbname='database' sslmode='verify-full'`, expConnStr: `user='user' password='p\'\\assword' host='host' dbname='database' sslmode='verify-full'`,
}, },
{ {
desc: "Custom SSL mode", desc: "Custom TLS/SSL mode",
host: "host", host: "host",
user: "user", user: "user",
password: "password", password: "password",
database: "database", database: "database",
sslMode: "disable", tlsMode: "disable",
expConnStr: "user='user' password='password' host='host' dbname='database' sslmode='disable'", expConnStr: "user='user' password='password' host='host' dbname='database' sslmode='disable'",
}, },
} }
for _, tt := range testCases { for _, tt := range testCases {
t.Run(tt.desc, func(t *testing.T) { t.Run(tt.desc, func(t *testing.T) {
data := map[string]interface{}{} data := map[string]interface{}{}
if tt.sslMode != "" { if tt.tlsMode != "" {
data["sslmode"] = tt.sslMode data["sslmode"] = tt.tlsMode
} }
ds := &models.DataSource{ ds := &models.DataSource{
Url: tt.host, Url: tt.host,
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form max-width-30"> <div class="gf-form max-width-30">
<span class="gf-form-label width-10">Host</span> <span class="gf-form-label width-10">Host</span>
<input type="text" class="gf-form-input" ng-model='ctrl.current.url' placeholder="localhost:5432" bs-typeahead="{{['localhost:5432', 'localhost:5433']}}" required></input> <input type="text" class="gf-form-input" ng-model='ctrl.current.url' placeholder="localhost:5432"
bs-typeahead="{{['localhost:5432', 'localhost:5433']}}" required></input>
</div> </div>
<div class="gf-form max-width-30"> <div class="gf-form max-width-30">
...@@ -28,35 +29,40 @@ ...@@ -28,35 +29,40 @@
</div> </div>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<label class="gf-form-label width-10">SSL Mode</label> <label class="gf-form-label width-10">TLS/SSL Mode</label>
<div class="gf-form-select-wrapper max-width-15 gf-form-select-wrapper--has-help-icon"> <div class="gf-form-select-wrapper max-width-15 gf-form-select-wrapper--has-help-icon">
<select class="gf-form-input" ng-model="ctrl.current.jsonData.sslmode" ng-options="mode for mode in ['disable', 'require', 'verify-ca', 'verify-full']" ng-init="ctrl.current.jsonData.sslmode"></select> <select class="gf-form-input" ng-model="ctrl.current.jsonData.sslmode"
ng-options="mode for mode in ['disable', 'require', 'verify-ca', 'verify-full']"
ng-init="ctrl.current.jsonData.sslmode"></select>
<info-popover mode="right-absolute"> <info-popover mode="right-absolute">
This option determines whether or with what priority a secure SSL (TLS) TCP/IP connection will be negotiated with the server. This option determines whether or with what priority a secure TLS/SSL TCP/IP connection will be negotiated with the server.
</info-popover> </info-popover>
</div> </div>
</div> </div>
<div class="gf-form max-width-30" ng-if="ctrl.current.jsonData.sslmode != 'disable'"> <div class="gf-form max-width-30" ng-if="ctrl.current.jsonData.sslmode != 'disable'">
<span class="gf-form-label width-10">SSL Root Certificate</span> <span class="gf-form-label width-10">TLS/SSL Root Certificate</span>
<input type="text" class="gf-form-input gf-form-input--has-help-icon" ng-model='ctrl.current.jsonData.sslRootCertFile' placeholder="SSL/TLS root cert file"></input> <input type="text" class="gf-form-input gf-form-input--has-help-icon"
ng-model='ctrl.current.jsonData.sslRootCertFile' placeholder="TLS/SSL root cert file"></input>
<info-popover mode="right-absolute"> <info-popover mode="right-absolute">
If the selected SSL mode requires a server root certificate, provide the path to the file here. If the selected TLS/SSL mode requires a server root certificate, provide the path to the file here.
Be sure that the file is readable by the user executing the grafana process. Be sure that the file is readable by the user executing the grafana process.
</info-popover> </info-popover>
</div> </div>
<div class="gf-form max-width-30" ng-if="ctrl.current.jsonData.sslmode != 'disable'"> <div class="gf-form max-width-30" ng-if="ctrl.current.jsonData.sslmode != 'disable'">
<span class="gf-form-label width-10">SSL Client Certificate</span> <span class="gf-form-label width-10">TLS/SSL Client Certificate</span>
<input type="text" class="gf-form-input gf-form-input--has-help-icon" ng-model='ctrl.current.jsonData.sslCertFile' placeholder="SSL/TLS client cert file"></input> <input type="text" class="gf-form-input gf-form-input--has-help-icon" ng-model='ctrl.current.jsonData.sslCertFile'
placeholder="TLS/SSL client cert file"></input>
<info-popover mode="right-absolute"> <info-popover mode="right-absolute">
To authenticate with an SSL/TLS client certificate, provide the path to the file here. To authenticate with an TLS/SSL client certificate, provide the path to the file here.
Be sure that the file is readable by the user executing the grafana process. Be sure that the file is readable by the user executing the grafana process.
</info-popover> </info-popover>
</div> </div>
<div class="gf-form max-width-30" ng-if="ctrl.current.jsonData.sslmode != 'disable'"> <div class="gf-form max-width-30" ng-if="ctrl.current.jsonData.sslmode != 'disable'">
<span class="gf-form-label width-10">SSL Client Key</span> <span class="gf-form-label width-10">TLS/SSL Client Key</span>
<input type="text" class="gf-form-input gf-form-input--has-help-icon" ng-model='ctrl.current.jsonData.sslKeyFile' placeholder="SSL/TLS client key file"></input> <input type="text" class="gf-form-input gf-form-input--has-help-icon" ng-model='ctrl.current.jsonData.sslKeyFile'
placeholder="TLS/SSL client key file"></input>
<info-popover mode="right-absolute"> <info-popover mode="right-absolute">
To authenticate with a client SSL/TLS certificate, provide the path to the corresponding key file here. To authenticate with a client TLS/SSL certificate, provide the path to the corresponding key file here.
Be sure that the file is <i>only</i> readable by the user executing the grafana process. Be sure that the file is <i>only</i> readable by the user executing the grafana process.
</info-popover> </info-popover>
</div> </div>
...@@ -67,7 +73,8 @@ ...@@ -67,7 +73,8 @@
<div class="gf-form-group"> <div class="gf-form-group">
<div class="gf-form max-width-15"> <div class="gf-form max-width-15">
<span class="gf-form-label width-7">Max open</span> <span class="gf-form-label width-7">Max open</span>
<input type="number" min="0" class="gf-form-input gf-form-input--has-help-icon" ng-model="ctrl.current.jsonData.maxOpenConns" placeholder="unlimited"></input> <input type="number" min="0" class="gf-form-input gf-form-input--has-help-icon"
ng-model="ctrl.current.jsonData.maxOpenConns" placeholder="unlimited"></input>
<info-popover mode="right-absolute"> <info-popover mode="right-absolute">
The maximum number of open connections to the database. If <i>Max idle connections</i> is greater than 0 and the The maximum number of open connections to the database. If <i>Max idle connections</i> is greater than 0 and the
<i>Max open connections</i> is less than <i>Max idle connections</i>, then <i>Max idle connections</i> will be <i>Max open connections</i> is less than <i>Max idle connections</i>, then <i>Max idle connections</i> will be
...@@ -77,7 +84,8 @@ ...@@ -77,7 +84,8 @@
</div> </div>
<div class="gf-form max-width-15"> <div class="gf-form max-width-15">
<span class="gf-form-label width-7">Max idle</span> <span class="gf-form-label width-7">Max idle</span>
<input type="number" min="0" class="gf-form-input gf-form-input--has-help-icon" ng-model="ctrl.current.jsonData.maxIdleConns" placeholder="2"></input> <input type="number" min="0" class="gf-form-input gf-form-input--has-help-icon"
ng-model="ctrl.current.jsonData.maxIdleConns" placeholder="2"></input>
<info-popover mode="right-absolute"> <info-popover mode="right-absolute">
The maximum number of connections in the idle connection pool. If <i>Max open connections</i> is greater than 0 but The maximum number of connections in the idle connection pool. If <i>Max open connections</i> is greater than 0 but
less than the <i>Max idle connections</i>, then the <i>Max idle connections</i> will be reduced to match the less than the <i>Max idle connections</i>, then the <i>Max idle connections</i> will be reduced to match the
...@@ -86,7 +94,8 @@ ...@@ -86,7 +94,8 @@
</div> </div>
<div class="gf-form max-width-15"> <div class="gf-form max-width-15">
<span class="gf-form-label width-7">Max lifetime</span> <span class="gf-form-label width-7">Max lifetime</span>
<input type="number" min="0" class="gf-form-input gf-form-input--has-help-icon" ng-model="ctrl.current.jsonData.connMaxLifetime" placeholder="14400"></input> <input type="number" min="0" class="gf-form-input gf-form-input--has-help-icon"
ng-model="ctrl.current.jsonData.connMaxLifetime" placeholder="14400"></input>
<info-popover mode="right-absolute"> <info-popover mode="right-absolute">
The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever. The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever.
</info-popover> </info-popover>
...@@ -104,11 +113,13 @@ ...@@ -104,11 +113,13 @@
</info-popover> </info-popover>
</span> </span>
<span class="gf-form-select-wrapper"> <span class="gf-form-select-wrapper">
<select class="gf-form-input gf-size-auto" ng-model="ctrl.current.jsonData.postgresVersion" ng-options="f.value as f.name for f in ctrl.postgresVersions"></select> <select class="gf-form-input gf-size-auto" ng-model="ctrl.current.jsonData.postgresVersion"
ng-options="f.value as f.name for f in ctrl.postgresVersions"></select>
</span> </span>
</div> </div>
<div class="gf-form"> <div class="gf-form">
<gf-form-switch class="gf-form" label="TimescaleDB" label-class="width-9" checked="ctrl.current.jsonData.timescaledb" switch-class="max-width-6"></gf-form-switch> <gf-form-switch class="gf-form" label="TimescaleDB" label-class="width-9"
checked="ctrl.current.jsonData.timescaledb" switch-class="max-width-6"></gf-form-switch>
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.toggleTimescaleDBHelp()"> <label class="gf-form-label query-keyword pointer" ng-click="ctrl.toggleTimescaleDBHelp()">
Help&nbsp; Help&nbsp;
<icon name="'angle-down'" ng-show="ctrl.showTimescaleDBHelp"></icon> <icon name="'angle-down'" ng-show="ctrl.showTimescaleDBHelp"></icon>
...@@ -133,17 +144,17 @@ ...@@ -133,17 +144,17 @@
</info-popover> </info-popover>
</div> </div>
</div> </div>
<div class="grafana-info-box alert alert-info" ng-show="ctrl.showTimescaleDBHelp"> <div class="grafana-info-box alert alert-info" ng-show="ctrl.showTimescaleDBHelp">
<div class="alert-body"> <div class="alert-body">
<p> <p>
<a href="https://github.com/timescale/timescaledb" class="pointer" target="_blank">TimescaleDB</a> is a time-series database built as a PostgreSQL extension. If enabled, Grafana will use <code>time_bucket</code> in the <code>$__timeGroup</code> macro and display TimescaleDB specific aggregate functions in the query builder. <a href="https://github.com/timescale/timescaledb" class="pointer" target="_blank">TimescaleDB</a> is a
time-series database built as a PostgreSQL extension. If enabled, Grafana will use <code>time_bucket</code> in
the <code>$__timeGroup</code> macro and display TimescaleDB specific aggregate functions in the query builder.
</p> </p>
</div> </div>
</div>
</div> </div>
</div>
<div class="gf-form-group"> <div class="gf-form-group">
<div class="grafana-info-box"> <div class="grafana-info-box">
<h5>User Permission</h5> <h5>User Permission</h5>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment