Browse Source

fix: Fix/ldap tls (#162)

* optimize and fix tls of LDAP

* fix
Tao Chen 11 months ago
parent
commit
5db3c8bf0b
4 changed files with 31 additions and 8 deletions
  1. 1 0
      Dockerfile.dev
  2. 1 1
      conf/config.yaml
  3. 1 1
      config/ldap.go
  4. 28 6
      service/ldap.go

+ 1 - 0
Dockerfile.dev

@@ -76,6 +76,7 @@ COPY --from=builder-backend /app/release /app/
76
 COPY --from=builder-backend /app/conf /app/conf/
76
 COPY --from=builder-backend /app/conf /app/conf/
77
 COPY --from=builder-backend /app/resources /app/resources/
77
 COPY --from=builder-backend /app/resources /app/resources/
78
 COPY --from=builder-backend /app/docs /app/docs/
78
 COPY --from=builder-backend /app/docs /app/docs/
79
+COPY --from=builder-backend /app/http/templates /app/http/templates
79
 # Copy frontend build from builder2 stage
80
 # Copy frontend build from builder2 stage
80
 COPY --from=builder-admin-frontend /frontend/dist/ /app/resources/admin/
81
 COPY --from=builder-admin-frontend /frontend/dist/ /app/resources/admin/
81
 
82
 

+ 1 - 1
conf/config.yaml

@@ -45,7 +45,7 @@ jwt:
45
 ldap:
45
 ldap:
46
   enable: false
46
   enable: false
47
   url: "ldap://ldap.example.com:389"
47
   url: "ldap://ldap.example.com:389"
48
-  tls: false
48
+  tls-ca-file: ""
49
   tls-verify: false
49
   tls-verify: false
50
   base-dn: "dc=example,dc=com"
50
   base-dn: "dc=example,dc=com"
51
   bind-dn: "cn=admin,dc=example,dc=com"
51
   bind-dn: "cn=admin,dc=example,dc=com"

+ 1 - 1
config/ldap.go

@@ -26,7 +26,7 @@ type LdapUser struct {
26
 type Ldap struct {
26
 type Ldap struct {
27
 	Enable       bool     `mapstructure:"enable"`
27
 	Enable       bool     `mapstructure:"enable"`
28
 	Url          string   `mapstructure:"url"`
28
 	Url          string   `mapstructure:"url"`
29
-	TLS          bool     `mapstructure:"tls"`
29
+	TlsCaFile    string   `mapstructure:"tls-ca-file"`
30
 	TlsVerify    bool     `mapstructure:"tls-verify"`
30
 	TlsVerify    bool     `mapstructure:"tls-verify"`
31
 	BaseDn       string   `mapstructure:"base-dn"`
31
 	BaseDn       string   `mapstructure:"base-dn"`
32
 	BindDn       string   `mapstructure:"bind-dn"`
32
 	BindDn       string   `mapstructure:"bind-dn"`

+ 28 - 6
service/ldap.go

@@ -2,8 +2,11 @@ package service
2
 
2
 
3
 import (
3
 import (
4
 	"crypto/tls"
4
 	"crypto/tls"
5
+	"crypto/x509"
5
 	"errors"
6
 	"errors"
6
 	"fmt"
7
 	"fmt"
8
+	"net/url"
9
+	"os"
7
 	"strconv"
10
 	"strconv"
8
 	"strings"
11
 	"strings"
9
 
12
 
@@ -14,6 +17,8 @@ import (
14
 )
17
 )
15
 
18
 
16
 var (
19
 var (
20
+	ErrUrlParseFailed        = errors.New("UrlParseFailed")
21
+	ErrFileReadFailed        = errors.New("FileReadFailed")
17
 	ErrLdapNotEnabled        = errors.New("LdapNotEnabled")
22
 	ErrLdapNotEnabled        = errors.New("LdapNotEnabled")
18
 	ErrLdapUserDisabled      = errors.New("UserDisabledAtLdap")
23
 	ErrLdapUserDisabled      = errors.New("UserDisabledAtLdap")
19
 	ErrLdapUserNotFound      = errors.New("UserNotFound")
24
 	ErrLdapUserNotFound      = errors.New("UserNotFound")
@@ -67,21 +72,38 @@ func (lu *LdapUser) ToUser(u *model.User) *model.User {
67
 
72
 
68
 // connectAndBind creates an LDAP connection, optionally starts TLS, and then binds using the provided credentials.
73
 // connectAndBind creates an LDAP connection, optionally starts TLS, and then binds using the provided credentials.
69
 func (ls *LdapService) connectAndBind(cfg *config.Ldap, username, password string) (*ldap.Conn, error) {
74
 func (ls *LdapService) connectAndBind(cfg *config.Ldap, username, password string) (*ldap.Conn, error) {
70
-	conn, err := ldap.DialURL(cfg.Url)
75
+	u, err := url.Parse(cfg.Url)
71
 	if err != nil {
76
 	if err != nil {
72
-		return nil, errors.Join(ErrLdapConnectFailed, err)
77
+		return nil, errors.Join(ErrUrlParseFailed, err)
73
 	}
78
 	}
74
 
79
 
75
-	if cfg.TLS {
80
+	var conn *ldap.Conn
81
+	if u.Scheme == "ldaps" {
76
 		// WARNING: InsecureSkipVerify: true is not recommended for production
82
 		// WARNING: InsecureSkipVerify: true is not recommended for production
77
-		if err = conn.StartTLS(&tls.Config{InsecureSkipVerify: !cfg.TlsVerify}); err != nil {
78
-			conn.Close()
79
-			return nil, errors.Join(ErrLdapTlsFailed, err)
83
+		tlsConfig := &tls.Config{InsecureSkipVerify: !cfg.TlsVerify}
84
+		if cfg.TlsCaFile != "" {
85
+			caCert, err := os.ReadFile(cfg.TlsCaFile)
86
+			if err != nil {
87
+				return nil, errors.Join(ErrFileReadFailed, err)
88
+			}
89
+			caCertPool := x509.NewCertPool()
90
+			if !caCertPool.AppendCertsFromPEM(caCert) {
91
+				return nil, errors.Join(ErrLdapTlsFailed, errors.New("failed to append CA certificate"))
92
+			}
93
+			tlsConfig.RootCAs = caCertPool
80
 		}
94
 		}
95
+		conn, err = ldap.DialURL(cfg.Url, ldap.DialWithTLSConfig(tlsConfig))
96
+	} else {
97
+		conn, err = ldap.DialURL(cfg.Url)
98
+	}
99
+
100
+	if err != nil {
101
+		return nil, errors.Join(ErrLdapConnectFailed, err)
81
 	}
102
 	}
82
 
103
 
83
 	// Bind as the "service" user
104
 	// Bind as the "service" user
84
 	if err = conn.Bind(username, password); err != nil {
105
 	if err = conn.Bind(username, password); err != nil {
106
+		fmt.Println("Bind failed")
85
 		conn.Close()
107
 		conn.Close()
86
 		return nil, errors.Join(ErrLdapBindService, err)
108
 		return nil, errors.Join(ErrLdapBindService, err)
87
 	}
109
 	}