Added ldap and pam authentication
This commit is contained in:
+90
-1
@@ -13,6 +13,7 @@ import (
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/jcmturner/gokrb5/v8/keytab"
|
||||
"github.com/uopi/uopi/internal/access"
|
||||
"github.com/uopi/uopi/internal/audit"
|
||||
"github.com/uopi/uopi/internal/broker"
|
||||
@@ -24,6 +25,8 @@ import (
|
||||
"github.com/uopi/uopi/internal/datasource/servervar"
|
||||
"github.com/uopi/uopi/internal/datasource/stub"
|
||||
"github.com/uopi/uopi/internal/datasource/synthetic"
|
||||
"github.com/uopi/uopi/internal/ldapauth"
|
||||
"github.com/uopi/uopi/internal/pamauth"
|
||||
"github.com/uopi/uopi/internal/panelacl"
|
||||
"github.com/uopi/uopi/internal/server"
|
||||
"github.com/uopi/uopi/internal/storage"
|
||||
@@ -220,7 +223,93 @@ func main() {
|
||||
ctrlEngine.SetDebugObserver(debugHub)
|
||||
ctrlEngine.Reload()
|
||||
|
||||
srv := server.New(cfg.Server.Listen, webFS, brk, synthDS, store, cfgStore, policy, aclStore, ctrlStore, ctrlEngine, dialogs, debugHub, recorder, cfg.Datasource.EPICS.ChannelFinderURL, cfg.Datasource.EPICS.ArchiveURL, cfg.Server.TrustedUserHeader, log)
|
||||
// Native SPNEGO/Kerberos authentication (optional): load the service keytab so
|
||||
// the server can validate browser Negotiate tickets and resolve users directly.
|
||||
var krbKeytab *keytab.Keytab
|
||||
if cfg.Server.Kerberos.Enabled {
|
||||
if cfg.Server.Kerberos.Keytab == "" {
|
||||
log.Error("kerberos enabled but no keytab configured (server.kerberos.keytab)")
|
||||
os.Exit(1)
|
||||
}
|
||||
kt, err := keytab.Load(cfg.Server.Kerberos.Keytab)
|
||||
if err != nil {
|
||||
log.Error("failed to load kerberos keytab", "path", cfg.Server.Kerberos.Keytab, "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
krbKeytab = kt
|
||||
log.Info("native SPNEGO/Kerberos authentication enabled",
|
||||
"keytab", cfg.Server.Kerberos.Keytab, "service_principal", cfg.Server.Kerberos.ServicePrincipal)
|
||||
}
|
||||
|
||||
// Built-in HTTP Basic authentication (optional): challenge the browser with a
|
||||
// login dialog and validate credentials against either the host PAM stack
|
||||
// (basic_auth) or an LDAP directory (ldap), so users log in with their normal
|
||||
// accounts. The three built-in auth methods (kerberos, basic_auth, ldap) are
|
||||
// mutually exclusive.
|
||||
var basicAuthFn func(user, pass string) error
|
||||
var basicAuthRealm string
|
||||
enabledAuth := 0
|
||||
for _, on := range []bool{cfg.Server.Kerberos.Enabled, cfg.Server.BasicAuth.Enabled, cfg.Server.LDAP.Enabled} {
|
||||
if on {
|
||||
enabledAuth++
|
||||
}
|
||||
}
|
||||
if enabledAuth > 1 {
|
||||
log.Error("server.kerberos, server.basic_auth and server.ldap are mutually exclusive; enable only one")
|
||||
os.Exit(1)
|
||||
}
|
||||
if cfg.Server.BasicAuth.Enabled {
|
||||
if !pamauth.Available {
|
||||
log.Error("basic_auth enabled but this binary lacks PAM support; rebuild with: make backend-pam (or use server.ldap, which needs no cgo)")
|
||||
os.Exit(1)
|
||||
}
|
||||
service := cfg.Server.BasicAuth.PAMService
|
||||
if service == "" {
|
||||
service = "uopi"
|
||||
}
|
||||
basicAuthFn = func(user, pass string) error {
|
||||
return pamauth.Authenticate(service, user, pass)
|
||||
}
|
||||
basicAuthRealm = "uopi"
|
||||
log.Info("built-in HTTP Basic authentication enabled (PAM)", "pam_service", service)
|
||||
}
|
||||
if cfg.Server.LDAP.Enabled {
|
||||
ldapAuth, err := ldapauth.New(ldapauth.Config{
|
||||
URIs: cfg.Server.LDAP.URIs,
|
||||
SearchBase: cfg.Server.LDAP.SearchBase,
|
||||
UserAttr: cfg.Server.LDAP.UserAttr,
|
||||
UserObjectClass: cfg.Server.LDAP.UserObjectClass,
|
||||
BindDN: cfg.Server.LDAP.BindDN,
|
||||
BindPassword: cfg.Server.LDAP.BindPassword,
|
||||
StartTLS: cfg.Server.LDAP.StartTLS,
|
||||
CACertFile: cfg.Server.LDAP.CACert,
|
||||
InsecureSkipVerify: cfg.Server.LDAP.InsecureSkipVerify,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("ldap auth misconfigured", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
basicAuthFn = ldapAuth.Authenticate
|
||||
basicAuthRealm = "uopi"
|
||||
log.Info("built-in HTTP Basic authentication enabled (LDAP)", "uri", cfg.Server.LDAP.URIs, "search_base", cfg.Server.LDAP.SearchBase)
|
||||
}
|
||||
if basicAuthFn != nil && !cfg.Server.TLS.Enabled {
|
||||
log.Warn("HTTP Basic authentication enabled without TLS; credentials are sent in clear text — enable server.tls unless on a fully isolated network")
|
||||
}
|
||||
|
||||
// Built-in TLS (optional): terminate HTTPS directly, recommended whenever
|
||||
// Basic auth is enabled.
|
||||
var tlsCert, tlsKey string
|
||||
if cfg.Server.TLS.Enabled {
|
||||
if cfg.Server.TLS.Cert == "" || cfg.Server.TLS.Key == "" {
|
||||
log.Error("server.tls enabled but cert/key not configured (server.tls.cert, server.tls.key)")
|
||||
os.Exit(1)
|
||||
}
|
||||
tlsCert, tlsKey = cfg.Server.TLS.Cert, cfg.Server.TLS.Key
|
||||
log.Info("built-in TLS enabled", "cert", tlsCert)
|
||||
}
|
||||
|
||||
srv := server.New(cfg.Server.Listen, webFS, brk, synthDS, store, cfgStore, policy, aclStore, ctrlStore, ctrlEngine, dialogs, debugHub, recorder, cfg.Datasource.EPICS.ChannelFinderURL, cfg.Datasource.EPICS.ArchiveURL, cfg.Server.TrustedUserHeader, krbKeytab, cfg.Server.Kerberos.ServicePrincipal, basicAuthFn, basicAuthRealm, tlsCert, tlsKey, cfg.UI.DefaultZoom, log)
|
||||
|
||||
if err := srv.Start(ctx); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "server error: %v\n", err)
|
||||
|
||||
Reference in New Issue
Block a user