Files
Gábor Farkas 8c18d06386 Postgres: Switch the datasource plugin from lib/pq to pgx (#81353)
* postgres: switch from lib/pq to pgx

* postgres: improved tls handling
2024-02-28 07:52:45 +01:00

383 lines
10 KiB
Go

package tls
import (
"errors"
"os"
"testing"
"github.com/grafana/grafana/pkg/tsdb/sqleng"
"github.com/stretchr/testify/require"
)
func noReadFile(path string) ([]byte, error) {
return nil, errors.New("not implemented")
}
func TestTLSNoMode(t *testing.T) {
// for backward-compatibility reason,
// when mode is unset, it defaults to `require`
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
ConfigurationMethod: "",
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.True(t, c.InsecureSkipVerify)
}
func TestTLSDisable(t *testing.T) {
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "disable",
ConfigurationMethod: "",
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.Nil(t, c)
}
func TestTLSRequire(t *testing.T) {
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "",
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.True(t, c.InsecureSkipVerify)
require.Nil(t, c.RootCAs)
}
func TestTLSRequireWithRootCert(t *testing.T) {
rootCertBytes, err := CreateRandomRootCertBytes()
require.NoError(t, err)
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{
"tlsCACert": string(rootCertBytes),
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.True(t, c.InsecureSkipVerify)
require.NotNil(t, c.VerifyConnection)
require.NotNil(t, c.RootCAs) // TODO: not the best, but nothing better available
}
func TestTLSVerifyCA(t *testing.T) {
rootCertBytes, err := CreateRandomRootCertBytes()
require.NoError(t, err)
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-ca",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{
"tlsCACert": string(rootCertBytes),
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.True(t, c.InsecureSkipVerify)
require.NotNil(t, c.VerifyConnection)
require.NotNil(t, c.RootCAs) // TODO: not the best, but nothing better available
}
func TestTLSVerifyCAMisingRootCert(t *testing.T) {
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-ca",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{},
}
_, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.ErrorIs(t, err, errNoRootCert)
}
func TestTLSClientCert(t *testing.T) {
clientKey, clientCert, err := CreateRandomClientCert()
require.NoError(t, err)
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{
"tlsClientCert": string(clientCert),
"tlsClientKey": string(clientKey),
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.Len(t, c.Certificates, 1)
}
func TestTLSMethodFileContentClientCertMissingKey(t *testing.T) {
_, clientCert, err := CreateRandomClientCert()
require.NoError(t, err)
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{
"tlsClientCert": string(clientCert),
},
}
_, err = GetTLSConfig(dsInfo, noReadFile, "localhost")
require.ErrorIs(t, err, errPartialClientCertNoKey)
}
func TestTLSMethodFileContentClientCertMissingCert(t *testing.T) {
clientKey, _, err := CreateRandomClientCert()
require.NoError(t, err)
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{
"tlsClientKey": string(clientKey),
},
}
_, err = GetTLSConfig(dsInfo, noReadFile, "localhost")
require.ErrorIs(t, err, errPartialClientCertNoCert)
}
func TestTLSMethodFilePathClientCertMissingKey(t *testing.T) {
clientKey, _, err := CreateRandomClientCert()
require.NoError(t, err)
readFile := newMockReadFile(map[string]([]byte){
"path1": clientKey,
})
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-path",
CertKeyFile: "path1",
},
}
_, err = GetTLSConfig(dsInfo, readFile, "localhost")
require.ErrorIs(t, err, errPartialClientCertNoCert)
}
func TestTLSMethodFilePathClientCertMissingCert(t *testing.T) {
_, clientCert, err := CreateRandomClientCert()
require.NoError(t, err)
readFile := newMockReadFile(map[string]([]byte){
"path1": clientCert,
})
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-path",
CertFile: "path1",
},
}
_, err = GetTLSConfig(dsInfo, readFile, "localhost")
require.ErrorIs(t, err, errPartialClientCertNoKey)
}
func TestTLSVerifyFull(t *testing.T) {
rootCertBytes, err := CreateRandomRootCertBytes()
require.NoError(t, err)
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-full",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{
"tlsCACert": string(rootCertBytes),
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.False(t, c.InsecureSkipVerify)
require.Nil(t, c.VerifyConnection)
require.NotNil(t, c.RootCAs) // TODO: not the best, but nothing better available
}
func TestTLSMethodFileContent(t *testing.T) {
rootCertBytes, err := CreateRandomRootCertBytes()
require.NoError(t, err)
clientKey, clientCert, err := CreateRandomClientCert()
require.NoError(t, err)
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-full",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{
"tlsCACert": string(rootCertBytes),
"tlsClientCert": string(clientCert),
"tlsClientKey": string(clientKey),
},
}
c, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.Len(t, c.Certificates, 1)
require.NotNil(t, c.RootCAs) // TODO: not the best, but nothing better available
}
func TestTLSMethodFilePath(t *testing.T) {
rootCertBytes, err := CreateRandomRootCertBytes()
require.NoError(t, err)
clientKey, clientCert, err := CreateRandomClientCert()
require.NoError(t, err)
readFile := newMockReadFile(map[string]([]byte){
"root-cert-path": rootCertBytes,
"client-key-path": clientKey,
"client-cert-path": clientCert,
})
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-full",
ConfigurationMethod: "file-path",
RootCertFile: "root-cert-path",
CertKeyFile: "client-key-path",
CertFile: "client-cert-path",
},
}
c, err := GetTLSConfig(dsInfo, readFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.Len(t, c.Certificates, 1)
require.NotNil(t, c.RootCAs) // TODO: not the best, but nothing better available
}
func TestTLSMethodFilePathRootCertDoesNotExist(t *testing.T) {
readFile := newMockReadFile(map[string]([]byte){})
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-full",
ConfigurationMethod: "file-path",
RootCertFile: "path1",
},
}
_, err := GetTLSConfig(dsInfo, readFile, "localhost")
require.ErrorIs(t, err, os.ErrNotExist)
}
func TestTLSMethodFilePathClientCertKeyDoesNotExist(t *testing.T) {
_, clientCert, err := CreateRandomClientCert()
require.NoError(t, err)
readFile := newMockReadFile(map[string]([]byte){
"cert-path": clientCert,
})
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-path",
CertKeyFile: "key-path",
CertFile: "cert-path",
},
}
_, err = GetTLSConfig(dsInfo, readFile, "localhost")
require.ErrorIs(t, err, os.ErrNotExist)
}
func TestTLSMethodFilePathClientCertCertDoesNotExist(t *testing.T) {
clientKey, _, err := CreateRandomClientCert()
require.NoError(t, err)
readFile := newMockReadFile(map[string]([]byte){
"key-path": clientKey,
})
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "require",
ConfigurationMethod: "file-path",
CertKeyFile: "key-path",
CertFile: "cert-path",
},
}
_, err = GetTLSConfig(dsInfo, readFile, "localhost")
require.ErrorIs(t, err, os.ErrNotExist)
}
// method="" equals to method="file-path"
func TestTLSMethodEmpty(t *testing.T) {
rootCertBytes, err := CreateRandomRootCertBytes()
require.NoError(t, err)
clientKey, clientCert, err := CreateRandomClientCert()
require.NoError(t, err)
readFile := newMockReadFile(map[string]([]byte){
"root-cert-path": rootCertBytes,
"client-key-path": clientKey,
"client-cert-path": clientCert,
})
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-full",
ConfigurationMethod: "",
RootCertFile: "root-cert-path",
CertKeyFile: "client-key-path",
CertFile: "client-cert-path",
},
}
c, err := GetTLSConfig(dsInfo, readFile, "localhost")
require.NoError(t, err)
require.NotNil(t, c)
require.Len(t, c.Certificates, 1)
require.NotNil(t, c.RootCAs) // TODO: not the best, but nothing better available
}
func TestTLSVerifyFullMisingRootCert(t *testing.T) {
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "verify-full",
ConfigurationMethod: "file-content",
},
DecryptedSecureJSONData: map[string]string{},
}
_, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.ErrorIs(t, err, errNoRootCert)
}
func TestTLSInvalidMode(t *testing.T) {
dsInfo := sqleng.DataSourceInfo{
JsonData: sqleng.JsonData{
Mode: "not-a-valid-mode",
},
}
_, err := GetTLSConfig(dsInfo, noReadFile, "localhost")
require.Error(t, err)
}