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 := ldaputil.ParseURL(provider.URL) if err != nil { return nil, fmt.Errorf("Error parsing LDAPPasswordIdentityProvider URL: %v", err) } clientConfig, err := ldaputil.NewLDAPClientConfig(provider.URL, provider.BindDN, provider.BindPassword, provider.CA, provider.Insecure) if err != nil { return nil, err } opts := ldappassword.Options{ URL: url, ClientConfig: clientConfig, UserAttributeDefiner: ldaputil.NewLDAPUserAttributeDefiner(provider.Attributes), } 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) } }
func ValidateLDAPIdentityProvider(provider *api.LDAPPasswordIdentityProvider) ValidationResults { validationResults := ValidationResults{} if len(provider.URL) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("provider.url")) return validationResults } u, err := ldaputil.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 == ldaputil.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.LDAPEntryAttributeMapping.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 ValidateLDAPClientConfig(url, bindDN, bindPassword, CA string, insecure bool) ValidationResults { validationResults := ValidationResults{} if len(url) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("url")) return validationResults } u, err := ldaputil.ParseURL(url) if err != nil { validationResults.AddErrors(fielderrors.NewFieldInvalid("url", 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(bindDN) == 0) != (len(bindPassword) == 0) { validationResults.AddErrors(fielderrors.NewFieldInvalid("bindDN", bindDN, "bindDN and bindPassword must both be specified, or both be empty")) validationResults.AddErrors(fielderrors.NewFieldInvalid("bindPassword", "<masked>", "bindDN and bindPassword must both be specified, or both be empty")) } if insecure { if u.Scheme == ldaputil.SchemeLDAPS { validationResults.AddErrors(fielderrors.NewFieldInvalid("url", url, fmt.Sprintf("Cannot use %s scheme with insecure=true", u.Scheme))) } if len(CA) > 0 { validationResults.AddErrors(fielderrors.NewFieldInvalid("ca", CA, "Cannot specify a ca with insecure=true")) } } else { if len(CA) > 0 { validationResults.AddErrors(ValidateFile(CA, "ca")...) } } // Warn if insecure if insecure { validationResults.AddWarnings(fielderrors.NewFieldInvalid("insecure", insecure, "validating passwords over an insecure connection could allow them to be intercepted")) } return validationResults }