diff --git a/cmd/authelia/main.go b/cmd/authelia/main.go index d2c20e6fc..58a92592e 100644 --- a/cmd/authelia/main.go +++ b/cmd/authelia/main.go @@ -36,7 +36,7 @@ func startServer() { os.Exit(1) } - autheliaCertPool, errs, nonFatalErrs := utils.NewX509CertPool(config.CertificatesDirectory, config) + autheliaCertPool, errs, nonFatalErrs := utils.NewX509CertPool(config.CertificatesDirectory) if len(errs) > 0 { for _, err := range errs { logger.Error(err) @@ -89,8 +89,8 @@ func startServer() { switch { case config.AuthenticationBackend.File != nil: userProvider = authentication.NewFileUserProvider(config.AuthenticationBackend.File) - case config.AuthenticationBackend.Ldap != nil: - userProvider = authentication.NewLDAPUserProvider(*config.AuthenticationBackend.Ldap, autheliaCertPool) + case config.AuthenticationBackend.LDAP != nil: + userProvider = authentication.NewLDAPUserProvider(*config.AuthenticationBackend.LDAP, autheliaCertPool) default: logger.Fatalf("Unrecognized authentication backend") } diff --git a/config.template.yml b/config.template.yml index b18794508..ef1df435f 100644 --- a/config.template.yml +++ b/config.template.yml @@ -162,8 +162,6 @@ authentication_backend: ## - {input} is a placeholder replaced by what the user inputs in the login form. ## - {username_attribute} is a mandatory placeholder replaced by what is configured in `username_attribute`. ## - {mail_attribute} is a placeholder replaced by what is configured in `mail_attribute`. - ## - DON'T USE - {0} is an alias for {input} supported for backward compatibility but it will be deprecated in later - ## versions, so please don't use it. ## ## Recommended settings are as follows: ## - Microsoft Active Directory: (&({username_attribute}={input})(objectCategory=person)(objectClass=user)) @@ -185,10 +183,6 @@ authentication_backend: ## - {dn} is a matcher replaced by the user distinguished name, aka, user DN. ## - {username_attribute} is a placeholder replaced by what is configured in `username_attribute`. ## - {mail_attribute} is a placeholder replaced by what is configured in `mail_attribute`. - ## - DON'T USE - {0} is an alias for {input} supported for backward compatibility but it will be deprecated in later - ## versions, so please don't use it. - ## - DON'T USE - {1} is an alias for {username} supported for backward compatibility but it will be deprecated in - ## later version, so please don't use it. ## ## If your groups use the `groupOfUniqueNames` structure use this instead: ## (&(uniquemember={dn})(objectclass=groupOfUniqueNames)) diff --git a/docs/configuration/authentication/ldap.md b/docs/configuration/authentication/ldap.md index d16b48e70..6c896d245 100644 --- a/docs/configuration/authentication/ldap.md +++ b/docs/configuration/authentication/ldap.md @@ -148,7 +148,11 @@ Similar to [additional_users_dn](#additional_users_dn) but it applies to group s ### groups_filter -Similar to [users_filter](#users_filter) but it applies to group searches. +Similar to [users_filter](#users_filter) but it applies to group searches. In order to include groups the memeber is not +a direct member of, but is a member of another group that is a member of those (i.e. recursive groups), you may try +using the following filter which is currently only tested against Microsoft Active Directory: + +`(&(member:1.2.840.113556.1.4.1941:={dn})(objectClass=group)(objectCategory=group))` ### mail_attribute diff --git a/internal/authentication/ldap_user_provider.go b/internal/authentication/ldap_user_provider.go index af3b44c0f..a6b3bbe2d 100644 --- a/internal/authentication/ldap_user_provider.go +++ b/internal/authentication/ldap_user_provider.go @@ -62,27 +62,6 @@ func NewLDAPUserProviderWithFactory(configuration schema.LDAPAuthenticationBacke } func (p *LDAPUserProvider) parseDynamicConfiguration() { - // Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28. - if strings.Contains(p.configuration.UsersFilter, "{0}") { - p.logger.Warnf("DEPRECATION NOTICE: LDAP Users Filter will no longer support replacing `{0}` in 4.28.0. Please use `{input}` instead.") - - p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{0}", "{input}") - } - - // Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28. - if strings.Contains(p.configuration.GroupsFilter, "{0}") { - p.logger.Warnf("DEPRECATION NOTICE: LDAP Groups Filter will no longer support replacing `{0}` in 4.28.0. Please use `{input}` instead.") - - p.configuration.GroupsFilter = strings.ReplaceAll(p.configuration.GroupsFilter, "{0}", "{input}") - } - - // Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28. - if strings.Contains(p.configuration.GroupsFilter, "{1}") { - p.logger.Warnf("DEPRECATION NOTICE: LDAP Groups Filter will no longer support replacing `{1}` in 4.28.0. Please use `{username}` instead.") - - p.configuration.GroupsFilter = strings.ReplaceAll(p.configuration.GroupsFilter, "{1}", "{username}") - } - p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{username_attribute}", p.configuration.UsernameAttribute) p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{mail_attribute}", p.configuration.MailAttribute) p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{display_name_attribute}", p.configuration.DisplayNameAttribute) diff --git a/internal/authentication/ldap_user_provider_test.go b/internal/authentication/ldap_user_provider_test.go index 05a6a60ea..5913df0d2 100644 --- a/internal/authentication/ldap_user_provider_test.go +++ b/internal/authentication/ldap_user_provider_test.go @@ -713,8 +713,8 @@ func TestShouldParseDynamicConfiguration(t *testing.T) { UsernameAttribute: "uid", MailAttribute: "mail", DisplayNameAttribute: "displayname", - UsersFilter: "(&(|({username_attribute}={0})({mail_attribute}={0})({display_name_attribute}={0}))(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!pwdLastSet=0))", - GroupsFilter: "(&(|(member={dn})(member={0})(member={1}))(objectClass=group))", + UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input})({display_name_attribute}={input}))(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!pwdLastSet=0))", + GroupsFilter: "(&(|(member={dn})(member={input})(member={username}))(objectClass=group))", AdditionalUsersDN: "ou=users", AdditionalGroupsDN: "ou=groups", BaseDN: "dc=example,dc=com", diff --git a/internal/configuration/config.template.yml b/internal/configuration/config.template.yml index b18794508..ef1df435f 100644 --- a/internal/configuration/config.template.yml +++ b/internal/configuration/config.template.yml @@ -162,8 +162,6 @@ authentication_backend: ## - {input} is a placeholder replaced by what the user inputs in the login form. ## - {username_attribute} is a mandatory placeholder replaced by what is configured in `username_attribute`. ## - {mail_attribute} is a placeholder replaced by what is configured in `mail_attribute`. - ## - DON'T USE - {0} is an alias for {input} supported for backward compatibility but it will be deprecated in later - ## versions, so please don't use it. ## ## Recommended settings are as follows: ## - Microsoft Active Directory: (&({username_attribute}={input})(objectCategory=person)(objectClass=user)) @@ -185,10 +183,6 @@ authentication_backend: ## - {dn} is a matcher replaced by the user distinguished name, aka, user DN. ## - {username_attribute} is a placeholder replaced by what is configured in `username_attribute`. ## - {mail_attribute} is a placeholder replaced by what is configured in `mail_attribute`. - ## - DON'T USE - {0} is an alias for {input} supported for backward compatibility but it will be deprecated in later - ## versions, so please don't use it. - ## - DON'T USE - {1} is an alias for {username} supported for backward compatibility but it will be deprecated in - ## later version, so please don't use it. ## ## If your groups use the `groupOfUniqueNames` structure use this instead: ## (&(uniquemember={dn})(objectclass=groupOfUniqueNames)) diff --git a/internal/configuration/reader_test.go b/internal/configuration/reader_test.go index 3fe72b2bd..c768cf815 100644 --- a/internal/configuration/reader_test.go +++ b/internal/configuration/reader_test.go @@ -195,7 +195,7 @@ func TestShouldParseConfigFile(t *testing.T) { assert.Equal(t, "duo_secret_from_env", config.DuoAPI.SecretKey) assert.Equal(t, "session_secret_from_env", config.Session.Secret) - assert.Equal(t, "ldap_secret_from_env", config.AuthenticationBackend.Ldap.Password) + assert.Equal(t, "ldap_secret_from_env", config.AuthenticationBackend.LDAP.Password) assert.Equal(t, "smtp_secret_from_env", config.Notifier.SMTP.Password) assert.Equal(t, "redis_secret_from_env", config.Session.Redis.Password) assert.Equal(t, "redis-sentinel_secret_from_env", config.Session.Redis.HighAvailability.SentinelPassword) @@ -253,7 +253,7 @@ func TestShouldNotParseConfigFileWithOldOrUnexpectedKeys(t *testing.T) { return errors[i].Error() < errors[j].Error() }) assert.EqualError(t, errors[0], "config key not expected: loggy_file") - assert.EqualError(t, errors[1], "config key replaced: logs_level is now log_level") + assert.EqualError(t, errors[1], "invalid configuration key 'logs_level' was replaced by 'log_level'") } func TestShouldValidateConfigurationTemplate(t *testing.T) { diff --git a/internal/configuration/schema/authentication.go b/internal/configuration/schema/authentication.go index 56a633c6e..588298839 100644 --- a/internal/configuration/schema/authentication.go +++ b/internal/configuration/schema/authentication.go @@ -17,8 +17,6 @@ type LDAPAuthenticationBackendConfiguration struct { Password string `mapstructure:"password"` StartTLS bool `mapstructure:"start_tls"` TLS *TLSConfig `mapstructure:"tls"` - SkipVerify *bool `mapstructure:"skip_verify"` // Deprecated: Replaced with LDAPAuthenticationBackendConfiguration.TLS.SkipVerify. TODO: Remove in 4.28. - MinimumTLSVersion string `mapstructure:"minimum_tls_version"` // Deprecated: Replaced with LDAPAuthenticationBackendConfiguration.TLS.MinimumVersion. TODO: Remove in 4.28. } // FileAuthenticationBackendConfiguration represents the configuration related to file-based backend. @@ -41,7 +39,7 @@ type PasswordConfiguration struct { type AuthenticationBackendConfiguration struct { DisableResetPassword bool `mapstructure:"disable_reset_password"` RefreshInterval string `mapstructure:"refresh_interval"` - Ldap *LDAPAuthenticationBackendConfiguration `mapstructure:"ldap"` + LDAP *LDAPAuthenticationBackendConfiguration `mapstructure:"ldap"` File *FileAuthenticationBackendConfiguration `mapstructure:"file"` } diff --git a/internal/configuration/schema/notifier.go b/internal/configuration/schema/notifier.go index 58c5428c6..bb6b878bd 100644 --- a/internal/configuration/schema/notifier.go +++ b/internal/configuration/schema/notifier.go @@ -18,8 +18,6 @@ type SMTPNotifierConfiguration struct { DisableRequireTLS bool `mapstructure:"disable_require_tls"` DisableHTMLEmails bool `mapstructure:"disable_html_emails"` TLS *TLSConfig `mapstructure:"tls"` - TrustedCert string `mapstructure:"trusted_cert"` // Deprecated: Replaced with Global Option CertificatesDirectory. TODO: Remove in 4.28. - DisableVerifyCert *bool `mapstructure:"disable_verify_cert"` // Deprecated: Replaced with LDAPAuthenticationBackendConfiguration.TLS.SkipVerify. TODO: Remove in 4.28. } // NotifierConfiguration represents the configuration of the notifier to use when sending notifications to users. diff --git a/internal/configuration/validator/authentication.go b/internal/configuration/validator/authentication.go index 38259697f..82bd48ca4 100644 --- a/internal/configuration/validator/authentication.go +++ b/internal/configuration/validator/authentication.go @@ -10,6 +10,32 @@ import ( "github.com/authelia/authelia/internal/utils" ) +// ValidateAuthenticationBackend validates and update authentication backend configuration. +func ValidateAuthenticationBackend(configuration *schema.AuthenticationBackendConfiguration, validator *schema.StructValidator) { + if configuration.LDAP == nil && configuration.File == nil { + validator.Push(errors.New("Please provide `ldap` or `file` object in `authentication_backend`")) + } + + if configuration.LDAP != nil && configuration.File != nil { + validator.Push(errors.New("You cannot provide both `ldap` and `file` objects in `authentication_backend`")) + } + + if configuration.File != nil { + validateFileAuthenticationBackend(configuration.File, validator) + } else if configuration.LDAP != nil { + validateLDAPAuthenticationBackend(configuration.LDAP, validator) + } + + if configuration.RefreshInterval == "" { + configuration.RefreshInterval = schema.RefreshIntervalDefault + } else { + _, err := utils.ParseDurationString(configuration.RefreshInterval) + if err != nil && configuration.RefreshInterval != schema.ProfileRefreshDisabled && configuration.RefreshInterval != schema.ProfileRefreshAlways { + validator.Push(fmt.Errorf("Auth Backend `refresh_interval` is configured to '%s' but it must be either a duration notation or one of 'disable', or 'always'. Error from parser: %s", configuration.RefreshInterval, err)) + } + } +} + //nolint:gocyclo // TODO: Consider refactoring/simplifying, time permitting. func validateFileAuthenticationBackend(configuration *schema.FileAuthenticationBackendConfiguration, validator *schema.StructValidator) { if configuration.Path == "" { @@ -72,14 +98,66 @@ func validateFileAuthenticationBackend(configuration *schema.FileAuthenticationB } } +func validateLDAPAuthenticationBackend(configuration *schema.LDAPAuthenticationBackendConfiguration, validator *schema.StructValidator) { + if configuration.Implementation == "" { + configuration.Implementation = schema.DefaultLDAPAuthenticationBackendConfiguration.Implementation + } + + if configuration.TLS == nil { + configuration.TLS = schema.DefaultLDAPAuthenticationBackendConfiguration.TLS + } + + if configuration.TLS.MinimumVersion == "" { + configuration.TLS.MinimumVersion = schema.DefaultLDAPAuthenticationBackendConfiguration.TLS.MinimumVersion + } + + if _, err := utils.TLSStringToTLSConfigVersion(configuration.TLS.MinimumVersion); err != nil { + validator.Push(fmt.Errorf("error occurred validating the LDAP minimum_tls_version key with value %s: %v", configuration.TLS.MinimumVersion, err)) + } + + switch configuration.Implementation { + case schema.LDAPImplementationCustom: + setDefaultImplementationCustomLDAPAuthenticationBackend(configuration) + case schema.LDAPImplementationActiveDirectory: + setDefaultImplementationActiveDirectoryLDAPAuthenticationBackend(configuration) + default: + validator.Push(fmt.Errorf("authentication backend ldap implementation must be blank or one of the following values `%s`, `%s`", schema.LDAPImplementationCustom, schema.LDAPImplementationActiveDirectory)) + } + + if strings.Contains(configuration.UsersFilter, "{0}") { + validator.Push(fmt.Errorf("authentication backend ldap users filter must not contain removed placeholders" + + ", {0} has been replaced with {input}")) + } + + if strings.Contains(configuration.GroupsFilter, "{0}") || + strings.Contains(configuration.GroupsFilter, "{1}") { + validator.Push(fmt.Errorf("authentication backend ldap groups filter must not contain removed " + + "placeholders, {0} has been replaced with {input} and {1} has been replaced with {username}")) + } + + if configuration.URL == "" { + validator.Push(errors.New("Please provide a URL to the LDAP server")) + } else { + ldapURL, serverName := validateLDAPURL(configuration.URL, validator) + + configuration.URL = ldapURL + + if configuration.TLS.ServerName == "" { + configuration.TLS.ServerName = serverName + } + } + + validateLDAPRequiredParameters(configuration, validator) +} + // Wrapper for test purposes to exclude the hostname from the return. -func validateLdapURLSimple(ldapURL string, validator *schema.StructValidator) (finalURL string) { - finalURL, _ = validateLdapURL(ldapURL, validator) +func validateLDAPURLSimple(ldapURL string, validator *schema.StructValidator) (finalURL string) { + finalURL, _ = validateLDAPURL(ldapURL, validator) return finalURL } -func validateLdapURL(ldapURL string, validator *schema.StructValidator) (finalURL string, hostname string) { +func validateLDAPURL(ldapURL string, validator *schema.StructValidator) (finalURL string, hostname string) { parsedURL, err := url.Parse(ldapURL) if err != nil { @@ -95,64 +173,7 @@ func validateLdapURL(ldapURL string, validator *schema.StructValidator) (finalUR return parsedURL.String(), parsedURL.Hostname() } -//nolint:gocyclo // TODO: Consider refactoring/simplifying, time permitting. -func validateLdapAuthenticationBackend(configuration *schema.LDAPAuthenticationBackendConfiguration, validator *schema.StructValidator) { - if configuration.Implementation == "" { - configuration.Implementation = schema.DefaultLDAPAuthenticationBackendConfiguration.Implementation - } - - nilTLS := configuration.TLS == nil - if nilTLS { - configuration.TLS = schema.DefaultLDAPAuthenticationBackendConfiguration.TLS - } - - // Deprecated. Maps deprecated values to the new ones. TODO: Remove in 4.28 (if block). - if configuration.SkipVerify != nil { - validator.PushWarning(errors.New("DEPRECATED: LDAP Auth Backend `skip_verify` option has been replaced by `authentication_backend.ldap.tls.skip_verify` (will be removed in 4.28.0)")) - - if nilTLS { - configuration.TLS.SkipVerify = *configuration.SkipVerify - } - } - - // Deprecated. Maps deprecated values to the new ones. TODO: Remove in 4.28 (if block). - if configuration.MinimumTLSVersion != "" { - validator.PushWarning(errors.New("DEPRECATED: LDAP Auth Backend `minimum_tls_version` option has been replaced by `authentication_backend.ldap.tls.minimum_version` (will be removed in 4.28.0)")) - - if nilTLS { - configuration.TLS.MinimumVersion = configuration.MinimumTLSVersion - } - } - - if configuration.TLS.MinimumVersion == "" { - configuration.TLS.MinimumVersion = schema.DefaultLDAPAuthenticationBackendConfiguration.TLS.MinimumVersion - } - - if _, err := utils.TLSStringToTLSConfigVersion(configuration.TLS.MinimumVersion); err != nil { - validator.Push(fmt.Errorf("error occurred validating the LDAP minimum_tls_version key with value %s: %v", configuration.TLS.MinimumVersion, err)) - } - - switch configuration.Implementation { - case schema.LDAPImplementationCustom: - setDefaultImplementationCustomLdapAuthenticationBackend(configuration) - case schema.LDAPImplementationActiveDirectory: - setDefaultImplementationActiveDirectoryLdapAuthenticationBackend(configuration) - default: - validator.Push(fmt.Errorf("authentication backend ldap implementation must be blank or one of the following values `%s`, `%s`", schema.LDAPImplementationCustom, schema.LDAPImplementationActiveDirectory)) - } - - if configuration.URL == "" { - validator.Push(errors.New("Please provide a URL to the LDAP server")) - } else { - ldapURL, serverName := validateLdapURL(configuration.URL, validator) - - configuration.URL = ldapURL - - if configuration.TLS.ServerName == "" { - configuration.TLS.ServerName = serverName - } - } - +func validateLDAPRequiredParameters(configuration *schema.LDAPAuthenticationBackendConfiguration, validator *schema.StructValidator) { // TODO: see if it's possible to disable this check if disable_reset_password is set and when anonymous/user binding is supported (#101 and #387) if configuration.User == "" { validator.Push(errors.New("Please provide a user name to connect to the LDAP server")) @@ -193,7 +214,7 @@ func validateLdapAuthenticationBackend(configuration *schema.LDAPAuthenticationB } } -func setDefaultImplementationActiveDirectoryLdapAuthenticationBackend(configuration *schema.LDAPAuthenticationBackendConfiguration) { +func setDefaultImplementationActiveDirectoryLDAPAuthenticationBackend(configuration *schema.LDAPAuthenticationBackendConfiguration) { if configuration.UsersFilter == "" { configuration.UsersFilter = schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.UsersFilter } @@ -219,7 +240,7 @@ func setDefaultImplementationActiveDirectoryLdapAuthenticationBackend(configurat } } -func setDefaultImplementationCustomLdapAuthenticationBackend(configuration *schema.LDAPAuthenticationBackendConfiguration) { +func setDefaultImplementationCustomLDAPAuthenticationBackend(configuration *schema.LDAPAuthenticationBackendConfiguration) { if configuration.UsernameAttribute == "" { configuration.UsernameAttribute = schema.DefaultLDAPAuthenticationBackendConfiguration.UsernameAttribute } @@ -236,29 +257,3 @@ func setDefaultImplementationCustomLdapAuthenticationBackend(configuration *sche configuration.DisplayNameAttribute = schema.DefaultLDAPAuthenticationBackendConfiguration.DisplayNameAttribute } } - -// ValidateAuthenticationBackend validates and update authentication backend configuration. -func ValidateAuthenticationBackend(configuration *schema.AuthenticationBackendConfiguration, validator *schema.StructValidator) { - if configuration.Ldap == nil && configuration.File == nil { - validator.Push(errors.New("Please provide `ldap` or `file` object in `authentication_backend`")) - } - - if configuration.Ldap != nil && configuration.File != nil { - validator.Push(errors.New("You cannot provide both `ldap` and `file` objects in `authentication_backend`")) - } - - if configuration.File != nil { - validateFileAuthenticationBackend(configuration.File, validator) - } else if configuration.Ldap != nil { - validateLdapAuthenticationBackend(configuration.Ldap, validator) - } - - if configuration.RefreshInterval == "" { - configuration.RefreshInterval = schema.RefreshIntervalDefault - } else { - _, err := utils.ParseDurationString(configuration.RefreshInterval) - if err != nil && configuration.RefreshInterval != schema.ProfileRefreshDisabled && configuration.RefreshInterval != schema.ProfileRefreshAlways { - validator.Push(fmt.Errorf("Auth Backend `refresh_interval` is configured to '%s' but it must be either a duration notation or one of 'disable', or 'always'. Error from parser: %s", configuration.RefreshInterval, err)) - } - } -} diff --git a/internal/configuration/validator/authentication_test.go b/internal/configuration/validator/authentication_test.go index 160ecceb9..95c2016b0 100644 --- a/internal/configuration/validator/authentication_test.go +++ b/internal/configuration/validator/authentication_test.go @@ -14,7 +14,7 @@ func TestShouldRaiseErrorWhenBothBackendsProvided(t *testing.T) { validator := schema.NewStructValidator() backendConfig := schema.AuthenticationBackendConfiguration{} - backendConfig.Ldap = &schema.LDAPAuthenticationBackendConfiguration{} + backendConfig.LDAP = &schema.LDAPAuthenticationBackendConfiguration{} backendConfig.File = &schema.FileAuthenticationBackendConfiguration{ Path: "/tmp", } @@ -202,47 +202,47 @@ func TestFileBasedAuthenticationBackend(t *testing.T) { suite.Run(t, new(FileBasedAuthenticationBackend)) } -type LdapAuthenticationBackendSuite struct { +type LDAPAuthenticationBackendSuite struct { suite.Suite configuration schema.AuthenticationBackendConfiguration validator *schema.StructValidator } -func (suite *LdapAuthenticationBackendSuite) SetupTest() { +func (suite *LDAPAuthenticationBackendSuite) SetupTest() { suite.validator = schema.NewStructValidator() suite.configuration = schema.AuthenticationBackendConfiguration{} - suite.configuration.Ldap = &schema.LDAPAuthenticationBackendConfiguration{} - suite.configuration.Ldap.Implementation = schema.LDAPImplementationCustom - suite.configuration.Ldap.URL = testLDAPURL - suite.configuration.Ldap.User = testLDAPUser - suite.configuration.Ldap.Password = testLDAPPassword - suite.configuration.Ldap.BaseDN = testLDAPBaseDN - suite.configuration.Ldap.UsernameAttribute = "uid" - suite.configuration.Ldap.UsersFilter = "({username_attribute}={input})" - suite.configuration.Ldap.GroupsFilter = "(cn={input})" + suite.configuration.LDAP = &schema.LDAPAuthenticationBackendConfiguration{} + suite.configuration.LDAP.Implementation = schema.LDAPImplementationCustom + suite.configuration.LDAP.URL = testLDAPURL + suite.configuration.LDAP.User = testLDAPUser + suite.configuration.LDAP.Password = testLDAPPassword + suite.configuration.LDAP.BaseDN = testLDAPBaseDN + suite.configuration.LDAP.UsernameAttribute = "uid" + suite.configuration.LDAP.UsersFilter = "({username_attribute}={input})" + suite.configuration.LDAP.GroupsFilter = "(cn={input})" } -func (suite *LdapAuthenticationBackendSuite) TestShouldValidateCompleteConfiguration() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldValidateCompleteConfiguration() { ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) suite.Assert().False(suite.validator.HasErrors()) } -func (suite *LdapAuthenticationBackendSuite) TestShouldValidateDefaultImplementationAndUsernameAttribute() { - suite.configuration.Ldap.Implementation = "" - suite.configuration.Ldap.UsernameAttribute = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldValidateDefaultImplementationAndUsernameAttribute() { + suite.configuration.LDAP.Implementation = "" + suite.configuration.LDAP.UsernameAttribute = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) - suite.Assert().Equal(schema.LDAPImplementationCustom, suite.configuration.Ldap.Implementation) + suite.Assert().Equal(schema.LDAPImplementationCustom, suite.configuration.LDAP.Implementation) - suite.Assert().Equal(suite.configuration.Ldap.UsernameAttribute, schema.DefaultLDAPAuthenticationBackendConfiguration.UsernameAttribute) + suite.Assert().Equal(suite.configuration.LDAP.UsernameAttribute, schema.DefaultLDAPAuthenticationBackendConfiguration.UsernameAttribute) suite.Assert().False(suite.validator.HasWarnings()) suite.Assert().False(suite.validator.HasErrors()) } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenImplementationIsInvalidMSAD() { - suite.configuration.Ldap.Implementation = "masd" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenImplementationIsInvalidMSAD() { + suite.configuration.LDAP.Implementation = "masd" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -252,8 +252,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenImplementat suite.Assert().EqualError(suite.validator.Errors()[0], "authentication backend ldap implementation must be blank or one of the following values `custom`, `activedirectory`") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenURLNotProvided() { - suite.configuration.Ldap.URL = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenURLNotProvided() { + suite.configuration.LDAP.URL = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) @@ -262,8 +262,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenURLNotProvi suite.Assert().EqualError(suite.validator.Errors()[0], "Please provide a URL to the LDAP server") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenUserNotProvided() { - suite.configuration.Ldap.User = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenUserNotProvided() { + suite.configuration.LDAP.User = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -273,8 +273,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenUserNotProv suite.Assert().EqualError(suite.validator.Errors()[0], "Please provide a user name to connect to the LDAP server") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenPasswordNotProvided() { - suite.configuration.Ldap.Password = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenPasswordNotProvided() { + suite.configuration.LDAP.Password = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -284,8 +284,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenPasswordNot suite.Assert().EqualError(suite.validator.Errors()[0], "Please provide a password to connect to the LDAP server") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenBaseDNNotProvided() { - suite.configuration.Ldap.BaseDN = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenBaseDNNotProvided() { + suite.configuration.LDAP.BaseDN = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -295,8 +295,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseErrorWhenBaseDNNotPr suite.Assert().EqualError(suite.validator.Errors()[0], "Please provide a base DN to connect to the LDAP server") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseOnEmptyGroupsFilter() { - suite.configuration.Ldap.GroupsFilter = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseOnEmptyGroupsFilter() { + suite.configuration.LDAP.GroupsFilter = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -306,8 +306,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseOnEmptyGroupsFilter( suite.Assert().EqualError(suite.validator.Errors()[0], "Please provide a groups filter with `groups_filter` attribute") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseOnEmptyUsersFilter() { - suite.configuration.Ldap.UsersFilter = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseOnEmptyUsersFilter() { + suite.configuration.LDAP.UsersFilter = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -317,8 +317,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseOnEmptyUsersFilter() suite.Assert().EqualError(suite.validator.Errors()[0], "Please provide a users filter with `users_filter` attribute") } -func (suite *LdapAuthenticationBackendSuite) TestShouldNotRaiseOnEmptyUsernameAttribute() { - suite.configuration.Ldap.UsernameAttribute = "" +func (suite *LDAPAuthenticationBackendSuite) TestShouldNotRaiseOnEmptyUsernameAttribute() { + suite.configuration.LDAP.UsernameAttribute = "" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -326,7 +326,7 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldNotRaiseOnEmptyUsernameAt suite.Assert().False(suite.validator.HasErrors()) } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseOnBadRefreshInterval() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseOnBadRefreshInterval() { suite.configuration.RefreshInterval = "blah" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -337,43 +337,60 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseOnBadRefreshInterval suite.Assert().EqualError(suite.validator.Errors()[0], "Auth Backend `refresh_interval` is configured to 'blah' but it must be either a duration notation or one of 'disable', or 'always'. Error from parser: Could not convert the input string of blah into a duration") } -func (suite *LdapAuthenticationBackendSuite) TestShouldSetDefaultImplementation() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldSetDefaultImplementation() { ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) suite.Assert().False(suite.validator.HasErrors()) - suite.Assert().Equal(schema.LDAPImplementationCustom, suite.configuration.Ldap.Implementation) + suite.Assert().Equal(schema.LDAPImplementationCustom, suite.configuration.LDAP.Implementation) } -func (suite *LdapAuthenticationBackendSuite) TestShouldSetDefaultGroupNameAttribute() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorOnBadFilterPlaceholders() { + suite.configuration.LDAP.UsersFilter = "(&({username_attribute}={0})(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2))" + suite.configuration.LDAP.GroupsFilter = "(&(member={0})(objectClass=group)(objectCategory=group))" + + ValidateAuthenticationBackend(&suite.configuration, suite.validator) + + suite.Assert().False(suite.validator.HasWarnings()) + suite.Assert().True(suite.validator.HasErrors()) + + suite.Require().Len(suite.validator.Errors(), 2) + suite.Assert().EqualError(suite.validator.Errors()[0], "authentication backend ldap users filter must "+ + "not contain removed placeholders, {0} has been replaced with {input}") + suite.Assert().EqualError(suite.validator.Errors()[1], "authentication backend ldap groups filter must "+ + "not contain removed placeholders, "+ + "{0} has been replaced with {input} and {1} has been replaced with {username}") +} + +func (suite *LDAPAuthenticationBackendSuite) TestShouldSetDefaultGroupNameAttribute() { ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) suite.Assert().False(suite.validator.HasErrors()) - suite.Assert().Equal("cn", suite.configuration.Ldap.GroupNameAttribute) + suite.Assert().Equal("cn", suite.configuration.LDAP.GroupNameAttribute) } -func (suite *LdapAuthenticationBackendSuite) TestShouldSetDefaultMailAttribute() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldSetDefaultMailAttribute() { ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) suite.Assert().False(suite.validator.HasErrors()) - suite.Assert().Equal("mail", suite.configuration.Ldap.MailAttribute) + suite.Assert().Equal("mail", suite.configuration.LDAP.MailAttribute) } -func (suite *LdapAuthenticationBackendSuite) TestShouldSetDefaultDisplayNameAttribute() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldSetDefaultDisplayNameAttribute() { ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) suite.Assert().False(suite.validator.HasErrors()) - suite.Assert().Equal("displayname", suite.configuration.Ldap.DisplayNameAttribute) + suite.Assert().Equal("displayname", suite.configuration.LDAP.DisplayNameAttribute) } -func (suite *LdapAuthenticationBackendSuite) TestShouldSetDefaultRefreshInterval() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldSetDefaultRefreshInterval() { ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) @@ -382,8 +399,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldSetDefaultRefreshInterval suite.Assert().Equal("5m", suite.configuration.RefreshInterval) } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseWhenUsersFilterDoesNotContainEnclosingParenthesis() { - suite.configuration.Ldap.UsersFilter = "{username_attribute}={input}" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseWhenUsersFilterDoesNotContainEnclosingParenthesis() { + suite.configuration.LDAP.UsersFilter = "{username_attribute}={input}" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -393,8 +410,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseWhenUsersFilterDoesN suite.Assert().EqualError(suite.validator.Errors()[0], "The users filter should contain enclosing parenthesis. For instance {username_attribute}={input} should be ({username_attribute}={input})") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseWhenGroupsFilterDoesNotContainEnclosingParenthesis() { - suite.configuration.Ldap.GroupsFilter = "cn={input}" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseWhenGroupsFilterDoesNotContainEnclosingParenthesis() { + suite.configuration.LDAP.GroupsFilter = "cn={input}" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -404,8 +421,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseWhenGroupsFilterDoes suite.Assert().EqualError(suite.validator.Errors()[0], "The groups filter should contain enclosing parenthesis. For instance cn={input} should be (cn={input})") } -func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseWhenUsersFilterDoesNotContainUsernameAttribute() { - suite.configuration.Ldap.UsersFilter = "(&({mail_attribute}={input})(objectClass=person))" +func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseWhenUsersFilterDoesNotContainUsernameAttribute() { + suite.configuration.LDAP.UsersFilter = "(&({mail_attribute}={input})(objectClass=person))" ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) @@ -414,8 +431,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldRaiseWhenUsersFilterDoesN suite.Assert().EqualError(suite.validator.Errors()[0], "Unable to detect {username_attribute} placeholder in users_filter, your configuration is broken. Please review configuration options listed at https://www.authelia.com/docs/configuration/authentication/ldap.html") } -func (suite *LdapAuthenticationBackendSuite) TestShouldHelpDetectNoInputPlaceholder() { - suite.configuration.Ldap.UsersFilter = "(&({username_attribute}={mail_attribute})(objectClass=person))" +func (suite *LDAPAuthenticationBackendSuite) TestShouldHelpDetectNoInputPlaceholder() { + suite.configuration.LDAP.UsersFilter = "(&({username_attribute}={mail_attribute})(objectClass=person))" ValidateAuthenticationBackend(&suite.configuration, suite.validator) @@ -425,40 +442,42 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldHelpDetectNoInputPlacehol suite.Assert().EqualError(suite.validator.Errors()[0], "Unable to detect {input} placeholder in users_filter, your configuration might be broken. Please review configuration options listed at https://www.authelia.com/docs/configuration/authentication/ldap.html") } -func (suite *LdapAuthenticationBackendSuite) TestShouldAdaptLDAPURL() { - suite.Assert().Equal("", validateLdapURLSimple("127.0.0.1", suite.validator)) +func (suite *LDAPAuthenticationBackendSuite) TestShouldAdaptLDAPURL() { + suite.Assert().Equal("", validateLDAPURLSimple("127.0.0.1", suite.validator)) suite.Assert().False(suite.validator.HasWarnings()) suite.Require().Len(suite.validator.Errors(), 1) suite.Assert().EqualError(suite.validator.Errors()[0], "Unknown scheme for ldap url, should be ldap:// or ldaps://") - suite.Assert().Equal("", validateLdapURLSimple("127.0.0.1:636", suite.validator)) + suite.Assert().Equal("", validateLDAPURLSimple("127.0.0.1:636", suite.validator)) suite.Assert().False(suite.validator.HasWarnings()) suite.Require().Len(suite.validator.Errors(), 2) suite.Assert().EqualError(suite.validator.Errors()[1], "Unable to parse URL to ldap server. The scheme is probably missing: ldap:// or ldaps://") - suite.Assert().Equal("ldap://127.0.0.1", validateLdapURLSimple("ldap://127.0.0.1", suite.validator)) - suite.Assert().Equal("ldap://127.0.0.1:390", validateLdapURLSimple("ldap://127.0.0.1:390", suite.validator)) - suite.Assert().Equal("ldap://127.0.0.1/abc", validateLdapURLSimple("ldap://127.0.0.1/abc", suite.validator)) - suite.Assert().Equal("ldap://127.0.0.1/abc?test=abc&x=y", validateLdapURLSimple("ldap://127.0.0.1/abc?test=abc&x=y", suite.validator)) + suite.Assert().Equal("ldap://127.0.0.1", validateLDAPURLSimple("ldap://127.0.0.1", suite.validator)) + suite.Assert().Equal("ldap://127.0.0.1:390", validateLDAPURLSimple("ldap://127.0.0.1:390", suite.validator)) + suite.Assert().Equal("ldap://127.0.0.1/abc", validateLDAPURLSimple("ldap://127.0.0.1/abc", suite.validator)) + suite.Assert().Equal("ldap://127.0.0.1/abc?test=abc&x=y", validateLDAPURLSimple("ldap://127.0.0.1/abc?test=abc&x=y", suite.validator)) - suite.Assert().Equal("ldaps://127.0.0.1:390", validateLdapURLSimple("ldaps://127.0.0.1:390", suite.validator)) - suite.Assert().Equal("ldaps://127.0.0.1", validateLdapURLSimple("ldaps://127.0.0.1", suite.validator)) + suite.Assert().Equal("ldaps://127.0.0.1:390", validateLDAPURLSimple("ldaps://127.0.0.1:390", suite.validator)) + suite.Assert().Equal("ldaps://127.0.0.1", validateLDAPURLSimple("ldaps://127.0.0.1", suite.validator)) } -func (suite *LdapAuthenticationBackendSuite) TestShouldDefaultTLS12() { +func (suite *LDAPAuthenticationBackendSuite) TestShouldSetDefaultTLSMinimumVersion() { + suite.configuration.LDAP.TLS = &schema.TLSConfig{MinimumVersion: ""} + ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().False(suite.validator.HasWarnings()) suite.Assert().False(suite.validator.HasErrors()) - suite.Assert().Equal(schema.DefaultLDAPAuthenticationBackendConfiguration.MinimumTLSVersion, suite.configuration.Ldap.MinimumTLSVersion) + suite.Assert().Equal(schema.DefaultLDAPAuthenticationBackendConfiguration.TLS.MinimumVersion, suite.configuration.LDAP.TLS.MinimumVersion) } -func (suite *LdapAuthenticationBackendSuite) TestShouldNotAllowInvalidTLSValue() { - suite.configuration.Ldap.TLS = &schema.TLSConfig{ +func (suite *LDAPAuthenticationBackendSuite) TestShouldNotAllowInvalidTLSValue() { + suite.configuration.LDAP.TLS = &schema.TLSConfig{ MinimumVersion: "SSL2.0", } @@ -470,59 +489,8 @@ func (suite *LdapAuthenticationBackendSuite) TestShouldNotAllowInvalidTLSValue() suite.Assert().EqualError(suite.validator.Errors()[0], "error occurred validating the LDAP minimum_tls_version key with value SSL2.0: supplied TLS version isn't supported") } -// Deprecated: Temporary Test. TODO: Remove in 4.28 (Whole Test). -func (suite *LdapAuthenticationBackendSuite) TestShouldReturnDeprecationWarningsAndNoMappingFor428() { - var skipVerify = true - - suite.configuration.Ldap.MinimumTLSVersion = "TLS1.0" - suite.configuration.Ldap.SkipVerify = &skipVerify - suite.configuration.Ldap.TLS = nil - suite.configuration.Ldap.TLS = &schema.TLSConfig{ - ServerName: "golang.org", - MinimumVersion: "", - } - - ValidateAuthenticationBackend(&suite.configuration, suite.validator) - - // Should not override since TLS schema is defined - suite.Assert().Equal(false, suite.configuration.Ldap.TLS.SkipVerify) - suite.Assert().Equal(schema.DefaultLDAPAuthenticationBackendConfiguration.TLS.MinimumVersion, suite.configuration.Ldap.TLS.MinimumVersion) - - suite.Assert().False(suite.validator.HasErrors()) - suite.Require().Len(suite.validator.Warnings(), 2) - - warnings := suite.validator.Warnings() - - suite.Assert().EqualError(warnings[0], "DEPRECATED: LDAP Auth Backend `skip_verify` option has been replaced by `authentication_backend.ldap.tls.skip_verify` (will be removed in 4.28.0)") - suite.Assert().EqualError(warnings[1], "DEPRECATED: LDAP Auth Backend `minimum_tls_version` option has been replaced by `authentication_backend.ldap.tls.minimum_version` (will be removed in 4.28.0)") -} - -// Deprecated: Temporary Test. TODO: Remove in 4.28 (Whole Test). -func (suite *LdapAuthenticationBackendSuite) TestShouldReturnDeprecationWarningsAndMappingFor428() { - var skipVerify = true - - tlsVersion := "TLS1.1" - - suite.configuration.Ldap.MinimumTLSVersion = tlsVersion - suite.configuration.Ldap.SkipVerify = &skipVerify - - ValidateAuthenticationBackend(&suite.configuration, suite.validator) - - // Should override since TLS schema is not defined - suite.Assert().Equal(true, suite.configuration.Ldap.TLS.SkipVerify) - suite.Assert().Equal(tlsVersion, suite.configuration.Ldap.TLS.MinimumVersion) - - suite.Assert().False(suite.validator.HasErrors()) - suite.Require().Len(suite.validator.Warnings(), 2) - - warnings := suite.validator.Warnings() - - suite.Assert().EqualError(warnings[0], "DEPRECATED: LDAP Auth Backend `skip_verify` option has been replaced by `authentication_backend.ldap.tls.skip_verify` (will be removed in 4.28.0)") - suite.Assert().EqualError(warnings[1], "DEPRECATED: LDAP Auth Backend `minimum_tls_version` option has been replaced by `authentication_backend.ldap.tls.minimum_version` (will be removed in 4.28.0)") -} - func TestLdapAuthenticationBackend(t *testing.T) { - suite.Run(t, new(LdapAuthenticationBackendSuite)) + suite.Run(t, new(LDAPAuthenticationBackendSuite)) } type ActiveDirectoryAuthenticationBackendSuite struct { @@ -534,13 +502,13 @@ type ActiveDirectoryAuthenticationBackendSuite struct { func (suite *ActiveDirectoryAuthenticationBackendSuite) SetupTest() { suite.validator = schema.NewStructValidator() suite.configuration = schema.AuthenticationBackendConfiguration{} - suite.configuration.Ldap = &schema.LDAPAuthenticationBackendConfiguration{} - suite.configuration.Ldap.Implementation = schema.LDAPImplementationActiveDirectory - suite.configuration.Ldap.URL = testLDAPURL - suite.configuration.Ldap.User = testLDAPUser - suite.configuration.Ldap.Password = testLDAPPassword - suite.configuration.Ldap.BaseDN = testLDAPBaseDN - suite.configuration.Ldap.TLS = schema.DefaultLDAPAuthenticationBackendConfiguration.TLS + suite.configuration.LDAP = &schema.LDAPAuthenticationBackendConfiguration{} + suite.configuration.LDAP.Implementation = schema.LDAPImplementationActiveDirectory + suite.configuration.LDAP.URL = testLDAPURL + suite.configuration.LDAP.User = testLDAPUser + suite.configuration.LDAP.Password = testLDAPPassword + suite.configuration.LDAP.BaseDN = testLDAPBaseDN + suite.configuration.LDAP.TLS = schema.DefaultLDAPAuthenticationBackendConfiguration.TLS } func (suite *ActiveDirectoryAuthenticationBackendSuite) TestShouldSetActiveDirectoryDefaults() { @@ -550,52 +518,52 @@ func (suite *ActiveDirectoryAuthenticationBackendSuite) TestShouldSetActiveDirec suite.Assert().False(suite.validator.HasErrors()) suite.Assert().Equal( - suite.configuration.Ldap.UsersFilter, + suite.configuration.LDAP.UsersFilter, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.UsersFilter) suite.Assert().Equal( - suite.configuration.Ldap.UsernameAttribute, + suite.configuration.LDAP.UsernameAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.UsernameAttribute) suite.Assert().Equal( - suite.configuration.Ldap.DisplayNameAttribute, + suite.configuration.LDAP.DisplayNameAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.DisplayNameAttribute) suite.Assert().Equal( - suite.configuration.Ldap.MailAttribute, + suite.configuration.LDAP.MailAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.MailAttribute) suite.Assert().Equal( - suite.configuration.Ldap.GroupsFilter, + suite.configuration.LDAP.GroupsFilter, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.GroupsFilter) suite.Assert().Equal( - suite.configuration.Ldap.GroupNameAttribute, + suite.configuration.LDAP.GroupNameAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.GroupNameAttribute) } func (suite *ActiveDirectoryAuthenticationBackendSuite) TestShouldOnlySetDefaultsIfNotManuallyConfigured() { - suite.configuration.Ldap.UsersFilter = "(&({username_attribute}={input})(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2))" - suite.configuration.Ldap.UsernameAttribute = "cn" - suite.configuration.Ldap.MailAttribute = "userPrincipalName" - suite.configuration.Ldap.DisplayNameAttribute = "name" - suite.configuration.Ldap.GroupsFilter = "(&(member={dn})(objectClass=group)(objectCategory=group))" - suite.configuration.Ldap.GroupNameAttribute = "distinguishedName" + suite.configuration.LDAP.UsersFilter = "(&({username_attribute}={input})(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2))" + suite.configuration.LDAP.UsernameAttribute = "cn" + suite.configuration.LDAP.MailAttribute = "userPrincipalName" + suite.configuration.LDAP.DisplayNameAttribute = "name" + suite.configuration.LDAP.GroupsFilter = "(&(member={dn})(objectClass=group)(objectCategory=group))" + suite.configuration.LDAP.GroupNameAttribute = "distinguishedName" ValidateAuthenticationBackend(&suite.configuration, suite.validator) suite.Assert().NotEqual( - suite.configuration.Ldap.UsersFilter, + suite.configuration.LDAP.UsersFilter, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.UsersFilter) suite.Assert().NotEqual( - suite.configuration.Ldap.UsernameAttribute, + suite.configuration.LDAP.UsernameAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.UsernameAttribute) suite.Assert().NotEqual( - suite.configuration.Ldap.DisplayNameAttribute, + suite.configuration.LDAP.DisplayNameAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.DisplayNameAttribute) suite.Assert().NotEqual( - suite.configuration.Ldap.MailAttribute, + suite.configuration.LDAP.MailAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.MailAttribute) suite.Assert().NotEqual( - suite.configuration.Ldap.GroupsFilter, + suite.configuration.LDAP.GroupsFilter, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.GroupsFilter) suite.Assert().NotEqual( - suite.configuration.Ldap.GroupNameAttribute, + suite.configuration.LDAP.GroupNameAttribute, schema.DefaultLDAPAuthenticationBackendImplementationActiveDirectoryConfiguration.GroupNameAttribute) } diff --git a/internal/configuration/validator/const.go b/internal/configuration/validator/const.go index 1b125bd11..1176657ee 100644 --- a/internal/configuration/validator/const.go +++ b/internal/configuration/validator/const.go @@ -5,6 +5,7 @@ const ( errFmtSessionRedisPortRange = "The port must be between 1 and 65535 for the %s session provider" errFmtSessionRedisHostRequired = "The host must be provided when using the %s session provider" errFmtSessionRedisHostOrNodesRequired = "Either the host or a node must be provided when using the %s session provider" + errFmtReplacedConfigurationKey = "invalid configuration key '%s' was replaced by '%s'" errFileHashing = "config key incorrect: authentication_backend.file.hashing should be authentication_backend.file.password" errFilePHashing = "config key incorrect: authentication_backend.file.password_hashing should be authentication_backend.file.password" @@ -138,12 +139,10 @@ var validKeys = []string{ "notifier.smtp.subject", "notifier.smtp.startup_check_address", "notifier.smtp.disable_require_tls", - "notifier.smtp.trusted_cert", // TODO: Deprecated: Remove in 4.28. "notifier.smtp.disable_html_emails", "notifier.smtp.tls.minimum_version", "notifier.smtp.tls.skip_verify", "notifier.smtp.tls.server_name", - "notifier.smtp.disable_verify_cert", // TODO: Deprecated: Remove in 4.28. // Regulation Keys. "regulation.max_retries", @@ -175,8 +174,6 @@ var validKeys = []string{ "authentication_backend.ldap.tls.minimum_version", "authentication_backend.ldap.tls.skip_verify", "authentication_backend.ldap.tls.server_name", - "authentication_backend.ldap.skip_verify", // TODO: Deprecated: Remove in 4.28. - "authentication_backend.ldap.minimum_tls_version", // TODO: Deprecated: Remove in 4.28. // File Authentication Backend Keys. "authentication_backend.file.path", @@ -188,10 +185,19 @@ var validKeys = []string{ "authentication_backend.file.password.parallelism", } +var replacedKeys = map[string]string{ + "authentication_backend.ldap.skip_verify": "authentication_backend.ldap.tls.skip_verify", + "authentication_backend.ldap.minimum_tls_version": "authentication_backend.ldap.tls.minimum_version", + "notifier.smtp.disable_verify_cert": "notifier.smtp.tls.skip_verify", + "logs_file_path": "log_file", + "logs_level": "log_level", +} + var specificErrorKeys = map[string]string{ - "logs_file_path": "config key replaced: logs_file is now log_file", - "logs_level": "config key replaced: logs_level is now log_level", "google_analytics": "config key removed: google_analytics - this functionality has been deprecated", + "notifier.smtp.trusted_cert": "invalid configuration key `notifier.smtp.trusted_cert` it has been removed, " + + "option has been replaced by the global option `certificates_directory`", + "authentication_backend.file.password_options.algorithm": errFilePOptions, "authentication_backend.file.password_options.iterations": errFilePOptions, "authentication_backend.file.password_options.key_length": errFilePOptions, diff --git a/internal/configuration/validator/keys.go b/internal/configuration/validator/keys.go index 6412312a0..900170f95 100644 --- a/internal/configuration/validator/keys.go +++ b/internal/configuration/validator/keys.go @@ -21,6 +21,11 @@ func ValidateKeys(validator *schema.StructValidator, keys []string) { continue } + if newKey, ok := replacedKeys[key]; ok { + validator.Push(fmt.Errorf(errFmtReplacedConfigurationKey, key, newKey)) + continue + } + if err, ok := specificErrorKeys[key]; ok { if !utils.IsStringInSlice(err, errStrings) { errStrings = append(errStrings, err) diff --git a/internal/configuration/validator/keys_test.go b/internal/configuration/validator/keys_test.go index 119eb3661..ba947422c 100644 --- a/internal/configuration/validator/keys_test.go +++ b/internal/configuration/validator/keys_test.go @@ -1,6 +1,7 @@ package validator import ( + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -62,8 +63,8 @@ func TestAllSpecificErrorKeys(t *testing.T) { func TestSpecificErrorKeys(t *testing.T) { configKeys := []string{ - "logs_level", - "logs_file_path", + "notifier.smtp.trusted_cert", + "google_analytics", "authentication_backend.file.password_options.algorithm", "authentication_backend.file.password_options.iterations", // This should not show another error since our target for the specific error is password_options. "authentication_backend.file.password_hashing.algorithm", @@ -77,9 +78,49 @@ func TestSpecificErrorKeys(t *testing.T) { require.Len(t, errs, 5) - assert.EqualError(t, errs[0], specificErrorKeys["logs_level"]) - assert.EqualError(t, errs[1], specificErrorKeys["logs_file_path"]) + assert.EqualError(t, errs[0], specificErrorKeys["notifier.smtp.trusted_cert"]) + assert.EqualError(t, errs[1], specificErrorKeys["google_analytics"]) assert.EqualError(t, errs[2], specificErrorKeys["authentication_backend.file.password_options.iterations"]) assert.EqualError(t, errs[3], specificErrorKeys["authentication_backend.file.password_hashing.algorithm"]) assert.EqualError(t, errs[4], specificErrorKeys["authentication_backend.file.hashing.algorithm"]) } + +func TestReplacedErrors(t *testing.T) { + configKeys := []string{ + "authentication_backend.ldap.skip_verify", + "authentication_backend.ldap.minimum_tls_version", + "notifier.smtp.disable_verify_cert", + "logs_file_path", + "logs_level", + } + + val := schema.NewStructValidator() + ValidateKeys(val, configKeys) + + warns := val.Warnings() + errs := val.Errors() + + assert.Len(t, warns, 0) + require.Len(t, errs, 5) + + assert.EqualError(t, errs[0], fmt.Sprintf(errFmtReplacedConfigurationKey, "authentication_backend.ldap.skip_verify", "authentication_backend.ldap.tls.skip_verify")) + assert.EqualError(t, errs[1], fmt.Sprintf(errFmtReplacedConfigurationKey, "authentication_backend.ldap.minimum_tls_version", "authentication_backend.ldap.tls.minimum_version")) + assert.EqualError(t, errs[2], fmt.Sprintf(errFmtReplacedConfigurationKey, "notifier.smtp.disable_verify_cert", "notifier.smtp.tls.skip_verify")) + assert.EqualError(t, errs[3], fmt.Sprintf(errFmtReplacedConfigurationKey, "logs_file_path", "log_file")) + assert.EqualError(t, errs[4], fmt.Sprintf(errFmtReplacedConfigurationKey, "logs_level", "log_level")) +} + +func TestSecretKeysDontRaiseErrors(t *testing.T) { + configKeys := []string{} + + for _, key := range SecretNames { + configKeys = append(configKeys, SecretNameToEnvName(key)) + configKeys = append(configKeys, key) + } + + val := schema.NewStructValidator() + ValidateKeys(val, configKeys) + + assert.Len(t, val.Warnings(), 0) + assert.Len(t, val.Errors(), 0) +} diff --git a/internal/configuration/validator/notifier.go b/internal/configuration/validator/notifier.go index 24ee5d7ef..38c3798d8 100644 --- a/internal/configuration/validator/notifier.go +++ b/internal/configuration/validator/notifier.go @@ -1,22 +1,17 @@ package validator import ( - "errors" "fmt" "github.com/authelia/authelia/internal/configuration/schema" ) // ValidateNotifier validates and update notifier configuration. -//nolint:gocyclo // TODO: Remove in 4.28. Should be able to remove this during the removal of deprecated config. func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *schema.StructValidator) { - if configuration.SMTP == nil && configuration.FileSystem == nil { + if configuration.SMTP == nil && configuration.FileSystem == nil || + configuration.SMTP != nil && configuration.FileSystem != nil { validator.Push(fmt.Errorf("Notifier should be either `smtp` or `filesystem`")) - return - } - if configuration.SMTP != nil && configuration.FileSystem != nil { - validator.Push(fmt.Errorf("Notifier should be either `smtp` or `filesystem`")) return } @@ -28,51 +23,39 @@ func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *sc return } - if configuration.SMTP != nil { - if configuration.SMTP.StartupCheckAddress == "" { - configuration.SMTP.StartupCheckAddress = "test@authelia.com" - } + validateSMTPNotifier(configuration.SMTP, validator) +} - if configuration.SMTP.Host == "" { - validator.Push(fmt.Errorf("Host of SMTP notifier must be provided")) - } +func validateSMTPNotifier(configuration *schema.SMTPNotifierConfiguration, validator *schema.StructValidator) { + if configuration.StartupCheckAddress == "" { + configuration.StartupCheckAddress = "test@authelia.com" + } - if configuration.SMTP.Port == 0 { - validator.Push(fmt.Errorf("Port of SMTP notifier must be provided")) - } + if configuration.Host == "" { + validator.Push(fmt.Errorf("Host of SMTP notifier must be provided")) + } - if configuration.SMTP.Sender == "" { - validator.Push(fmt.Errorf("Sender of SMTP notifier must be provided")) - } + if configuration.Port == 0 { + validator.Push(fmt.Errorf("Port of SMTP notifier must be provided")) + } - if configuration.SMTP.Subject == "" { - configuration.SMTP.Subject = schema.DefaultSMTPNotifierConfiguration.Subject - } + if configuration.Sender == "" { + validator.Push(fmt.Errorf("Sender of SMTP notifier must be provided")) + } - if configuration.SMTP.Identifier == "" { - configuration.SMTP.Identifier = schema.DefaultSMTPNotifierConfiguration.Identifier - } + if configuration.Subject == "" { + configuration.Subject = schema.DefaultSMTPNotifierConfiguration.Subject + } - if configuration.SMTP.TLS == nil { - configuration.SMTP.TLS = schema.DefaultSMTPNotifierConfiguration.TLS + if configuration.Identifier == "" { + configuration.Identifier = schema.DefaultSMTPNotifierConfiguration.Identifier + } - // Deprecated. Maps deprecated values to the new ones. TODO: Remove in 4.28. - if configuration.SMTP.DisableVerifyCert != nil { - validator.PushWarning(errors.New("DEPRECATED: SMTP Notifier `disable_verify_cert` option has been replaced by `notifier.smtp.tls.skip_verify` (will be removed in 4.28.0)")) + if configuration.TLS == nil { + configuration.TLS = schema.DefaultSMTPNotifierConfiguration.TLS + } - configuration.SMTP.TLS.SkipVerify = *configuration.SMTP.DisableVerifyCert - } - } - - // Deprecated. Maps deprecated values to the new ones. TODO: Remove in 4.28. - if configuration.SMTP.TrustedCert != "" { - validator.PushWarning(errors.New("DEPRECATED: SMTP Notifier `trusted_cert` option has been replaced by the global option `certificates_directory` (will be removed in 4.28.0)")) - } - - if configuration.SMTP.TLS.ServerName == "" { - configuration.SMTP.TLS.ServerName = configuration.SMTP.Host - } - - return + if configuration.TLS.ServerName == "" { + configuration.TLS.ServerName = configuration.Host } } diff --git a/internal/configuration/validator/notifier_test.go b/internal/configuration/validator/notifier_test.go index 85ff7602b..b26f010d6 100644 --- a/internal/configuration/validator/notifier_test.go +++ b/internal/configuration/validator/notifier_test.go @@ -127,29 +127,6 @@ func (suite *NotifierSuite) TestShouldEnsureSenderOfSMTPNotifierAreProvided() { suite.Assert().EqualError(suite.validator.Errors()[0], "Sender of SMTP notifier must be provided") } -// Deprecated: Temporary Test. TODO: Remove in 4.28 (Whole Test). -func (suite *NotifierSuite) TestShouldReturnDeprecationWarningsFor428() { - var disableVerifyCert = true - - suite.configuration.SMTP.TrustedCert = "/tmp" - suite.configuration.SMTP.DisableVerifyCert = &disableVerifyCert - - ValidateNotifier(&suite.configuration, suite.validator) - - suite.Require().True(suite.validator.HasWarnings()) - suite.Assert().False(suite.validator.HasErrors()) - - warnings := suite.validator.Warnings() - - suite.Require().Len(warnings, 2) - - suite.Assert().EqualError(warnings[0], "DEPRECATED: SMTP Notifier `disable_verify_cert` option has been replaced by `notifier.smtp.tls.skip_verify` (will be removed in 4.28.0)") - suite.Assert().EqualError(warnings[1], "DEPRECATED: SMTP Notifier `trusted_cert` option has been replaced by the global option `certificates_directory` (will be removed in 4.28.0)") - - // Should override since TLS schema is not defined - suite.Assert().Equal(true, suite.configuration.SMTP.TLS.SkipVerify) -} - func TestNotifierSuite(t *testing.T) { suite.Run(t, new(NotifierSuite)) } diff --git a/internal/configuration/validator/secrets.go b/internal/configuration/validator/secrets.go index 244022aef..cb46513d6 100644 --- a/internal/configuration/validator/secrets.go +++ b/internal/configuration/validator/secrets.go @@ -43,8 +43,8 @@ func ValidateSecrets(configuration *schema.Configuration, validator *schema.Stru } } - if configuration.AuthenticationBackend.Ldap != nil { - configuration.AuthenticationBackend.Ldap.Password = getSecretValue(SecretNames["LDAPPassword"], validator, viper) + if configuration.AuthenticationBackend.LDAP != nil { + configuration.AuthenticationBackend.LDAP.Password = getSecretValue(SecretNames["LDAPPassword"], validator, viper) } if configuration.Notifier != nil && configuration.Notifier.SMTP != nil { diff --git a/internal/handlers/handler_verify.go b/internal/handlers/handler_verify.go index 0be8cad65..951c8d852 100644 --- a/internal/handlers/handler_verify.go +++ b/internal/handlers/handler_verify.go @@ -402,7 +402,7 @@ func verifySessionHasUpToDateProfile(ctx *middlewares.AutheliaCtx, targetURL *ur } func getProfileRefreshSettings(cfg schema.AuthenticationBackendConfiguration) (refresh bool, refreshInterval time.Duration) { - if cfg.Ldap != nil { + if cfg.LDAP != nil { if cfg.RefreshInterval == schema.ProfileRefreshDisabled { refresh = false refreshInterval = 0 diff --git a/internal/handlers/handler_verify_test.go b/internal/handlers/handler_verify_test.go index 2ff816776..b1427fea6 100644 --- a/internal/handlers/handler_verify_test.go +++ b/internal/handlers/handler_verify_test.go @@ -23,7 +23,7 @@ import ( var verifyGetCfg = schema.AuthenticationBackendConfiguration{ RefreshInterval: schema.RefreshIntervalDefault, - Ldap: &schema.LDAPAuthenticationBackendConfiguration{}, + LDAP: &schema.LDAPAuthenticationBackendConfiguration{}, } // Test getOriginalURL. diff --git a/internal/utils/certificates.go b/internal/utils/certificates.go index 976ff983e..c8190f5ab 100644 --- a/internal/utils/certificates.go +++ b/internal/utils/certificates.go @@ -27,9 +27,8 @@ func NewTLSConfig(config *schema.TLSConfig, defaultMinVersion uint16, certPool * } } -//nolint:gocyclo // TODO: Remove in 4.28. Should be able to remove the nolint during the removal of deprecated config. // NewX509CertPool generates a x509.CertPool from the system PKI and the directory specified. -func NewX509CertPool(directory string, config *schema.Configuration) (certPool *x509.CertPool, errors []error, nonFatalErrors []error) { +func NewX509CertPool(directory string) (certPool *x509.CertPool, errors []error, nonFatalErrors []error) { certPool, err := x509.SystemCertPool() if err != nil { nonFatalErrors = append(nonFatalErrors, fmt.Errorf("could not load system certificate pool which may result in untrusted certificate issues: %v", err)) @@ -66,22 +65,6 @@ func NewX509CertPool(directory string, config *schema.Configuration) (certPool * logger.Tracef("Finished scan of directory %s for certificates", directory) - // Deprecated. Maps deprecated values to the new ones. TODO: Remove in 4.28. - if config != nil && config.Notifier != nil && config.Notifier.SMTP != nil && config.Notifier.SMTP.TrustedCert != "" { - nonFatalErrors = append(nonFatalErrors, fmt.Errorf("defining the trusted cert in the SMTP notifier is deprecated and will be removed in 4.28.0, please use the global certificates_directory instead")) - - if exists, _ := FileExists(config.Notifier.SMTP.TrustedCert); exists { - pem, err := ioutil.ReadFile(config.Notifier.SMTP.TrustedCert) - if err != nil { - errors = append(errors, fmt.Errorf("failed to read legacy SMTP trusted_cert (see the new certificates_directory option) certificate %s with error: %s", config.Notifier.SMTP.TrustedCert, err)) - } else if ok := certPool.AppendCertsFromPEM(pem); !ok { - errors = append(errors, fmt.Errorf("could not import legacy SMTP trusted_cert (see the new certificates_directory option) certificate %s", config.Notifier.SMTP.TrustedCert)) - } - } else { - errors = append(errors, fmt.Errorf("could not import legacy SMTP trusted_cert (see the new certificates_directory option) certificate %s (file does not exist)", config.Notifier.SMTP.TrustedCert)) - } - } - return certPool, errors, nonFatalErrors } diff --git a/internal/utils/certificates_test.go b/internal/utils/certificates_test.go index 16af21b67..716562c9b 100644 --- a/internal/utils/certificates_test.go +++ b/internal/utils/certificates_test.go @@ -77,7 +77,7 @@ func TestShouldReturnZeroAndErrorOnInvalidTLSVersions(t *testing.T) { } func TestShouldReturnErrWhenX509DirectoryNotExist(t *testing.T) { - pool, errs, nonFatalErrs := NewX509CertPool("/tmp/asdfzyxabc123/not/a/real/dir", nil) + pool, errs, nonFatalErrs := NewX509CertPool("/tmp/asdfzyxabc123/not/a/real/dir") assert.NotNil(t, pool) if runtime.GOOS == windows { @@ -97,7 +97,7 @@ func TestShouldReturnErrWhenX509DirectoryNotExist(t *testing.T) { } func TestShouldNotReturnErrWhenX509DirectoryExist(t *testing.T) { - pool, errs, nonFatalErrs := NewX509CertPool("/tmp", nil) + pool, errs, nonFatalErrs := NewX509CertPool("/tmp") assert.NotNil(t, pool) if runtime.GOOS == windows { @@ -110,64 +110,8 @@ func TestShouldNotReturnErrWhenX509DirectoryExist(t *testing.T) { assert.Len(t, errs, 0) } -func TestShouldRaiseNonFatalErrWhenNotifierTrustedCertConfigured(t *testing.T) { - config := &schema.Configuration{ - Notifier: &schema.NotifierConfiguration{ - SMTP: &schema.SMTPNotifierConfiguration{ - TrustedCert: "../suites/common/ssl/cert.pem", - }, - }, - } - - pool, errs, nonFatalErrs := NewX509CertPool("/tmp", config) - assert.NotNil(t, pool) - - index := 0 - - if runtime.GOOS == windows { - require.Len(t, nonFatalErrs, 2) - assert.EqualError(t, nonFatalErrs[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") - - index = 1 - } else { - require.Len(t, nonFatalErrs, 1) - } - - assert.Len(t, errs, 0) - assert.EqualError(t, nonFatalErrs[index], "defining the trusted cert in the SMTP notifier is deprecated and will be removed in 4.28.0, please use the global certificates_directory instead") -} - -func TestShouldRaiseErrAndNonFatalErrWhenNotifierTrustedCertConfiguredAndNotExist(t *testing.T) { - config := &schema.Configuration{ - Notifier: &schema.NotifierConfiguration{ - SMTP: &schema.SMTPNotifierConfiguration{ - TrustedCert: "/tmp/asdfzyxabc123/not/a/real/cert.pem", - }, - }, - } - - pool, errs, nonFatalErrs := NewX509CertPool("/tmp", config) - assert.NotNil(t, pool) - - index := 0 - - if runtime.GOOS == windows { - require.Len(t, nonFatalErrs, 2) - assert.EqualError(t, nonFatalErrs[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") - - index = 1 - } else { - require.Len(t, nonFatalErrs, 1) - } - - require.Len(t, errs, 1) - - assert.EqualError(t, errs[0], "could not import legacy SMTP trusted_cert (see the new certificates_directory option) certificate /tmp/asdfzyxabc123/not/a/real/cert.pem (file does not exist)") - assert.EqualError(t, nonFatalErrs[index], "defining the trusted cert in the SMTP notifier is deprecated and will be removed in 4.28.0, please use the global certificates_directory instead") -} - func TestShouldReadCertsFromDirectoryButNotKeys(t *testing.T) { - pool, errs, nonFatalErrs := NewX509CertPool("../suites/common/ssl/", nil) + pool, errs, nonFatalErrs := NewX509CertPool("../suites/common/ssl/") assert.NotNil(t, pool) require.Len(t, errs, 1)