func ValidateLDAPIdentityProvider(provider *api.LDAPPasswordIdentityProvider, identityProvider api.IdentityProvider) ValidationResults { validationResults := ValidationResults{} if len(provider.URL) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("provider.url")) return validationResults } u, err := ldappassword.ParseURL(provider.URL) if err != nil { validationResults.AddErrors(fielderrors.NewFieldInvalid("provider.url", provider.URL, err.Error())) return validationResults } // Make sure bindDN and bindPassword are both set, or both unset // Both unset means an anonymous bind is used for search (https://tools.ietf.org/html/rfc4513#section-5.1.1) // Both set means the name/password simple bind is used for search (https://tools.ietf.org/html/rfc4513#section-5.1.3) if (len(provider.BindDN) == 0) != (len(provider.BindPassword) == 0) { validationResults.AddErrors(fielderrors.NewFieldInvalid("provider.bindDN", provider.BindDN, "bindDN and bindPassword must both be specified, or both be empty")) validationResults.AddErrors(fielderrors.NewFieldInvalid("provider.bindPassword", "<masked>", "bindDN and bindPassword must both be specified, or both be empty")) } if provider.Insecure { if u.Scheme == ldappassword.SchemeLDAPS { validationResults.AddErrors(fielderrors.NewFieldInvalid("provider.url", provider.URL, fmt.Sprintf("Cannot use %s scheme with insecure=true", u.Scheme))) } if len(provider.CA) > 0 { validationResults.AddErrors(fielderrors.NewFieldInvalid("provider.ca", provider.CA, "Cannot specify a ca with insecure=true")) } } else { if len(provider.CA) > 0 { validationResults.AddErrors(ValidateFile(provider.CA, "provider.ca")...) } } // At least one attribute to use as the user id is required if len(provider.Attributes.ID) == 0 { validationResults.AddErrors(fielderrors.NewFieldInvalid("provider.attributes.id", "[]", "at least one id attribute is required (LDAP standard identity attribute is 'dn')")) } // Warn if insecure if provider.Insecure { validationResults.AddWarnings(fielderrors.NewFieldInvalid("provider.insecure", provider.Insecure, "validating passwords over an insecure connection could allow them to be intercepted")) } return validationResults }
func (c *AuthConfig) getPasswordAuthenticator(identityProvider configapi.IdentityProvider) (authenticator.Password, error) { identityMapper := identitymapper.NewAlwaysCreateUserIdentityToUserMapper(c.IdentityRegistry, c.UserRegistry) switch provider := identityProvider.Provider.Object.(type) { case (*configapi.AllowAllPasswordIdentityProvider): return allowanypassword.New(identityProvider.Name, identityMapper), nil case (*configapi.DenyAllPasswordIdentityProvider): return denypassword.New(), nil case (*configapi.LDAPPasswordIdentityProvider): url, err := ldappassword.ParseURL(provider.URL) if err != nil { return nil, fmt.Errorf("Error parsing LDAPPasswordIdentityProvider URL: %v", err) } tlsConfig := &tls.Config{} if len(provider.CA) > 0 { roots, err := util.CertPoolFromFile(provider.CA) if err != nil { return nil, fmt.Errorf("error loading cert pool from ca file %s: %v", provider.CA, err) } tlsConfig.RootCAs = roots } opts := ldappassword.Options{ URL: url, Insecure: provider.Insecure, TLSConfig: tlsConfig, BindDN: provider.BindDN, BindPassword: provider.BindPassword, AttributeEmail: provider.Attributes.Email, AttributeName: provider.Attributes.Name, AttributeID: provider.Attributes.ID, AttributePreferredUsername: provider.Attributes.PreferredUsername, } return ldappassword.New(identityProvider.Name, opts, identityMapper) case (*configapi.HTPasswdPasswordIdentityProvider): htpasswdFile := provider.File if len(htpasswdFile) == 0 { return nil, fmt.Errorf("HTPasswdFile is required to support htpasswd auth") } if htpasswordAuth, err := htpasswd.New(identityProvider.Name, htpasswdFile, identityMapper); err != nil { return nil, fmt.Errorf("Error loading htpasswd file %s: %v", htpasswdFile, err) } else { return htpasswordAuth, nil } case (*configapi.BasicAuthPasswordIdentityProvider): connectionInfo := provider.RemoteConnectionInfo if len(connectionInfo.URL) == 0 { return nil, fmt.Errorf("URL is required for BasicAuthPasswordIdentityProvider") } transport, err := cmdutil.TransportFor(connectionInfo.CA, connectionInfo.ClientCert.CertFile, connectionInfo.ClientCert.KeyFile) if err != nil { return nil, fmt.Errorf("Error building BasicAuthPasswordIdentityProvider client: %v", err) } return basicauthpassword.New(identityProvider.Name, connectionInfo.URL, transport, identityMapper), nil default: return nil, fmt.Errorf("No password auth found that matches %v. The OAuth server cannot start!", identityProvider) } }