mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Pass PDC file contents in requests (#84783)
* Plugins: Pass PDC file contents in requests * go mod tidy * undo go.mod changes * fix linter * fix tests * undo unnecessary changes * update dep * join with comma * update naming * bump SDK
This commit is contained in:
parent
0b4c81158e
commit
b765c21d4c
8
go.mod
8
go.mod
@ -51,7 +51,7 @@ require (
|
|||||||
github.com/grafana/cuetsy v0.1.11 // @grafana/grafana-as-code
|
github.com/grafana/cuetsy v0.1.11 // @grafana/grafana-as-code
|
||||||
github.com/grafana/grafana-aws-sdk v0.25.0 // @grafana/aws-datasources
|
github.com/grafana/grafana-aws-sdk v0.25.0 // @grafana/aws-datasources
|
||||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.0.1 // @grafana/partner-datasources
|
github.com/grafana/grafana-azure-sdk-go/v2 v2.0.1 // @grafana/partner-datasources
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.216.0 // @grafana/plugins-platform-backend
|
github.com/grafana/grafana-plugin-sdk-go v0.217.0 // @grafana/plugins-platform-backend
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // @grafana/backend-platform
|
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // @grafana/backend-platform
|
||||||
github.com/hashicorp/go-hclog v1.6.2 // @grafana/plugins-platform-backend
|
github.com/hashicorp/go-hclog v1.6.2 // @grafana/plugins-platform-backend
|
||||||
github.com/hashicorp/go-plugin v1.6.0 // @grafana/plugins-platform-backend
|
github.com/hashicorp/go-plugin v1.6.0 // @grafana/plugins-platform-backend
|
||||||
@ -109,7 +109,7 @@ require (
|
|||||||
gopkg.in/mail.v2 v2.3.1 // @grafana/backend-platform
|
gopkg.in/mail.v2 v2.3.1 // @grafana/backend-platform
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // @grafana/alerting-squad-backend
|
gopkg.in/yaml.v3 v3.0.1 // @grafana/alerting-squad-backend
|
||||||
xorm.io/builder v0.3.6 // indirect; @grafana/backend-platform
|
xorm.io/builder v0.3.6 // @grafana/backend-platform
|
||||||
xorm.io/core v0.7.3 // @grafana/backend-platform
|
xorm.io/core v0.7.3 // @grafana/backend-platform
|
||||||
xorm.io/xorm v0.8.2 // @grafana/alerting-squad-backend
|
xorm.io/xorm v0.8.2 // @grafana/alerting-squad-backend
|
||||||
)
|
)
|
||||||
@ -161,7 +161,7 @@ require (
|
|||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-msgpack v0.5.5 // indirect
|
github.com/hashicorp/go-msgpack v0.5.5 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect; @grafana/alerting-squad
|
github.com/hashicorp/go-multierror v1.1.1 // @grafana/alerting-squad
|
||||||
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
|
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
|
||||||
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
||||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||||
@ -317,7 +317,7 @@ require (
|
|||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||||
github.com/grafana/regexp v0.0.0-20221123153739-15dc172cd2db // indirect
|
github.com/grafana/regexp v0.0.0-20221123153739-15dc172cd2db // indirect
|
||||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect; @grafana/alerting-squad-backend
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // @grafana/alerting-squad-backend
|
||||||
github.com/hashicorp/memberlist v0.5.0 // indirect
|
github.com/hashicorp/memberlist v0.5.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/invopop/yaml v0.2.0 // indirect
|
github.com/invopop/yaml v0.2.0 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -2184,8 +2184,8 @@ github.com/grafana/grafana-google-sdk-go v0.1.0/go.mod h1:Vo2TKWfDVmNTELBUM+3lkr
|
|||||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 h1:r+mU5bGMzcXCRVAuOrTn54S80qbfVkvTdUJZfSfTNbs=
|
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 h1:r+mU5bGMzcXCRVAuOrTn54S80qbfVkvTdUJZfSfTNbs=
|
||||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
|
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
|
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.216.0 h1:DftszjdGZM6hikBazyB7CdrhyYOwUct9s5lA/BwSl2c=
|
github.com/grafana/grafana-plugin-sdk-go v0.217.0 h1:oQjq5KRrVrhweXHxFtEMgjv1KW7hujGiRPIYrsPZ9PE=
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.216.0/go.mod h1:FdvSvOliqpVLnytM7e89zCFyYPDE6VOn9SIjVQRvVxM=
|
github.com/grafana/grafana-plugin-sdk-go v0.217.0/go.mod h1:FdvSvOliqpVLnytM7e89zCFyYPDE6VOn9SIjVQRvVxM=
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240226124929-648abdbd0ea4 h1:hpyusz8c3yRFoJPlA0o34rWnsLbaOOBZleqRhFBi5Lg=
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240226124929-648abdbd0ea4 h1:hpyusz8c3yRFoJPlA0o34rWnsLbaOOBZleqRhFBi5Lg=
|
||||||
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240226124929-648abdbd0ea4/go.mod h1:vrRQJuNprTWqwm6JPxHf3BoTJhvO15QMEjQ7Q/YUOnI=
|
github.com/grafana/grafana/pkg/apimachinery v0.0.0-20240226124929-648abdbd0ea4/go.mod h1:vrRQJuNprTWqwm6JPxHf3BoTJhvO15QMEjQ7Q/YUOnI=
|
||||||
github.com/grafana/grafana/pkg/apiserver v0.0.0-20240226124929-648abdbd0ea4 h1:tIbI5zgos92vwJ8lV3zwHwuxkV03GR3FGLkFW9V5LxY=
|
github.com/grafana/grafana/pkg/apiserver v0.0.0-20240226124929-648abdbd0ea4 h1:tIbI5zgos92vwJ8lV3zwHwuxkV03GR3FGLkFW9V5LxY=
|
||||||
|
@ -534,7 +534,7 @@ func (s *Service) httpClientOptions(ctx context.Context, ds *datasources.DataSou
|
|||||||
ClientCfg: &sdkproxy.ClientCfg{
|
ClientCfg: &sdkproxy.ClientCfg{
|
||||||
ClientCert: s.cfg.SecureSocksDSProxy.ClientCert,
|
ClientCert: s.cfg.SecureSocksDSProxy.ClientCert,
|
||||||
ClientKey: s.cfg.SecureSocksDSProxy.ClientKey,
|
ClientKey: s.cfg.SecureSocksDSProxy.ClientKey,
|
||||||
RootCA: s.cfg.SecureSocksDSProxy.RootCA,
|
RootCAs: s.cfg.SecureSocksDSProxy.RootCAs,
|
||||||
ProxyAddress: s.cfg.SecureSocksDSProxy.ProxyAddress,
|
ProxyAddress: s.cfg.SecureSocksDSProxy.ProxyAddress,
|
||||||
ServerName: s.cfg.SecureSocksDSProxy.ServerName,
|
ServerName: s.cfg.SecureSocksDSProxy.ServerName,
|
||||||
AllowInsecure: s.cfg.SecureSocksDSProxy.AllowInsecure,
|
AllowInsecure: s.cfg.SecureSocksDSProxy.AllowInsecure,
|
||||||
|
@ -122,13 +122,20 @@ func (p *EnvVarsProvider) awsEnvVars(pluginID string) []string {
|
|||||||
func (p *EnvVarsProvider) secureSocksProxyEnvVars() []string {
|
func (p *EnvVarsProvider) secureSocksProxyEnvVars() []string {
|
||||||
if p.cfg.ProxySettings.Enabled {
|
if p.cfg.ProxySettings.Enabled {
|
||||||
return []string{
|
return []string{
|
||||||
envVar(proxy.PluginSecureSocksProxyClientCert, p.cfg.ProxySettings.ClientCert),
|
// nolint:staticcheck
|
||||||
envVar(proxy.PluginSecureSocksProxyClientKey, p.cfg.ProxySettings.ClientKey),
|
envVar(proxy.PluginSecureSocksProxyClientCertFilePathEnvVarName, p.cfg.ProxySettings.ClientCertFilePath),
|
||||||
envVar(proxy.PluginSecureSocksProxyRootCACert, p.cfg.ProxySettings.RootCA),
|
// nolint:staticcheck
|
||||||
envVar(proxy.PluginSecureSocksProxyProxyAddress, p.cfg.ProxySettings.ProxyAddress),
|
envVar(proxy.PluginSecureSocksProxyClientKeyFilePathEnvVarName, p.cfg.ProxySettings.ClientKeyFilePath),
|
||||||
envVar(proxy.PluginSecureSocksProxyServerName, p.cfg.ProxySettings.ServerName),
|
// nolint:staticcheck
|
||||||
envVar(proxy.PluginSecureSocksProxyEnabled, strconv.FormatBool(p.cfg.ProxySettings.Enabled)),
|
envVar(proxy.PluginSecureSocksProxyRootCACertFilePathsEnvVarName, strings.Join(p.cfg.ProxySettings.RootCAFilePaths, " ")),
|
||||||
envVar(proxy.PluginSecureSocksProxyAllowInsecure, strconv.FormatBool(p.cfg.ProxySettings.AllowInsecure)),
|
// nolint:staticcheck
|
||||||
|
envVar(proxy.PluginSecureSocksProxyAddressEnvVarName, p.cfg.ProxySettings.ProxyAddress),
|
||||||
|
// nolint:staticcheck
|
||||||
|
envVar(proxy.PluginSecureSocksProxyServerNameEnvVarName, p.cfg.ProxySettings.ServerName),
|
||||||
|
// nolint:staticcheck
|
||||||
|
envVar(proxy.PluginSecureSocksProxyEnabledEnvVarName, strconv.FormatBool(p.cfg.ProxySettings.Enabled)),
|
||||||
|
// nolint:staticcheck
|
||||||
|
envVar(proxy.PluginSecureSocksProxyAllowInsecureEnvVarName, strconv.FormatBool(p.cfg.ProxySettings.AllowInsecure)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -75,7 +75,7 @@ func (s *RequestConfigProvider) PluginRequestConfig(ctx context.Context, pluginI
|
|||||||
m[proxy.PluginSecureSocksProxyEnabled] = "true"
|
m[proxy.PluginSecureSocksProxyEnabled] = "true"
|
||||||
m[proxy.PluginSecureSocksProxyClientCert] = s.cfg.ProxySettings.ClientCert
|
m[proxy.PluginSecureSocksProxyClientCert] = s.cfg.ProxySettings.ClientCert
|
||||||
m[proxy.PluginSecureSocksProxyClientKey] = s.cfg.ProxySettings.ClientKey
|
m[proxy.PluginSecureSocksProxyClientKey] = s.cfg.ProxySettings.ClientKey
|
||||||
m[proxy.PluginSecureSocksProxyRootCACert] = s.cfg.ProxySettings.RootCA
|
m[proxy.PluginSecureSocksProxyRootCAs] = strings.Join(s.cfg.ProxySettings.RootCAs, ",")
|
||||||
m[proxy.PluginSecureSocksProxyProxyAddress] = s.cfg.ProxySettings.ProxyAddress
|
m[proxy.PluginSecureSocksProxyProxyAddress] = s.cfg.ProxySettings.ProxyAddress
|
||||||
m[proxy.PluginSecureSocksProxyServerName] = s.cfg.ProxySettings.ServerName
|
m[proxy.PluginSecureSocksProxyServerName] = s.cfg.ProxySettings.ServerName
|
||||||
m[proxy.PluginSecureSocksProxyAllowInsecure] = strconv.FormatBool(s.cfg.ProxySettings.AllowInsecure)
|
m[proxy.PluginSecureSocksProxyAllowInsecure] = strconv.FormatBool(s.cfg.ProxySettings.AllowInsecure)
|
||||||
|
@ -39,7 +39,7 @@ func TestRequestConfigProvider_PluginRequestConfig(t *testing.T) {
|
|||||||
ShowUI: true,
|
ShowUI: true,
|
||||||
ClientCert: "c3rt",
|
ClientCert: "c3rt",
|
||||||
ClientKey: "k3y",
|
ClientKey: "k3y",
|
||||||
RootCA: "ca",
|
RootCAs: []string{"ca"},
|
||||||
ProxyAddress: "https://proxy.grafana.com",
|
ProxyAddress: "https://proxy.grafana.com",
|
||||||
ServerName: "secureProxy",
|
ServerName: "secureProxy",
|
||||||
AllowInsecure: true,
|
AllowInsecure: true,
|
||||||
@ -65,7 +65,7 @@ func TestRequestConfigProvider_PluginRequestConfig(t *testing.T) {
|
|||||||
ShowUI: true,
|
ShowUI: true,
|
||||||
ClientCert: "c3rt",
|
ClientCert: "c3rt",
|
||||||
ClientKey: "k3y",
|
ClientKey: "k3y",
|
||||||
RootCA: "ca",
|
RootCAs: []string{"ca"},
|
||||||
ProxyAddress: "https://proxy.grafana.com",
|
ProxyAddress: "https://proxy.grafana.com",
|
||||||
ServerName: "secureProxy",
|
ServerName: "secureProxy",
|
||||||
},
|
},
|
||||||
@ -83,7 +83,7 @@ func TestRequestConfigProvider_PluginRequestConfig(t *testing.T) {
|
|||||||
ShowUI: true,
|
ShowUI: true,
|
||||||
ClientCert: "c3rt",
|
ClientCert: "c3rt",
|
||||||
ClientKey: "k3y",
|
ClientKey: "k3y",
|
||||||
RootCA: "ca",
|
RootCAs: []string{"ca"},
|
||||||
ProxyAddress: "https://proxy.grafana.com",
|
ProxyAddress: "https://proxy.grafana.com",
|
||||||
ServerName: "secureProxy",
|
ServerName: "secureProxy",
|
||||||
},
|
},
|
||||||
|
@ -1,33 +1,41 @@
|
|||||||
package setting
|
package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
|
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecureSocksDSProxySettings struct {
|
type SecureSocksDSProxySettings struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
ShowUI bool
|
ShowUI bool
|
||||||
AllowInsecure bool
|
AllowInsecure bool
|
||||||
ClientCert string
|
ClientCert string
|
||||||
ClientKey string
|
ClientCertFilePath string
|
||||||
RootCA string
|
ClientKey string
|
||||||
ProxyAddress string
|
ClientKeyFilePath string
|
||||||
ServerName string
|
RootCAs []string
|
||||||
|
RootCAFilePaths []string
|
||||||
|
ProxyAddress string
|
||||||
|
ServerName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func readSecureSocksDSProxySettings(iniFile *ini.File) (SecureSocksDSProxySettings, error) {
|
func readSecureSocksDSProxySettings(iniFile *ini.File) (SecureSocksDSProxySettings, error) {
|
||||||
s := SecureSocksDSProxySettings{}
|
s := SecureSocksDSProxySettings{
|
||||||
|
RootCAs: []string{},
|
||||||
|
RootCAFilePaths: []string{},
|
||||||
|
}
|
||||||
secureSocksProxySection := iniFile.Section("secure_socks_datasource_proxy")
|
secureSocksProxySection := iniFile.Section("secure_socks_datasource_proxy")
|
||||||
s.Enabled = secureSocksProxySection.Key("enabled").MustBool(false)
|
s.Enabled = secureSocksProxySection.Key("enabled").MustBool(false)
|
||||||
s.ClientCert = secureSocksProxySection.Key("client_cert").MustString("")
|
|
||||||
s.ClientKey = secureSocksProxySection.Key("client_key").MustString("")
|
|
||||||
s.RootCA = secureSocksProxySection.Key("root_ca_cert").MustString("")
|
|
||||||
s.ProxyAddress = secureSocksProxySection.Key("proxy_address").MustString("")
|
s.ProxyAddress = secureSocksProxySection.Key("proxy_address").MustString("")
|
||||||
s.ServerName = secureSocksProxySection.Key("server_name").MustString("")
|
s.ServerName = secureSocksProxySection.Key("server_name").MustString("")
|
||||||
s.ShowUI = secureSocksProxySection.Key("show_ui").MustBool(true)
|
s.ShowUI = secureSocksProxySection.Key("show_ui").MustBool(true)
|
||||||
s.AllowInsecure = secureSocksProxySection.Key("allow_insecure").MustBool(false)
|
s.AllowInsecure = secureSocksProxySection.Key("allow_insecure").MustBool(false)
|
||||||
|
s.ClientCertFilePath = secureSocksProxySection.Key("client_cert").MustString("")
|
||||||
|
s.ClientKeyFilePath = secureSocksProxySection.Key("client_key").MustString("")
|
||||||
|
s.RootCAFilePaths = secureSocksProxySection.Key("root_ca_cert").Strings(" ")
|
||||||
|
|
||||||
if !s.Enabled {
|
if !s.Enabled {
|
||||||
return s, nil
|
return s, nil
|
||||||
@ -40,14 +48,50 @@ func readSecureSocksDSProxySettings(iniFile *ini.File) (SecureSocksDSProxySettin
|
|||||||
// If the proxy is going to use TLS.
|
// If the proxy is going to use TLS.
|
||||||
if !s.AllowInsecure {
|
if !s.AllowInsecure {
|
||||||
// all fields must be specified to use the proxy
|
// all fields must be specified to use the proxy
|
||||||
if s.RootCA == "" {
|
if len(s.RootCAFilePaths) == 0 {
|
||||||
return s, errors.New("rootCA required")
|
return s, errors.New("one or more rootCA required")
|
||||||
} else if s.ClientCert == "" || s.ClientKey == "" {
|
} else if s.ClientCertFilePath == "" || s.ClientKeyFilePath == "" {
|
||||||
return s, errors.New("client key pair required")
|
return s, errors.New("client key pair required")
|
||||||
} else if s.ServerName == "" {
|
} else if s.ServerName == "" {
|
||||||
return s, errors.New("server name required")
|
return s, errors.New("server name required")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.ClientCertFilePath != "" {
|
||||||
|
certPEMBlock, err := os.ReadFile(s.ClientCertFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
s.ClientCert = string(certPEMBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ClientKeyFilePath != "" {
|
||||||
|
keyPEMBlock, err := os.ReadFile(s.ClientKeyFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
s.ClientKey = string(keyPEMBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rootCAs []string
|
||||||
|
for _, rootCAFile := range s.RootCAFilePaths {
|
||||||
|
// nolint:gosec
|
||||||
|
// The gosec G304 warning can be ignored because `rootCAFile` comes from config ini, and we check below if
|
||||||
|
// it's the right file type.
|
||||||
|
pemBytes, err := os.ReadFile(rootCAFile)
|
||||||
|
if err != nil {
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pemDecoded, _ := pem.Decode(pemBytes)
|
||||||
|
if pemDecoded == nil || pemDecoded.Type != "CERTIFICATE" {
|
||||||
|
return s, errors.New("root ca is invalid")
|
||||||
|
}
|
||||||
|
rootCAs = append(rootCAs, string(pemBytes))
|
||||||
|
}
|
||||||
|
s.RootCAs = rootCAs
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,46 @@
|
|||||||
package setting
|
package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mustNewIniFile(fileContents string) *ini.File {
|
|
||||||
file, err := ini.Load([]byte(fileContents))
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("creating ini file for test: %s", err))
|
|
||||||
}
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadSecureSocksDSProxySettings(t *testing.T) {
|
func TestReadSecureSocksDSProxySettings(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
testFilePath := filepath.Join(tempDir, "test")
|
||||||
|
testFileData := "foobar"
|
||||||
|
err := os.WriteFile(testFilePath, []byte(testFileData), 0600)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
rootCACertFilePath := filepath.Join(tempDir, "ca.cert")
|
||||||
|
// nolint:gosec
|
||||||
|
caCertFile, err := os.Create(rootCACertFilePath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer func() {
|
||||||
|
err = caCertFile.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
rootCaFileData := createTestRootCAFile(t, rootCACertFilePath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
description string
|
description string
|
||||||
iniFile *ini.File
|
iniFile *ini.File
|
||||||
@ -32,24 +53,27 @@ func TestReadSecureSocksDSProxySettings(t *testing.T) {
|
|||||||
[secure_socks_datasource_proxy]
|
[secure_socks_datasource_proxy]
|
||||||
`),
|
`),
|
||||||
expectedSettings: SecureSocksDSProxySettings{
|
expectedSettings: SecureSocksDSProxySettings{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
ClientCert: "",
|
ShowUI: true,
|
||||||
ClientKey: "",
|
AllowInsecure: false,
|
||||||
RootCA: "",
|
ClientCertFilePath: "",
|
||||||
ProxyAddress: "",
|
ClientCert: "",
|
||||||
ServerName: "",
|
ClientKey: "",
|
||||||
ShowUI: true,
|
ClientKeyFilePath: "",
|
||||||
AllowInsecure: false,
|
RootCAs: []string{},
|
||||||
|
RootCAFilePaths: []string{},
|
||||||
|
ProxyAddress: "",
|
||||||
|
ServerName: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "root ca is required",
|
description: "one or more root ca is required",
|
||||||
iniFile: mustNewIniFile(`
|
iniFile: mustNewIniFile(`
|
||||||
[secure_socks_datasource_proxy]
|
[secure_socks_datasource_proxy]
|
||||||
enabled = true
|
enabled = true
|
||||||
proxy_address = address
|
proxy_address = address
|
||||||
`),
|
`),
|
||||||
expectedErr: errors.New("rootCA required"),
|
expectedErr: errors.New("one or more rootCA required"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "client cert is required",
|
description: "client cert is required",
|
||||||
@ -106,35 +130,40 @@ server_name = name
|
|||||||
allow_insecure = true
|
allow_insecure = true
|
||||||
`),
|
`),
|
||||||
expectedSettings: SecureSocksDSProxySettings{
|
expectedSettings: SecureSocksDSProxySettings{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ProxyAddress: "address",
|
ProxyAddress: "address",
|
||||||
ServerName: "name",
|
ServerName: "name",
|
||||||
ShowUI: true,
|
ShowUI: true,
|
||||||
AllowInsecure: true,
|
AllowInsecure: true,
|
||||||
|
RootCAFilePaths: []string{},
|
||||||
|
RootCAs: []string{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "custom values",
|
description: "custom values",
|
||||||
iniFile: mustNewIniFile(`
|
iniFile: mustNewIniFile(fmt.Sprintf(`
|
||||||
[secure_socks_datasource_proxy]
|
[secure_socks_datasource_proxy]
|
||||||
enabled = true
|
enabled = true
|
||||||
client_cert = cert
|
client_cert = %s
|
||||||
client_key = key
|
client_key = %s
|
||||||
root_ca_cert = root_ca
|
root_ca_cert = %s
|
||||||
proxy_address = proxy_address
|
proxy_address = proxy_address
|
||||||
server_name = server_name
|
server_name = server_name
|
||||||
show_ui = false
|
show_ui = false
|
||||||
allow_insecure = true
|
allow_insecure = false
|
||||||
`),
|
`, testFilePath, testFilePath, rootCACertFilePath)),
|
||||||
expectedSettings: SecureSocksDSProxySettings{
|
expectedSettings: SecureSocksDSProxySettings{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ClientCert: "cert",
|
ShowUI: false,
|
||||||
ClientKey: "key",
|
AllowInsecure: false,
|
||||||
RootCA: "root_ca",
|
ClientCert: testFileData,
|
||||||
ProxyAddress: "proxy_address",
|
ClientCertFilePath: testFilePath,
|
||||||
ServerName: "server_name",
|
ClientKey: testFileData,
|
||||||
ShowUI: false,
|
ClientKeyFilePath: testFilePath,
|
||||||
AllowInsecure: true,
|
RootCAs: []string{rootCaFileData},
|
||||||
|
RootCAFilePaths: []string{rootCACertFilePath},
|
||||||
|
ProxyAddress: "proxy_address",
|
||||||
|
ServerName: "server_name",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -146,9 +175,56 @@ allow_insecure = true
|
|||||||
if tt.expectedErr != nil {
|
if tt.expectedErr != nil {
|
||||||
assert.Equal(t, tt.expectedErr, err)
|
assert.Equal(t, tt.expectedErr, err)
|
||||||
} else {
|
} else {
|
||||||
assert.Equal(t, tt.expectedSettings, settings)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.expectedSettings, settings)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createTestRootCAFile(t *testing.T, path string) string {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
ca := &x509.Certificate{
|
||||||
|
SerialNumber: big.NewInt(2019),
|
||||||
|
Subject: pkix.Name{
|
||||||
|
Organization: []string{"Grafana Labs"},
|
||||||
|
CommonName: "Grafana",
|
||||||
|
},
|
||||||
|
NotBefore: time.Now(),
|
||||||
|
NotAfter: time.Now().AddDate(10, 0, 0),
|
||||||
|
IsCA: true,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
require.NoError(t, err)
|
||||||
|
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// nolint:gosec
|
||||||
|
caCertFile, err := os.Create(path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
block := &pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: caBytes,
|
||||||
|
}
|
||||||
|
err = pem.Encode(caCertFile, block)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = pem.Encode(buf, block)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustNewIniFile(fileContents string) *ini.File {
|
||||||
|
file, err := ini.Load([]byte(fileContents))
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("creating ini file for test: %s", err))
|
||||||
|
}
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user