@@ -76,6 +76,7 @@ COPY --from=builder-backend /app/release /app/
|
|||||||
COPY --from=builder-backend /app/conf /app/conf/
|
COPY --from=builder-backend /app/conf /app/conf/
|
||||||
COPY --from=builder-backend /app/resources /app/resources/
|
COPY --from=builder-backend /app/resources /app/resources/
|
||||||
COPY --from=builder-backend /app/docs /app/docs/
|
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 frontend build from builder2 stage
|
||||||
COPY --from=builder-admin-frontend /frontend/dist/ /app/resources/admin/
|
COPY --from=builder-admin-frontend /frontend/dist/ /app/resources/admin/
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ jwt:
|
|||||||
ldap:
|
ldap:
|
||||||
enable: false
|
enable: false
|
||||||
url: "ldap://ldap.example.com:389"
|
url: "ldap://ldap.example.com:389"
|
||||||
tls: false
|
tls-ca-file: ""
|
||||||
tls-verify: false
|
tls-verify: false
|
||||||
base-dn: "dc=example,dc=com"
|
base-dn: "dc=example,dc=com"
|
||||||
bind-dn: "cn=admin,dc=example,dc=com"
|
bind-dn: "cn=admin,dc=example,dc=com"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type LdapUser struct {
|
|||||||
type Ldap struct {
|
type Ldap struct {
|
||||||
Enable bool `mapstructure:"enable"`
|
Enable bool `mapstructure:"enable"`
|
||||||
Url string `mapstructure:"url"`
|
Url string `mapstructure:"url"`
|
||||||
TLS bool `mapstructure:"tls"`
|
TlsCaFile string `mapstructure:"tls-ca-file"`
|
||||||
TlsVerify bool `mapstructure:"tls-verify"`
|
TlsVerify bool `mapstructure:"tls-verify"`
|
||||||
BaseDn string `mapstructure:"base-dn"`
|
BaseDn string `mapstructure:"base-dn"`
|
||||||
BindDn string `mapstructure:"bind-dn"`
|
BindDn string `mapstructure:"bind-dn"`
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -14,6 +17,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
ErrUrlParseFailed = errors.New("UrlParseFailed")
|
||||||
|
ErrFileReadFailed = errors.New("FileReadFailed")
|
||||||
ErrLdapNotEnabled = errors.New("LdapNotEnabled")
|
ErrLdapNotEnabled = errors.New("LdapNotEnabled")
|
||||||
ErrLdapUserDisabled = errors.New("UserDisabledAtLdap")
|
ErrLdapUserDisabled = errors.New("UserDisabledAtLdap")
|
||||||
ErrLdapUserNotFound = errors.New("UserNotFound")
|
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.
|
// 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) {
|
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 {
|
if err != nil {
|
||||||
return nil, errors.Join(ErrLdapConnectFailed, err)
|
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
|
// Bind as the "service" user
|
||||||
if err = conn.Bind(username, password); err != nil {
|
if err = conn.Bind(username, password); err != nil {
|
||||||
|
fmt.Println("Bind failed")
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, errors.Join(ErrLdapBindService, err)
|
return nil, errors.Join(ErrLdapBindService, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user