mirror of
https://github.com/grafana/grafana.git
synced 2025-01-26 16:27:02 -06:00
DataSourceSettings: Add servername field to DataSource TLS config (#29279)
* DataSourceSettings: Add servername field to DataSource TLS config A DNS lookup URL can be provided in the DataSource URL field in order to dynamically load balance between multiple instances of a DataSource. When using mutual TLS, Golang's TLS config implementation checks that the certificate's common name (< 1.15) or subject alternative name (>= 1.15) has the same value as the domain being accessed. If the DNS entry is dynamically generated for a specific environment, the certificate cannot be generated with a name matching the dynamic DNS URL. As such, Golang offers a servername field that can be set to overwrite what value is used when checking against the certificate's common name (or subject alternative name). Without this change, Skip TLS Verify must be set to true in order for the DataSource to work, removing some of the benefits gained by using mutual TLS. This commit adds the ability to set Grafana's internal Golang TLS config servername field from the UI or a provisioned DataSource. The servername field is optional and the existing behavior is retained if the field is not set. Co-authored-by: Dana Pruitt <dpruitt@vmware.com> Co-authored-by: Jeremy Alvis <jalvis@pivotal.io> * Update docs with PR review changes Co-authored-by: Jeremy Alvis <jalvis@pivotal.io> Co-authored-by: Dana Pruitt <dpruitt@vmware.com> * Update with additional PR requested changes * Minor updates based on PR change requests Co-authored-by: Dana Pruitt <dpruitt@vmware.com>
This commit is contained in:
parent
ed9076da29
commit
f021f97c31
@ -146,6 +146,7 @@ Since not all datasources have the same configuration settings we only have the
|
||||
| tlsAuth | boolean | _All_ | Enable TLS authentication using client cert configured in secure json data |
|
||||
| tlsAuthWithCACert | boolean | _All_ | Enable TLS authentication using CA cert |
|
||||
| tlsSkipVerify | boolean | _All_ | Controls whether a client verifies the server's certificate chain and host name. |
|
||||
| serverName | string | _All_ | Optional. Controls the server name used for certificate common name/subject alternative name verification. Defaults to using the data source URL. |
|
||||
| graphiteVersion | string | Graphite | Graphite version |
|
||||
| timeInterval | string | Prometheus, Elasticsearch, InfluxDB, MySQL, PostgreSQL and MSSQL | Lowest interval/step value that should be used for this data source. |
|
||||
| httpMode | string | Influxdb | HTTP Method. 'GET', 'POST', defaults to GET |
|
||||
|
@ -25,6 +25,7 @@ const settingsMock: DataSourceSettings<any, any> = {
|
||||
timeInterval: '15s',
|
||||
httpMode: 'GET',
|
||||
keepCookies: ['cookie1', 'cookie2'],
|
||||
serverName: '',
|
||||
},
|
||||
secureJsonData: {
|
||||
password: true,
|
||||
|
@ -5,11 +5,13 @@ import { Tooltip } from '../Tooltip/Tooltip';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
import { CertificationKey } from './CertificationKey';
|
||||
import { HttpSettingsBaseProps } from './types';
|
||||
import { FormField } from '../FormField/FormField';
|
||||
|
||||
export const TLSAuthSettings: React.FC<HttpSettingsBaseProps> = ({ dataSourceConfig, onChange }) => {
|
||||
const hasTLSCACert = dataSourceConfig.secureJsonFields && dataSourceConfig.secureJsonFields.tlsCACert;
|
||||
const hasTLSClientCert = dataSourceConfig.secureJsonFields && dataSourceConfig.secureJsonFields.tlsClientCert;
|
||||
const hasTLSClientKey = dataSourceConfig.secureJsonFields && dataSourceConfig.secureJsonFields.tlsClientKey;
|
||||
const hasServerName = dataSourceConfig.jsonData && dataSourceConfig.jsonData.serverName;
|
||||
|
||||
const onResetClickFactory = (field: string) => (event: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
event.preventDefault();
|
||||
@ -31,6 +33,18 @@ export const TLSAuthSettings: React.FC<HttpSettingsBaseProps> = ({ dataSourceCon
|
||||
});
|
||||
};
|
||||
|
||||
const onServerNameLabelChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
const newJsonData = {
|
||||
...dataSourceConfig.jsonData,
|
||||
serverName: event.currentTarget.value,
|
||||
};
|
||||
|
||||
onChange({
|
||||
...dataSourceConfig,
|
||||
jsonData: newJsonData,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="gf-form-group">
|
||||
<div
|
||||
@ -65,6 +79,16 @@ export const TLSAuthSettings: React.FC<HttpSettingsBaseProps> = ({ dataSourceCon
|
||||
|
||||
{dataSourceConfig.jsonData.tlsAuth && (
|
||||
<>
|
||||
<div className="gf-form">
|
||||
<FormField
|
||||
label="ServerName"
|
||||
labelWidth={7}
|
||||
inputWidth={30}
|
||||
placeholder="domain.example.com"
|
||||
value={hasServerName && dataSourceConfig.jsonData.serverName}
|
||||
onChange={onServerNameLabelChange}
|
||||
/>
|
||||
</div>
|
||||
<CertificationKey
|
||||
hasCert={!!hasTLSClientCert}
|
||||
label="Client Cert"
|
||||
|
@ -208,14 +208,18 @@ func (ds *DataSource) sigV4Middleware(next http.RoundTripper) http.RoundTripper
|
||||
|
||||
func (ds *DataSource) GetTLSConfig() (*tls.Config, error) {
|
||||
var tlsSkipVerify, tlsClientAuth, tlsAuthWithCACert bool
|
||||
var serverName string
|
||||
|
||||
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)
|
||||
serverName = ds.JsonData.Get("serverName").MustString()
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: tlsSkipVerify,
|
||||
ServerName: serverName,
|
||||
}
|
||||
|
||||
if tlsClientAuth || tlsAuthWithCACert {
|
||||
|
@ -129,16 +129,19 @@ func TestDataSourceProxyCache(t *testing.T) {
|
||||
|
||||
json := simplejson.New()
|
||||
json.Set("tlsAuthWithCACert", true)
|
||||
json.Set("serverName", "server-name")
|
||||
|
||||
tlsCaCert, err := util.Encrypt([]byte(caCert), "password")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ds := DataSource{
|
||||
Id: 1,
|
||||
Url: "http://k8s:8001",
|
||||
Type: "Kubernetes",
|
||||
JsonData: json,
|
||||
SecureJsonData: map[string][]byte{"tlsCACert": tlsCaCert},
|
||||
Id: 1,
|
||||
Url: "http://k8s:8001",
|
||||
Type: "Kubernetes",
|
||||
JsonData: json,
|
||||
SecureJsonData: map[string][]byte{
|
||||
"tlsCACert": tlsCaCert,
|
||||
},
|
||||
}
|
||||
|
||||
tr, err := ds.GetHttpTransport()
|
||||
@ -150,6 +153,9 @@ func TestDataSourceProxyCache(t *testing.T) {
|
||||
Convey("Should have a TLS CA configured", func() {
|
||||
So(len(tr.transport.TLSClientConfig.RootCAs.Subjects()), ShouldEqual, 1)
|
||||
})
|
||||
Convey("Should include a server name if one is provided", func() {
|
||||
So(tr.transport.TLSClientConfig.ServerName, ShouldEqual, "server-name")
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When caching a datasource proxy when user skips TLS verification", t, func() {
|
||||
|
Loading…
Reference in New Issue
Block a user