mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #14888 from bugficks/8570-mysql-ssl-datasource
MySQL SSL CA in datasource connector
This commit is contained in:
commit
75f89ecf1f
@ -46,19 +46,16 @@ func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
|||||||
return t.Transport, nil
|
return t.Transport, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsSkipVerify, tlsClientAuth, tlsAuthWithCACert bool
|
tlsConfig, err := ds.GetTLSConfig()
|
||||||
if ds.JsonData != nil {
|
if err != nil {
|
||||||
tlsClientAuth = ds.JsonData.Get("tlsAuth").MustBool(false)
|
return nil, err
|
||||||
tlsAuthWithCACert = ds.JsonData.Get("tlsAuthWithCACert").MustBool(false)
|
|
||||||
tlsSkipVerify = ds.JsonData.Get("tlsSkipVerify").MustBool(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlsConfig.Renegotiation = tls.RenegotiateFreelyAsClient
|
||||||
|
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: tlsConfig,
|
||||||
InsecureSkipVerify: tlsSkipVerify,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
Renegotiation: tls.RenegotiateFreelyAsClient,
|
|
||||||
},
|
|
||||||
Proxy: http.ProxyFromEnvironment,
|
|
||||||
Dial: (&net.Dialer{
|
Dial: (&net.Dialer{
|
||||||
Timeout: 30 * time.Second,
|
Timeout: 30 * time.Second,
|
||||||
KeepAlive: 30 * time.Second,
|
KeepAlive: 30 * time.Second,
|
||||||
@ -70,6 +67,26 @@ func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
|||||||
IdleConnTimeout: 90 * time.Second,
|
IdleConnTimeout: 90 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptc.cache[ds.Id] = cachedTransport{
|
||||||
|
Transport: transport,
|
||||||
|
updated: ds.Updated,
|
||||||
|
}
|
||||||
|
|
||||||
|
return transport, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *DataSource) GetTLSConfig() (*tls.Config, error) {
|
||||||
|
var tlsSkipVerify, tlsClientAuth, tlsAuthWithCACert bool
|
||||||
|
if ds.JsonData != nil {
|
||||||
|
tlsClientAuth = ds.JsonData.Get("tlsAuth").MustBool(false)
|
||||||
|
tlsAuthWithCACert = ds.JsonData.Get("tlsAuthWithCACert").MustBool(false)
|
||||||
|
tlsSkipVerify = ds.JsonData.Get("tlsSkipVerify").MustBool(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
InsecureSkipVerify: tlsSkipVerify,
|
||||||
|
}
|
||||||
|
|
||||||
if tlsClientAuth || tlsAuthWithCACert {
|
if tlsClientAuth || tlsAuthWithCACert {
|
||||||
decrypted := ds.SecureJsonData.Decrypt()
|
decrypted := ds.SecureJsonData.Decrypt()
|
||||||
if tlsAuthWithCACert && len(decrypted["tlsCACert"]) > 0 {
|
if tlsAuthWithCACert && len(decrypted["tlsCACert"]) > 0 {
|
||||||
@ -78,7 +95,7 @@ func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("Failed to parse TLS CA PEM certificate")
|
return nil, errors.New("Failed to parse TLS CA PEM certificate")
|
||||||
}
|
}
|
||||||
transport.TLSClientConfig.RootCAs = caPool
|
tlsConfig.RootCAs = caPool
|
||||||
}
|
}
|
||||||
|
|
||||||
if tlsClientAuth {
|
if tlsClientAuth {
|
||||||
@ -86,14 +103,9 @@ func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
|
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptc.cache[ds.Id] = cachedTransport{
|
return tlsConfig, nil
|
||||||
Transport: transport,
|
|
||||||
updated: ds.Updated,
|
|
||||||
}
|
|
||||||
|
|
||||||
return transport, nil
|
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,18 @@ func newMysqlQueryEndpoint(datasource *models.DataSource) (tsdb.TsdbQueryEndpoin
|
|||||||
datasource.Url,
|
datasource.Url,
|
||||||
datasource.Database,
|
datasource.Database,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tlsConfig, err := datasource.GetTLSConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tlsConfig.RootCAs != nil || len(tlsConfig.Certificates) > 0 {
|
||||||
|
tlsConfigString := fmt.Sprintf("ds%d", datasource.Id)
|
||||||
|
mysql.RegisterTLSConfig(tlsConfigString, tlsConfig)
|
||||||
|
cnnstr += "&tls=" + tlsConfigString
|
||||||
|
}
|
||||||
|
|
||||||
logger.Debug("getEngine", "connection", cnnstr)
|
logger.Debug("getEngine", "connection", cnnstr)
|
||||||
|
|
||||||
config := tsdb.SqlQueryEndpointConfiguration{
|
config := tsdb.SqlQueryEndpointConfiguration{
|
||||||
|
@ -12,3 +12,4 @@ import './manage-dashboards';
|
|||||||
import './teams/CreateTeamCtrl';
|
import './teams/CreateTeamCtrl';
|
||||||
import './profile/all';
|
import './profile/all';
|
||||||
import './datasources/settings/HttpSettingsCtrl';
|
import './datasources/settings/HttpSettingsCtrl';
|
||||||
|
import './datasources/settings/TlsAuthSettingsCtrl';
|
||||||
|
@ -101,53 +101,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form-group" ng-if="(current.jsonData.tlsAuth || current.jsonData.tlsAuthWithCACert) && current.access=='proxy'">
|
<datasource-tls-auth-settings current="current" ng-if="(current.jsonData.tlsAuth || current.jsonData.tlsAuthWithCACert) && current.access=='proxy'">
|
||||||
<div class="gf-form">
|
</datasource-tls-auth-settings>
|
||||||
<h6>TLS Auth Details</h6>
|
|
||||||
<info-popover mode="header">TLS Certs are encrypted and stored in the Grafana database.</info-popover>
|
|
||||||
</div>
|
|
||||||
<div ng-if="current.jsonData.tlsAuthWithCACert">
|
|
||||||
<div class="gf-form-inline">
|
|
||||||
<div class="gf-form gf-form--v-stretch">
|
|
||||||
<label class="gf-form-label width-7">CA Cert</label>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsCACert">
|
|
||||||
<textarea rows="7" class="gf-form-input gf-form-textarea" ng-model="current.secureJsonData.tlsCACert" placeholder="Begins with -----BEGIN CERTIFICATE-----"></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form" ng-if="current.secureJsonFields.tlsCACert">
|
|
||||||
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
|
|
||||||
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsCACert = false">reset</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-if="current.jsonData.tlsAuth">
|
|
||||||
<div class="gf-form-inline">
|
|
||||||
<div class="gf-form gf-form--v-stretch">
|
|
||||||
<label class="gf-form-label width-7">Client Cert</label>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsClientCert">
|
|
||||||
<textarea rows="7" class="gf-form-input gf-form-textarea" ng-model="current.secureJsonData.tlsClientCert" placeholder="Begins with -----BEGIN CERTIFICATE-----" required></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form" ng-if="current.secureJsonFields.tlsClientCert">
|
|
||||||
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
|
|
||||||
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsClientCert = false">reset</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form-inline">
|
|
||||||
<div class="gf-form gf-form--v-stretch">
|
|
||||||
<label class="gf-form-label width-7">Client Key</label>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsClientKey">
|
|
||||||
<textarea rows="7" class="gf-form-input gf-form-textarea" ng-model="current.secureJsonData.tlsClientKey" placeholder="Begins with -----BEGIN RSA PRIVATE KEY-----" required></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form" ng-if="current.secureJsonFields.tlsClientKey">
|
|
||||||
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
|
|
||||||
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsClientKey = false">reset</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
|||||||
|
<div class="gf-form-group">
|
||||||
|
<div class="gf-form">
|
||||||
|
<h6>TLS Auth Details</h6>
|
||||||
|
<info-popover mode="header">TLS Certs are encrypted and stored in the Grafana database.</info-popover>
|
||||||
|
</div>
|
||||||
|
<div ng-if="current.jsonData.tlsAuthWithCACert">
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form gf-form--v-stretch"><label class="gf-form-label width-7">CA Cert</label></div>
|
||||||
|
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsCACert">
|
||||||
|
<textarea
|
||||||
|
rows="7"
|
||||||
|
class="gf-form-input gf-form-textarea"
|
||||||
|
ng-model="current.secureJsonData.tlsCACert"
|
||||||
|
placeholder="Begins with -----BEGIN CERTIFICATE-----"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form" ng-if="current.secureJsonFields.tlsCACert">
|
||||||
|
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured" />
|
||||||
|
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsCACert = false">reset</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="current.jsonData.tlsAuth">
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form gf-form--v-stretch"><label class="gf-form-label width-7">Client Cert</label></div>
|
||||||
|
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsClientCert">
|
||||||
|
<textarea
|
||||||
|
rows="7"
|
||||||
|
class="gf-form-input gf-form-textarea"
|
||||||
|
ng-model="current.secureJsonData.tlsClientCert"
|
||||||
|
placeholder="Begins with -----BEGIN CERTIFICATE-----"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form" ng-if="current.secureJsonFields.tlsClientCert">
|
||||||
|
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured" />
|
||||||
|
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsClientCert = false"
|
||||||
|
>reset</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form gf-form--v-stretch"><label class="gf-form-label width-7">Client Key</label></div>
|
||||||
|
<div class="gf-form gf-form--grow" ng-if="!current.secureJsonFields.tlsClientKey">
|
||||||
|
<textarea
|
||||||
|
rows="7"
|
||||||
|
class="gf-form-input gf-form-textarea"
|
||||||
|
ng-model="current.secureJsonData.tlsClientKey"
|
||||||
|
placeholder="Begins with -----BEGIN RSA PRIVATE KEY-----"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form" ng-if="current.secureJsonFields.tlsClientKey">
|
||||||
|
<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured" />
|
||||||
|
<a class="btn btn-secondary gf-form-btn" href="#" ng-click="current.secureJsonFields.tlsClientKey = false">reset</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,10 @@
|
|||||||
|
import { coreModule } from 'app/core/core';
|
||||||
|
|
||||||
|
coreModule.directive('datasourceTlsAuthSettings', () => {
|
||||||
|
return {
|
||||||
|
scope: {
|
||||||
|
current: '=',
|
||||||
|
},
|
||||||
|
templateUrl: 'public/app/features/datasources/partials/tls_auth_settings.html',
|
||||||
|
};
|
||||||
|
});
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<h3 class="page-heading">MySQL Connection</h3>
|
<h3 class="page-heading">MySQL Connection</h3>
|
||||||
|
|
||||||
<div class="gf-form-group">
|
<div class="gf-form-group">
|
||||||
@ -22,7 +21,23 @@
|
|||||||
<input type="password" class="gf-form-input" ng-model='ctrl.current.password' placeholder="password"></input>
|
<input type="password" class="gf-form-input" ng-model='ctrl.current.password' placeholder="password"></input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="gf-form-group">
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<gf-form-checkbox class="gf-form" label="TLS Client Auth" label-class="width-10"
|
||||||
|
checked="ctrl.current.jsonData.tlsAuth" switch-class="max-width-6"></gf-form-checkbox>
|
||||||
|
<gf-form-checkbox class="gf-form" label="With CA Cert" tooltip="Needed for
|
||||||
|
verifing self-signed TLS Certs" checked="ctrl.current.jsonData.tlsAuthWithCACert" label-class="width-11"
|
||||||
|
switch-class="max-width-6"></gf-form-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<gf-form-checkbox class="gf-form" label="Skip TLS Verify" label-class="width-10"
|
||||||
|
checked="ctrl.current.jsonData.tlsSkipVerify" switch-class="max-width-6"></gf-form-checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<datasource-tls-auth-settings current="ctrl.current" ng-if="(ctrl.current.jsonData.tlsAuth || ctrl.current.jsonData.tlsAuthWithCACert)">
|
||||||
|
</datasource-tls-auth-settings>
|
||||||
|
|
||||||
<b>Connection limits</b>
|
<b>Connection limits</b>
|
||||||
|
|
||||||
@ -84,4 +99,3 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user