From 5db3c8bf0b2973971c41ee00d92f6b96debb08bc Mon Sep 17 00:00:00 2001 From: Tao Chen <42793494+IamTaoChen@users.noreply.github.com> Date: Sun, 2 Mar 2025 22:59:01 +0800 Subject: [PATCH] fix: Fix/ldap tls (#162) * optimize and fix tls of LDAP * fix --- Dockerfile.dev | 1 + conf/config.yaml | 2 +- config/ldap.go | 2 +- service/ldap.go | 40 +++++++++++++++++++++++++++++++--------- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Dockerfile.dev b/Dockerfile.dev index d48794f..13c22f4 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -76,6 +76,7 @@ COPY --from=builder-backend /app/release /app/ COPY --from=builder-backend /app/conf /app/conf/ COPY --from=builder-backend /app/resources /app/resources/ COPY --from=builder-backend /app/docs /app/docs/ +COPY --from=builder-backend /app/http/templates /app/http/templates # Copy frontend build from builder2 stage COPY --from=builder-admin-frontend /frontend/dist/ /app/resources/admin/ diff --git a/conf/config.yaml b/conf/config.yaml index cf2ca64..81de224 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -45,7 +45,7 @@ jwt: ldap: enable: false url: "ldap://ldap.example.com:389" - tls: false + tls-ca-file: "" tls-verify: false base-dn: "dc=example,dc=com" bind-dn: "cn=admin,dc=example,dc=com" diff --git a/config/ldap.go b/config/ldap.go index 4d08607..f1ead74 100644 --- a/config/ldap.go +++ b/config/ldap.go @@ -26,7 +26,7 @@ type LdapUser struct { type Ldap struct { Enable bool `mapstructure:"enable"` Url string `mapstructure:"url"` - TLS bool `mapstructure:"tls"` + TlsCaFile string `mapstructure:"tls-ca-file"` TlsVerify bool `mapstructure:"tls-verify"` BaseDn string `mapstructure:"base-dn"` BindDn string `mapstructure:"bind-dn"` diff --git a/service/ldap.go b/service/ldap.go index 6d12646..9d498ab 100644 --- a/service/ldap.go +++ b/service/ldap.go @@ -2,8 +2,11 @@ package service import ( "crypto/tls" + "crypto/x509" "errors" "fmt" + "net/url" + "os" "strconv" "strings" @@ -14,6 +17,8 @@ import ( ) var ( + ErrUrlParseFailed = errors.New("UrlParseFailed") + ErrFileReadFailed = errors.New("FileReadFailed") ErrLdapNotEnabled = errors.New("LdapNotEnabled") ErrLdapUserDisabled = errors.New("UserDisabledAtLdap") ErrLdapUserNotFound = errors.New("UserNotFound") @@ -67,21 +72,38 @@ func (lu *LdapUser) ToUser(u *model.User) *model.User { // connectAndBind creates an LDAP connection, optionally starts TLS, and then binds using the provided credentials. func (ls *LdapService) connectAndBind(cfg *config.Ldap, username, password string) (*ldap.Conn, error) { - conn, err := ldap.DialURL(cfg.Url) + u, err := url.Parse(cfg.Url) + if err != nil { + return nil, errors.Join(ErrUrlParseFailed, err) + } + + var conn *ldap.Conn + if u.Scheme == "ldaps" { + // WARNING: InsecureSkipVerify: true is not recommended for production + tlsConfig := &tls.Config{InsecureSkipVerify: !cfg.TlsVerify} + if cfg.TlsCaFile != "" { + caCert, err := os.ReadFile(cfg.TlsCaFile) + if err != nil { + return nil, errors.Join(ErrFileReadFailed, err) + } + caCertPool := x509.NewCertPool() + if !caCertPool.AppendCertsFromPEM(caCert) { + return nil, errors.Join(ErrLdapTlsFailed, errors.New("failed to append CA certificate")) + } + tlsConfig.RootCAs = caCertPool + } + conn, err = ldap.DialURL(cfg.Url, ldap.DialWithTLSConfig(tlsConfig)) + } else { + conn, err = ldap.DialURL(cfg.Url) + } + if err != nil { return nil, errors.Join(ErrLdapConnectFailed, err) } - if cfg.TLS { - // WARNING: InsecureSkipVerify: true is not recommended for production - if err = conn.StartTLS(&tls.Config{InsecureSkipVerify: !cfg.TlsVerify}); err != nil { - conn.Close() - return nil, errors.Join(ErrLdapTlsFailed, err) - } - } - // Bind as the "service" user if err = conn.Bind(username, password); err != nil { + fmt.Println("Bind failed") conn.Close() return nil, errors.Join(ErrLdapBindService, err) }