)
type ldapLoginController struct {
- Cluster *arvados.Cluster
- RailsProxy *railsProxy
+ Cluster *arvados.Cluster
+ Parent *Conn
}
func (ctrl *ldapLoginController) Logout(ctx context.Context, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
- return noopLogout(ctrl.Cluster, opts)
+ return logout(ctx, ctrl.Cluster, opts)
}
func (ctrl *ldapLoginController) Login(ctx context.Context, opts arvados.LoginOptions) (arvados.LoginResponse, error) {
conf := ctrl.Cluster.Login.LDAP
errFailed := httpserver.ErrorWithStatus(fmt.Errorf("LDAP: Authentication failure (with username %q and password)", opts.Username), http.StatusUnauthorized)
+ if conf.SearchAttribute == "" {
+ return arvados.APIClientAuthorization{}, errors.New("config error: SearchAttribute is blank")
+ }
if opts.Password == "" {
log.WithField("username", opts.Username).Error("refusing to authenticate with empty password")
return arvados.APIClientAuthorization{}, errFailed
}
log = log.WithField("URL", conf.URL.String())
- l, err := ldap.DialURL(conf.URL.String())
+ var l *ldap.Conn
+ var err error
+ if conf.URL.Scheme == "ldaps" {
+ // ldap.DialURL does not currently allow us to control
+ // tls.Config, so we need to figure out the port
+ // ourselves and call DialTLS.
+ host, port, err := net.SplitHostPort(conf.URL.Host)
+ if err != nil {
+ // Assume error means no port given
+ host = conf.URL.Host
+ port = ldap.DefaultLdapsPort
+ }
+ l, err = ldap.DialTLS("tcp", net.JoinHostPort(host, port), &tls.Config{
+ ServerName: host,
+ MinVersion: uint16(conf.MinTLSVersion),
+ })
+ } else {
+ l, err = ldap.DialURL(conf.URL.String())
+ }
if err != nil {
log.WithError(err).Error("ldap connection failed")
return arvados.APIClientAuthorization{}, err
if conf.StartTLS {
var tlsconfig tls.Config
+ tlsconfig.MinVersion = uint16(conf.MinTLSVersion)
if conf.InsecureTLS {
tlsconfig.InsecureSkipVerify = true
} else {
}
}
- if conf.SearchAttribute == "" {
- return arvados.APIClientAuthorization{}, errors.New("config error: must provide SearchAttribute")
+ search := fmt.Sprintf("(%s=%s)", ldap.EscapeFilter(conf.SearchAttribute), ldap.EscapeFilter(username))
+ if conf.SearchFilters != "" {
+ search = fmt.Sprintf("(&%s%s)", conf.SearchFilters, search)
}
-
- search := fmt.Sprintf("(&%s(%s=%s))", conf.SearchFilters, ldap.EscapeFilter(conf.SearchAttribute), ldap.EscapeFilter(username))
log = log.WithField("search", search)
req := ldap.NewSearchRequest(
conf.SearchBase,
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoResultsReturned) ||
ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) ||
(err == nil && len(resp.Entries) == 0) {
- log.WithError(err).Debug("ldap lookup returned no results")
+ log.WithError(err).Info("ldap lookup returned no results")
return arvados.APIClientAuthorization{}, errFailed
} else if err != nil {
log.WithError(err).Error("ldap lookup failed")
// Now that we have the DN, try authenticating.
err = l.Bind(userdn, opts.Password)
if err != nil {
- log.WithError(err).Warn("ldap user authentication failed")
+ log.WithError(err).Info("ldap user authentication failed")
return arvados.APIClientAuthorization{}, errFailed
}
log.Debug("ldap authentication succeeded")
return arvados.APIClientAuthorization{}, errors.New("authentication succeeded but ldap returned no email address")
}
- return createAPIClientAuthorization(ctx, ctrl.RailsProxy, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
+ return ctrl.Parent.CreateAPIClientAuthorization(ctx, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
Email: email,
FirstName: attrs["givenname"],
LastName: attrs["sn"],