mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 02:40:26 -06:00
82 lines
2.2 KiB
Go
82 lines
2.2 KiB
Go
package proxy
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"errors"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"golang.org/x/net/proxy"
|
|
)
|
|
|
|
// NewSecureSocksHTTPProxy takes a http.DefaultTransport and wraps it in a socks5 proxy with TLS
|
|
func NewSecureSocksHTTPProxy(cfg *setting.SecureSocksDSProxySettings, transport *http.Transport) error {
|
|
dialSocksProxy, err := NewSecureSocksProxyContextDialer(cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
contextDialer, ok := dialSocksProxy.(proxy.ContextDialer)
|
|
if !ok {
|
|
return errors.New("unable to cast socks proxy dialer to context proxy dialer")
|
|
}
|
|
|
|
transport.DialContext = contextDialer.DialContext
|
|
return nil
|
|
}
|
|
|
|
// NewSecureSocksProxyContextDialer returns a proxy context dialer that will wrap connections in a secure socks proxy
|
|
func NewSecureSocksProxyContextDialer(cfg *setting.SecureSocksDSProxySettings) (proxy.Dialer, error) {
|
|
certPool := x509.NewCertPool()
|
|
for _, rootCAFile := range strings.Split(cfg.RootCA, " ") {
|
|
// nolint:gosec
|
|
// The gosec G304 warning can be ignored because `rootCAFile` comes from config ini.
|
|
pem, err := os.ReadFile(rootCAFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !certPool.AppendCertsFromPEM(pem) {
|
|
return nil, errors.New("failed to append CA certificate " + rootCAFile)
|
|
}
|
|
}
|
|
|
|
cert, err := tls.LoadX509KeyPair(cfg.ClientCert, cfg.ClientKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tlsDialer := &tls.Dialer{
|
|
Config: &tls.Config{
|
|
Certificates: []tls.Certificate{cert},
|
|
ServerName: cfg.ServerName,
|
|
RootCAs: certPool,
|
|
},
|
|
}
|
|
dialSocksProxy, err := proxy.SOCKS5("tcp", cfg.ProxyAddress, nil, tlsDialer)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return dialSocksProxy, nil
|
|
}
|
|
|
|
// SecureSocksProxyEnabledOnDS checks the datasource json data to see if the secure socks proxy is enabled on it
|
|
func SecureSocksProxyEnabledOnDS(opts sdkhttpclient.Options) bool {
|
|
jsonData := backend.JSONDataFromHTTPClientOptions(opts)
|
|
res, enabled := jsonData["enableSecureSocksProxy"]
|
|
if !enabled {
|
|
return false
|
|
}
|
|
|
|
if val, ok := res.(bool); ok {
|
|
return val
|
|
}
|
|
|
|
return false
|
|
}
|