Pārlūkot izejas kodu

feat(httpsettings): add tls auth option

- Three text areas where the user can paste
in the CA Cert (optional), Client Cert
and Client Key.

- Tooltips for Auth checkboxes with brief
descriptions of what With Credentials and
With CA Cert are.

- Adds popover for TLS Auth header too.

- Aligns gf-form elements as labels and
checkboxes were not aligned before.

- Makes CA Cert optional as it is only
needed for self-signed certs.
Daniel Lee 9 gadi atpakaļ
vecāks
revīzija
0618122bcd

+ 5 - 5
pkg/api/dataproxy.go

@@ -31,18 +31,18 @@ func DataProxyTransport(ds *m.DataSource) (*http.Transport, error) {
 		TLSHandshakeTimeout: 10 * time.Second,
 	}
 
-	var tlsAuth bool
-	var err error
+	var tlsAuth, tlsAuthWithCACert bool
 	if ds.JsonData != nil {
-		tlsAuth, err = ds.JsonData.Get("tlsAuth").Bool()
+		tlsAuth = ds.JsonData.Get("tlsAuth").MustBool(false)
+		tlsAuthWithCACert = ds.JsonData.Get("tlsAuthWithCACert").MustBool(false)
 	}
 
-	if err == nil && tlsAuth {
+	if tlsAuth {
 		transport.TLSClientConfig.InsecureSkipVerify = false
 
 		decrypted := ds.SecureJsonData.Decrypt()
 
-		if len(decrypted["tlsCACert"]) > 0 {
+		if tlsAuthWithCACert && len(decrypted["tlsCACert"]) > 0 {
 			caPool := x509.NewCertPool()
 			ok := caPool.AppendCertsFromPEM([]byte(decrypted["tlsCACert"]))
 			if ok {

+ 99 - 56
public/app/features/plugins/partials/ds_http_settings.html

@@ -1,60 +1,69 @@
 
 
 <div class="gf-form-group">
-	<h3 class="page-heading">Http settings</h3>
+  <h3 class="page-heading">Http settings</h3>
+  <div class="gf-form-group">
+    <div class="gf-form-inline">
+      <div class="gf-form max-width-30">
+        <span class="gf-form-label width-7">Url</span>
+        <input class="gf-form-input" type="text"
+              ng-model='current.url' placeholder="{{suggestUrl}}"
+              bs-typeahead="getSuggestUrls"  min-length="0"
+              ng-pattern="/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/" required></input>
+        <info-popover mode="right-absolute">
+          <p>Specify a complete HTTP url (for example http://your_server:8080)</p>
+          <span ng-show="current.access === 'direct'">
+            Your access method is <em>Direct</em>, this means the url
+            needs to be accessable from the browser.
+          </span>
+          <span ng-show="current.access === 'proxy'">
+            Your access method is currently <em>Proxy</em>, this means the url
+            needs to be accessable from the grafana backend.
+          </span>
+        </info-popover>
+      </div>
+    </div>
 
-	<div class="gf-form-inline">
-		<div class="gf-form max-width-30">
-			<span class="gf-form-label width-7">Url</span>
-			<input class="gf-form-input" type="text"
-						 ng-model='current.url' placeholder="{{suggestUrl}}"
-						 bs-typeahead="getSuggestUrls"  min-length="0"
-						 ng-pattern="/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/" required></input>
-			<info-popover mode="right-absolute">
-				<p>Specify a complete HTTP url (for example http://your_server:8080)</p>
-				<span ng-show="current.access === 'direct'">
-					Your access method is <em>Direct</em>, this means the url
-					needs to be accessable from the browser.
-				</span>
-				<span ng-show="current.access === 'proxy'">
-					Your access method is currently <em>Proxy</em>, this means the url
-					needs to be accessable from the grafana backend.
-				</span>
-			</info-popover>
-		</div>
-	</div>
+    <div class="gf-form-inline">
+      <div class="gf-form max-width-30">
+        <span class="gf-form-label width-7">Access</span>
+        <div class="gf-form-select-wrapper gf-form-select-wrapper--has-help-icon max-width-24">
+          <select class="gf-form-input" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select>
+          <info-popover mode="right-absolute">
+            Direct = url is used directly from browser<br>
+            Proxy = Grafana backend will proxy the request
+          </info-popover>
+        </div>
+      </div>
+    </div>
+  </div>
 
-	<div class="gf-form-inline">
-		<div class="gf-form max-width-30">
-			<span class="gf-form-label width-7">Access</span>
-			<div class="gf-form-select-wrapper gf-form-select-wrapper--has-help-icon max-width-24">
-				<select class="gf-form-input" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select>
-				<info-popover mode="right-absolute">
-					Direct = url is used directly from browser<br>
-					Proxy = Grafana backend will proxy the request
-				</info-popover>
-			</div>
-		</div>
-	</div>
+  <h3 class="page-heading">Http Auth</h3>
 
 	<div class="gf-form-inline">
-		<div class="gf-form">
-			<label class="gf-form-label width-7">Http Auth</label>
-		</div>
 		<gf-form-switch class="gf-form"
 									label="Basic Auth"
-				 checked="current.basicAuth" switch-class="max-width-6">
+				 checked="current.basicAuth" label-class="width-8" switch-class="max-width-6">
 		</gf-form-switch>
 		<gf-form-switch class="gf-form"
-									label="With Credentials"
-				 checked="current.withCredentials" switch-class="max-width-6">
-		</gf-form-switch>
-		<gf-form-switch class="gf-form" ng-if="current.access=='proxy'"
-									label="TLS Client Auth"
-				 checked="current.tlsAuth" switch-class="max-width-6">
+									label="With Credentials" tooltip="Whether credentials such as cookies or auth headers should be sent with cross-site requests."
+				 checked="current.withCredentials" label-class="width-11" switch-class="max-width-6">
 		</gf-form-switch>
 	</div>
+  <div class="gf-form-inline">
+    <gf-form-switch class="gf-form" ng-if="current.access=='proxy'"
+									label="TLS Client Auth" label-class="width-8"
+				 checked="current.jsonData.tlsAuth" switch-class="max-width-6">
+		</gf-form-switch>
+    <gf-form-switch class="gf-form" ng-if="current.access=='proxy'"
+									label="With CA Cert" tooltip="Optional. Needed for self-signed TLS Certs."
+				 checked="current.jsonData.tlsAuthWithCACert" label-class="width-11" switch-class="max-width-6">
+		</gf-form-switch>
+  </div>
+</div>
 
+<div class="gf-form-group" ng-if="current.basicAuth">
+  <h6>Basic Auth Details</h6>
 	<div class="gf-form" ng-if="current.basicAuth">
 		<span class="gf-form-label width-7">
 			User
@@ -62,25 +71,59 @@
 		<input class="gf-form-input max-width-21" type="text"  ng-model='current.basicAuthUser' placeholder="user" required></input>
 	</div>
 
-	<div class="gf-form" ng-if="current.basicAuth">
+	<div class="gf-form">
 		<span class="gf-form-label width-7">
 			Password
 		</span>
 		<input class="gf-form-input max-width-21" type="password" ng-model='current.basicAuthPassword' placeholder="password" required></input>
 	</div>
+</div>
 
-	<div class="gf-form" ng-if="current.tlsAuth && current.access=='proxy'">
-		<span class="gf-form-label width-7">
-			Client Cert
-		</span>
-		<input class="gf-form-input max-width-23" type="text"  ng-model='current.tlsClientCert' placeholder="cert path" required></input>
-	</div>
+<div class="gf-form-group" ng-if="current.jsonData.tlsAuth && current.access=='proxy'">
+  <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.tlsAuth.tlsCACertSet">
+        <textarea rows="7" class="gf-form-input gf-form-textarea" ng-model="current.secureJsonData.tlsCACert" placeholder="Begins with -----BEGIN CERTIFICATE-----. The CA Certificate is necessary if you are using self-signed certificates."></textarea>
+      </div>
 
-	<div class="gf-form" ng-if="current.tlsAuth && current.access=='proxy'">
-		<span class="gf-form-label width-7">
-			Client Key
-		</span>
-		<input class="gf-form-input max-width-23" type="text" ng-model='current.tlsClientKey' placeholder="key path" required></input>
-	</div>
+      <div class="gf-form" ng-if="current.tlsAuth.tlsCACertSet">
+        <input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
+        <a class="btn btn-secondary gf-form-btn" href="#" ng-if="current.tlsAuth.tlsCACertSet" ng-click="current.tlsAuth.tlsCACertSet = false">reset</a>
+      </div>
+    </div>
+  </div>
+
+  <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.tlsAuth.tlsClientCertSet">
+      <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.tlsAuth.tlsClientCertSet">
+      <input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
+      <a class="btn btn-secondary gf-form-btn" href="#" ng-if="current.tlsAuth.tlsClientCertSet" ng-click="current.tlsAuth.tlsClientCertSet = 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.tlsAuth.tlsClientKeySet">
+      <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.tlsAuth.tlsClientKeySet">
+      <input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
+      <a class="btn btn-secondary gf-form-btn" href="#" ng-if="current.tlsAuth.tlsClientKeySet" ng-click="current.tlsAuth.tlsClientKeySet = false">reset</a>
+    </div>
+  </div>
 </div>
 

+ 8 - 0
public/sass/components/_gf-form.scss

@@ -79,6 +79,10 @@ $gf-form-margin: 0.25rem;
   }
 }
 
+.gf-form-textarea {
+  max-width: 650px;
+}
+
 .gf-form-input {
   display: block;
   width: 100%;
@@ -249,6 +253,10 @@ $gf-form-margin: 0.25rem;
   &--right-normal {
     float: right;
   }
+
+  &--header {
+    margin-bottom: $gf-form-margin
+  }
 }
 
 select.gf-form-input ~ .gf-form-help-icon {