mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 10:50:37 -06:00
4f3856adfb
I renamed `tlsAuth` to `tlsClientAuth` to better describe the fact that this variable is used to enable TLS client authentication (as opposed to server authentication) in c04d95f35. However, changing the name breaks backwards compatibility for existing installations using this feature and Grafana does not have a standardised way of migrating changes in the schema: https://github.com/grafana/grafana/pull/9377#issuecomment-333063543 For reasons of expediency given the severity of the bug (not verifying TLS), keep the old name.
100 lines
2.2 KiB
Go
100 lines
2.2 KiB
Go
package models
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"errors"
|
|
"net"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type proxyTransportCache struct {
|
|
cache map[int64]cachedTransport
|
|
sync.Mutex
|
|
}
|
|
|
|
type cachedTransport struct {
|
|
updated time.Time
|
|
|
|
*http.Transport
|
|
}
|
|
|
|
var ptc = proxyTransportCache{
|
|
cache: make(map[int64]cachedTransport),
|
|
}
|
|
|
|
func (ds *DataSource) GetHttpClient() (*http.Client, error) {
|
|
transport, err := ds.GetHttpTransport()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &http.Client{
|
|
Timeout: time.Duration(30 * time.Second),
|
|
Transport: transport,
|
|
}, nil
|
|
}
|
|
|
|
func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
|
ptc.Lock()
|
|
defer ptc.Unlock()
|
|
|
|
if t, present := ptc.cache[ds.Id]; present && ds.Updated.Equal(t.updated) {
|
|
return t.Transport, nil
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
transport := &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: tlsSkipVerify,
|
|
Renegotiation: tls.RenegotiateFreelyAsClient,
|
|
},
|
|
Proxy: http.ProxyFromEnvironment,
|
|
Dial: (&net.Dialer{
|
|
Timeout: 30 * time.Second,
|
|
KeepAlive: 30 * time.Second,
|
|
DualStack: true,
|
|
}).Dial,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
MaxIdleConns: 100,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
}
|
|
|
|
if tlsClientAuth || tlsAuthWithCACert {
|
|
decrypted := ds.SecureJsonData.Decrypt()
|
|
if tlsAuthWithCACert && len(decrypted["tlsCACert"]) > 0 {
|
|
caPool := x509.NewCertPool()
|
|
ok := caPool.AppendCertsFromPEM([]byte(decrypted["tlsCACert"]))
|
|
if !ok {
|
|
return nil, errors.New("Failed to parse TLS CA PEM certificate")
|
|
}
|
|
transport.TLSClientConfig.RootCAs = caPool
|
|
}
|
|
|
|
if tlsClientAuth {
|
|
cert, err := tls.X509KeyPair([]byte(decrypted["tlsClientCert"]), []byte(decrypted["tlsClientKey"]))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
|
|
}
|
|
}
|
|
|
|
ptc.cache[ds.Id] = cachedTransport{
|
|
Transport: transport,
|
|
updated: ds.Updated,
|
|
}
|
|
|
|
return transport, nil
|
|
}
|