Browse Source

Always verify TLS unless explicitly told otherwise

TLS was not being verified in a number of places:

- connections to grafana.com

- connections to OAuth providers when TLS client authentication was
  enabled

- connections to self-hosted Grafana installations when using the CLI
  tool

TLS should always be verified unless the user explicitly enables an
option to skip verification.

Removes some instances where `InsecureSkipVerify` is explicitly set to
`false`, the default, to help avoid confusion and make it more difficult
to regress on this fix by accident.

Adds a `--insecure` flag to `grafana-cli` to skip TLS verification.

Adds a `tls_skip_verify_insecure` setting for OAuth.

Adds a `app_tls_skip_verify_insecure` setting under a new `[plugins]`
section.

I'm not super happy with the way the global setting is used by
`pkg/api/app_routes.go` but that seems to be the existing pattern used.
Matt Bostock 8 years ago
parent
commit
16c5d0e4b7

+ 16 - 13
pkg/api/app_routes.go

@@ -13,24 +13,27 @@ import (
 	"github.com/grafana/grafana/pkg/middleware"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/plugins"
+	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/util"
 )
 
-var pluginProxyTransport = &http.Transport{
-	TLSClientConfig: &tls.Config{
-		InsecureSkipVerify: true,
-		Renegotiation:      tls.RenegotiateFreelyAsClient,
-	},
-	Proxy: http.ProxyFromEnvironment,
-	Dial: (&net.Dialer{
-		Timeout:   30 * time.Second,
-		KeepAlive: 30 * time.Second,
-		DualStack: true,
-	}).Dial,
-	TLSHandshakeTimeout: 10 * time.Second,
-}
+var pluginProxyTransport *http.Transport
 
 func InitAppPluginRoutes(r *macaron.Macaron) {
+	pluginProxyTransport = &http.Transport{
+		TLSClientConfig: &tls.Config{
+			InsecureSkipVerify: setting.PluginAppsSkipVerifyTLS,
+			Renegotiation:      tls.RenegotiateFreelyAsClient,
+		},
+		Proxy: http.ProxyFromEnvironment,
+		Dial: (&net.Dialer{
+			Timeout:   30 * time.Second,
+			KeepAlive: 30 * time.Second,
+			DualStack: true,
+		}).Dial,
+		TLSHandshakeTimeout: 10 * time.Second,
+	}
+
 	for _, plugin := range plugins.Apps {
 		for _, route := range plugin.Routes {
 			url := util.JoinUrlFragments("/api/plugin-proxy/"+plugin.Id, route.Path)

+ 1 - 3
pkg/api/grafana_com_proxy.go

@@ -1,7 +1,6 @@
 package api
 
 import (
-	"crypto/tls"
 	"net"
 	"net/http"
 	"net/http/httputil"
@@ -14,8 +13,7 @@ import (
 )
 
 var grafanaComProxyTransport = &http.Transport{
-	TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
-	Proxy:           http.ProxyFromEnvironment,
+	Proxy: http.ProxyFromEnvironment,
 	Dial: (&net.Dialer{
 		Timeout:   30 * time.Second,
 		KeepAlive: 30 * time.Second,

+ 1 - 1
pkg/api/login_oauth.go

@@ -97,7 +97,7 @@ func OAuthLogin(ctx *middleware.Context) {
 
 		tr := &http.Transport{
 			TLSClientConfig: &tls.Config{
-				InsecureSkipVerify: true,
+				InsecureSkipVerify: setting.OAuthService.OAuthInfos[name].TlsSkipVerify,
 				Certificates:       []tls.Certificate{cert},
 				RootCAs:            caCertPool,
 			},

+ 8 - 2
pkg/cmd/grafana-cli/main.go

@@ -17,8 +17,6 @@ var version = "master"
 func main() {
 	setupLogging()
 
-	services.Init(version)
-
 	app := cli.NewApp()
 	app.Name = "Grafana cli"
 	app.Usage = ""
@@ -44,12 +42,20 @@ func main() {
 			Value:  "",
 			EnvVar: "GF_PLUGIN_URL",
 		},
+		cli.BoolFlag{
+			Name:  "insecure",
+			Usage: "Skip TLS verification (insecure)",
+		},
 		cli.BoolFlag{
 			Name:  "debug, d",
 			Usage: "enable debug logging",
 		},
 	}
 
+	app.Before = func(c *cli.Context) error {
+		services.Init(version, c.GlobalBool("insecure"))
+		return nil
+	}
 	app.Commands = commands.Commands
 	app.CommandNotFound = cmdNotFound
 

+ 4 - 3
pkg/cmd/grafana-cli/services/services.go

@@ -22,7 +22,7 @@ var (
 	grafanaVersion string
 )
 
-func Init(version string) {
+func Init(version string, skipTLSVerify bool) {
 	grafanaVersion = version
 
 	tr := &http.Transport{
@@ -36,8 +36,9 @@ func Init(version string) {
 		IdleConnTimeout:       90 * time.Second,
 		TLSHandshakeTimeout:   10 * time.Second,
 		ExpectContinueTimeout: 1 * time.Second,
-
-		TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
+		TLSClientConfig: &tls.Config{
+			InsecureSkipVerify: skipTLSVerify,
+		},
 	}
 
 	HttpClient = http.Client{

+ 6 - 0
pkg/setting/setting.go

@@ -122,6 +122,9 @@ var (
 	// Basic Auth
 	BasicAuthEnabled bool
 
+	// Plugin settings
+	PluginAppsSkipVerifyTLS bool
+
 	// Session settings.
 	SessionOptions session.Options
 
@@ -560,6 +563,9 @@ func NewConfigContext(args *CommandLineArgs) error {
 	authBasic := Cfg.Section("auth.basic")
 	BasicAuthEnabled = authBasic.Key("enabled").MustBool(true)
 
+	// global plugin settings
+	PluginAppsSkipVerifyTLS = Cfg.Section("plugins").Key("app_tls_skip_verify_insecure").MustBool(false)
+
 	// PhantomJS rendering
 	ImagesDir = filepath.Join(DataPath, "png")
 	PhantomDir = filepath.Join(HomePath, "vendor/phantomjs")

+ 1 - 0
pkg/setting/setting_oauth.go

@@ -13,6 +13,7 @@ type OAuthInfo struct {
 	TlsClientCert          string
 	TlsClientKey           string
 	TlsClientCa            string
+	TlsSkipVerify          bool
 }
 
 type OAuther struct {

+ 1 - 0
pkg/social/social.go

@@ -66,6 +66,7 @@ func NewOAuthService() {
 			TlsClientCert:  sec.Key("tls_client_cert").String(),
 			TlsClientKey:   sec.Key("tls_client_key").String(),
 			TlsClientCa:    sec.Key("tls_client_ca").String(),
+			TlsSkipVerify:  sec.Key("tls_skip_verify_insecure").MustBool(),
 		}
 
 		if !info.Enabled {