Auth: Add root and client certificate value fields in LDAP config (#88746)

* add root and client certificate value fields for LDAP

* update error messages for connection error
This commit is contained in:
Mihai Doarna
2024-06-10 18:13:15 +03:00
committed by GitHub
parent 06c30ee165
commit 0f936e2939
8 changed files with 289 additions and 28 deletions

View File

@ -14,6 +14,43 @@ import (
"github.com/grafana/grafana/pkg/setting"
)
const (
validCert = `LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURYVENDQWtXZ0F3SUJBZ0lKQUxtVlZ1RFd1NE5ZTUEwR0NTcUdTSWIzRFFFQkN
3VUFNRVV4Q3pBSkJnTlYKQkFZVEFrRlZNUk13RVFZRFZRUUlEQXBUYjIxbExWTjBZWFJsTVNFd0h3WURWUVFLREJoSmJuUmxjbTVsZENCWAphV1JuYVhSekl
GQjBlU0JNZEdRd0hoY05NVFl4TWpNeE1UUXpORFEzV2hjTk5EZ3dOakkxTVRRek5EUTNXakJGCk1Rc3dDUVlEVlFRR0V3SkJWVEVUTUJFR0ExVUVDQXdLVTI
5dFpTMVRkR0YwWlRFaE1COEdBMVVFQ2d3WVNXNTAKWlhKdVpYUWdWMmxrWjJsMGN5QlFkSGtnVEhSa01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUTh
BTUlJQgpDZ0tDQVFFQXpVQ0ZvemdOYjFoMU0wanpOUlNDamhPQm5SK3VWYlZwYVdmWFlJUitBaFdEZEVlNXJ5WStDZ2F2Ck9nOGJmTHlieXpGZGVobFlkRFJ
na2VkRUIvR2pHOGFKdzA2bDBxRjRqRE9BdzBrRXlnV0N1Mm1jSDdYT3hSdCsKWUFIM1RWSGEvSHUxVzNXanprb2JxcXFMUThna0tXV00yN2ZPZ0FaNkdpZWF
KQk42VkJTTU1jUGV5M0hXTEJtYworVFlKbXYxZGJhTzJqSGhLaDhwZkt3MFcxMlZNOFAxUElPOGd2NFBodS91dUpZaWVCV0tpeEJFeXkwbEhqeWl4CllGQ1I
xMnhkaDRDQTQ3cTk1OFpSR25uRFVHRlZFMVFoZ1JhY0pDT1o5YmQ1dDltcjhLTGFWQllUQ0pvNUVSRTgKanltYWI1ZFBxZTVxS2ZKc0NaaXFXZ2xialVvOXR
3SURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVV4cHV3Y3MvQwpZUU95dWkrcjFHKzNLeEJOaHhrd0h3WURWUjBqQkJnd0ZvQVV4cHV3Y3MvQ1lRT3l1aStyMUc
rM0t4Qk5oeGt3CkRBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBQWlXVUtzLzJ4L3ZpTkNLaTNZNmIKbEV1Q3RBR2h6T09aOUV
qcnZKOCtDT0gzUmFnM3RWQldyY0JaMy91aGhQcTVneTlscXc0T2t2RXdzOTkvNWpGcwpYMUZKNk1LQmdxZnV5N3loNXMxWWZNMEFOSFljek1tWXBaZUFjUWY
yQ0dBYVZmd1RUZlNsek5Mc0YybFcvbHk3CnlhcEZ6bFlTSkxHb1ZFK09IRXU4ZzVTbE5BQ1VFZmtYdys1RWdoaCtLemxJTjdSNlE3cjJpeFdORkJDL2pXZjc
KTktVZkp5WDhxSUc1bWQxWVVlVDZHQlc5Qm0yLzEvUmlPMjRKVGFZbGZMZEtLOVRZYjhzRzVCK09MYWIyREltRwo5OUNKMjVSa0FjU29iV05GNXpEME82bGd
PbzNjRWRCL2tzQ3EzaG10bEMvRGxMWi9EOENKKzdWdVpuUzFyUjJuCmFRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==`
validKey = `LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFdlFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLY3dnZ1NqQWdFQUFv
SUJBUUROUUlXak9BMXZXSFV6ClNQTTFGSUtPRTRHZEg2NVZ0V2xwWjlkZ2hINENGWU4wUjdtdkpqNEtCcTg2RHh0OHZKdkxNVjE2R1ZoME5HQ1IKNTBRSDhh
TWJ4b25EVHFYU29YaU1NNEREU1FUS0JZSzdhWndmdGM3RkczNWdBZmROVWRyOGU3VmJkYVBPU2h1cQpxb3REeUNRcFpZemJ0ODZBQm5vYUo1b2tFM3BVRkl3
eHc5N0xjZFlzR1p6NU5nbWEvVjF0bzdhTWVFcUh5bDhyCkRSYlhaVXp3L1U4Zzd5Qy9nK0c3KzY0bGlKNEZZcUxFRVRMTFNVZVBLTEZnVUpIWGJGMkhnSURq
dXIzbnhsRWEKZWNOUVlWVVRWQ0dCRnB3a0k1bjF0M20zMmF2d290cFVGaE1JbWprUkVUeVBLWnB2bDArcDdtb3A4bXdKbUtwYQpDVnVOU2oyM0FnTUJBQUVD
Z2dFQUJuNEkvQjIweHhYY056QVNpVlpKdnVhOURkUkh0bXhUbGtMem5CajB4Mm9ZCnkxL05iczNkM29GUm41dUV1aEJaT1RjcGhzZ3dkUlNIRFhac1AzZ1VP
YmV3K2QyTi96aWVVSWo4aExEVmx2SlAKclUvczRVL2w1M1EwTGlOQnlFOVRodkwrekpMUENLSnRkNXVIWmpCNWZGbTY5K1E3Z3U4eGc0eEhJdWIrMHBQNQpQ
SGFubUhDRHJiZ05OL29xbGFyNEZaMk1YVGdla1c2QW15Yy9rb0U5aEluNEJhYTJLZS9CL0FVR1k0cE1STHFwClRBcnQrR1RWZVdlb0ZZOVFBQ1VwYUhwSmhH
Yi9QaW91NnRsVTU3ZTQyY0xva2kxZjArU0FSc0JCS3lYQTdCQjEKMWZNSDEwS1FZRkE2OGRUWVdsS3pRYXUvSzR4YXFnNEZLbXR3RjY2R1FRS0JnUUQ5T3BO
VVM3b1J4TUhWSmFCUgpUTldXK1YxRlh5Y3FvamVrRnBEaWpQYjJYNUNXVjE2b2VXZ2FYcDBuT0hGZHk5RVdzM0d0R3BmWmFzYVJWSHNYClNIdFBoNE5iOEpx
SGRHRTAvQ0Q2dDArNERuczhCbjljU3F0ZFFCN1IzSm43SU1YaTlYL1U4TERLbytBMTgvSnEKVjhWZ1VuZ01ueTlZak1rUUliSzhUUldrWVFLQmdRRFBmNG54
TzZqdSt0T0hIT1JRdHkzYllERDArT1YzSTArTAoweXowdVByZXJ5QlZpOW5ZNDNLYWtINTJEN1VaRXd3c0JqakdYRCtXSDh4RXNtQldzR05YSnUwMjVQdnpJ
Sm96CmxBRWlYdk1wL05tWXArdFk0ckRtTzhSaHlWb2NCcVdIemgzOG0wSUZPZDRCeUZENW5MRURyQTNwRFZvMGFOZ1kKbjBHd1J5c1pGd0tCZ1FEa0NqM202
Wk1Vc1VXRXR5K2FSMEVKaG1LeU9EQkRPblkwOUlWaEgyUy9GZXhWRnpVTgpMdGZLOTIwNmhwL0F3ZXozTG4ydVQ0WnpxcTVLN2ZNelVuaUpkQldkVkIwMDRs
OHZvZVhwSWU5T1p1d2ZjQko5CmdGaTF6eXB4L3VGRHY0MjFCelFwQk4rUWZPZEtidmJkUVZGam5xQ3hiU0RyODB5VmxHTXJJNWZid1FLQmdHMDkKb1JyZXBP
N0VJTzhHTi9HQ3J1TEsvcHRLR2t5aHkzUTZ4blZFbWRiNDdoWDduY0pBNUlvWlBtcmJsQ1ZTVU5zdwpuMTFYSGFia3NMOE9CZ2c5cnQ4b1FFVGhRdi9hRHpU
T1c5YURsSk5yYWdlamlCVHdxOTlhWWVaMWdqbzFDWnE0CjJqS3VicENmeVpDNHJHRHRySWZaWWkxcStTMlVjUWh0ZDhEZGh3UWJBb0dBQU00RXBEQTR5SEI1
eWllazFwL28KQ2JxUkN0YS9EeDZFeW8wS2xOQXlQdUZQQXNodXBHNE5CeDdtVDJBU2ZMKzJWQkhvaTZtSFNyaStCRFg1cnlZRgpmTVl2cDdVUllvcTd3N3Fp
dlJsdnZFZzV5b1lySzEzRjIrR2o2eEo0akVOOW0wS2RNL2czbUpHcTBIQlRJUXJwClNtNzVXWHNmbE94dVRuMDhMYmdHYzRzPQotLS0tLUVORCBSU0EgUFJJ
VkFURSBLRVktLS0tLQ==`
)
func TestNew(t *testing.T) {
result := New(&ServerConfig{
Attr: AttributeMap{},
@ -23,6 +60,128 @@ func TestNew(t *testing.T) {
assert.Implements(t, (*IServer)(nil), result)
}
func TestServer_Dial(t *testing.T) {
t.Run("fails having no host but with valid root and client certificate files", func(t *testing.T) {
serverConfig := &ServerConfig{
Host: "",
RootCACert: "./testdata/parsable.cert",
ClientCert: "./testdata/parsable.cert",
ClientKey: "./testdata/parsable.pem",
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "connect")
})
t.Run("fails with invalid root certificate file", func(t *testing.T) {
serverConfig := &ServerConfig{
RootCACert: "./testdata/invalid.cert",
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "failed to append CA certificate")
})
t.Run("fails with non existing root certificate file", func(t *testing.T) {
serverConfig := &ServerConfig{
RootCACert: "./testdata/nofile.cert",
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "no such file or directory")
})
t.Run("fails with invalid client certificate file", func(t *testing.T) {
serverConfig := &ServerConfig{
ClientCert: "./testdata/invalid.cert",
ClientKey: "./testdata/invalid.pem",
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "failed to find any PEM data")
})
t.Run("fails with non existing client certificate file", func(t *testing.T) {
serverConfig := &ServerConfig{
ClientCert: "./testdata/nofile.cert",
ClientKey: "./testdata/parsable.pem",
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "no such file or directory")
})
t.Run("fails having no host but with valid root and client certificate values", func(t *testing.T) {
serverConfig := &ServerConfig{
Host: "",
RootCACertValue: []string{validCert},
ClientCertValue: validCert,
ClientKeyValue: validKey,
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "connect")
})
t.Run("fails with invalid base64 root certificate value", func(t *testing.T) {
serverConfig := &ServerConfig{
RootCACertValue: []string{"invalid-certificate"},
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "illegal base64 data")
})
t.Run("fails with invalid root certificate value", func(t *testing.T) {
serverConfig := &ServerConfig{
RootCACertValue: []string{"aW52YWxpZC1jZXJ0aWZpY2F0ZQ=="},
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "failed to append CA certificate")
})
t.Run("fails with invalid base64 client certificate value", func(t *testing.T) {
serverConfig := &ServerConfig{
ClientCertValue: "invalid-certificate",
ClientKeyValue: validKey,
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "illegal base64 data")
})
t.Run("fails with invalid client certificate value", func(t *testing.T) {
serverConfig := &ServerConfig{
ClientCertValue: validCert,
ClientKeyValue: "aW52YWxpZC1rZXk=",
}
server := New(serverConfig, &setting.Cfg{})
err := server.Dial()
require.Error(t, err)
require.ErrorContains(t, err, "failed to find any PEM data")
})
}
func TestServer_Close(t *testing.T) {
t.Run("close the connection", func(t *testing.T) {
connection := &MockConnection{}