2020-01-21 20:15:40 +00:00
package validator
import (
2022-10-21 08:41:33 +00:00
"crypto/tls"
2021-08-07 03:58:08 +00:00
"fmt"
2021-11-30 11:15:21 +00:00
"net/mail"
2023-04-13 10:58:18 +00:00
"path/filepath"
2020-01-21 20:15:40 +00:00
"testing"
2023-04-13 10:58:18 +00:00
"github.com/stretchr/testify/assert"
2023-04-19 04:27:10 +00:00
"github.com/stretchr/testify/require"
2020-01-21 20:15:40 +00:00
"github.com/stretchr/testify/suite"
2020-04-05 12:37:21 +00:00
2021-08-11 01:04:35 +00:00
"github.com/authelia/authelia/v4/internal/configuration/schema"
2020-01-21 20:15:40 +00:00
)
type NotifierSuite struct {
suite . Suite
2022-02-28 03:15:01 +00:00
config schema . NotifierConfiguration
validator * schema . StructValidator
2020-01-21 20:15:40 +00:00
}
2021-01-04 10:28:55 +00:00
func ( suite * NotifierSuite ) SetupTest ( ) {
suite . validator = schema . NewStructValidator ( )
2022-02-28 03:15:01 +00:00
suite . config . SMTP = & schema . SMTPNotifierConfiguration {
2023-05-07 06:39:17 +00:00
Address : & schema . AddressSMTP { Address : schema . NewAddressFromNetworkValues ( schema . AddressSchemeSMTP , exampleDotCom , 25 ) } ,
2020-01-21 20:15:40 +00:00
Username : "john" ,
Password : "password" ,
2021-11-30 11:15:21 +00:00
Sender : mail . Address { Name : "Authelia" , Address : "authelia@example.com" } ,
2020-01-21 20:15:40 +00:00
}
2022-02-28 03:15:01 +00:00
suite . config . FileSystem = nil
2020-01-21 20:15:40 +00:00
}
2021-11-30 11:15:21 +00:00
/ *
2022-08-07 01:24:00 +00:00
Common Tests .
2021-11-30 11:15:21 +00:00
* /
2021-01-04 10:28:55 +00:00
func ( suite * NotifierSuite ) TestShouldEnsureAtLeastSMTPOrFilesystemIsProvided ( ) {
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
2021-01-04 10:28:55 +00:00
2022-02-28 03:15:01 +00:00
suite . config . SMTP = nil
2020-01-21 20:15:40 +00:00
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
2021-01-04 10:28:55 +00:00
suite . Require ( ) . True ( suite . validator . HasErrors ( ) )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Errors ( ) , 1 )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , errFmtNotifierNotConfigured )
2020-01-21 20:15:40 +00:00
}
2021-01-04 10:28:55 +00:00
func ( suite * NotifierSuite ) TestShouldEnsureEitherSMTPOrFilesystemIsProvided ( ) {
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Errors ( ) , 0 )
2020-01-21 20:15:40 +00:00
2022-02-28 03:15:01 +00:00
suite . config . FileSystem = & schema . FileSystemNotifierConfiguration {
2020-01-21 20:15:40 +00:00
Filename : "test" ,
}
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
2021-01-04 10:28:55 +00:00
suite . Require ( ) . True ( suite . validator . HasErrors ( ) )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Errors ( ) , 1 )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , errFmtNotifierMultipleConfigured )
2021-01-04 10:28:55 +00:00
}
2020-01-21 20:15:40 +00:00
2021-11-30 11:15:21 +00:00
/ *
2022-08-07 01:24:00 +00:00
SMTP Tests .
2021-11-30 11:15:21 +00:00
* /
func ( suite * NotifierSuite ) TestSMTPShouldSetTLSDefaults ( ) {
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . Equal ( exampleDotCom , suite . config . SMTP . TLS . ServerName )
suite . Equal ( uint16 ( tls . VersionTLS12 ) , suite . config . SMTP . TLS . MinimumVersion . Value )
suite . False ( suite . config . SMTP . TLS . SkipVerify )
}
func ( suite * NotifierSuite ) TestSMTPShouldSetDefaultsWithLegacyAddress ( ) {
suite . config . SMTP . Address = nil
suite . config . SMTP . Host = "xyz" //nolint:staticcheck
suite . config . SMTP . Port = 123 //nolint:staticcheck
ValidateNotifier ( & suite . config , suite . validator )
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
suite . Equal ( & schema . AddressSMTP { Address : MustParseAddress ( "smtp://xyz:123" ) } , suite . config . SMTP . Address )
suite . Equal ( "xyz" , suite . config . SMTP . TLS . ServerName )
suite . Equal ( uint16 ( tls . VersionTLS12 ) , suite . config . SMTP . TLS . MinimumVersion . Value )
suite . False ( suite . config . SMTP . TLS . SkipVerify )
}
func ( suite * NotifierSuite ) TestSMTPShouldErrorWithAddressAndLegacyAddress ( ) {
suite . config . SMTP . Host = "fgh" //nolint:staticcheck
suite . config . SMTP . Port = 123 //nolint:staticcheck
ValidateNotifier ( & suite . config , suite . validator )
suite . Equal ( & schema . AddressSMTP { Address : MustParseAddress ( "smtp://example.com:25" ) } , suite . config . SMTP . Address )
suite . Equal ( exampleDotCom , suite . config . SMTP . TLS . ServerName )
suite . Equal ( uint16 ( tls . VersionTLS12 ) , suite . config . SMTP . TLS . MinimumVersion . Value )
suite . False ( suite . config . SMTP . TLS . SkipVerify )
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Require ( ) . Len ( suite . validator . Errors ( ) , 1 )
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , "notifier: smtp: option 'host' and 'port' can't be configured at the same time as 'address'" )
}
func ( suite * NotifierSuite ) TestSMTPShouldErrorWithInvalidAddressScheme ( ) {
suite . config . SMTP . Address = & schema . AddressSMTP { Address : MustParseAddress ( "udp://example.com:25" ) }
ValidateNotifier ( & suite . config , suite . validator )
suite . Equal ( & schema . AddressSMTP { Address : MustParseAddress ( "udp://example.com:25" ) } , suite . config . SMTP . Address )
suite . Equal ( exampleDotCom , suite . config . SMTP . TLS . ServerName )
suite . Equal ( uint16 ( tls . VersionTLS12 ) , suite . config . SMTP . TLS . MinimumVersion . Value )
suite . False ( suite . config . SMTP . TLS . SkipVerify )
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Require ( ) . Len ( suite . validator . Errors ( ) , 1 )
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , "notifier: smtp: option 'address' with value 'udp://example.com:25' is invalid: scheme must be one of 'smtp', 'submission', or 'submissions' but is configured as 'udp'" )
2021-11-30 11:15:21 +00:00
}
2022-07-18 00:56:09 +00:00
func ( suite * NotifierSuite ) TestSMTPShouldDefaultStartupCheckAddress ( ) {
2023-05-07 06:39:17 +00:00
suite . Equal ( mail . Address { Name : "" , Address : "" } , suite . config . SMTP . StartupCheckAddress )
2022-07-18 00:56:09 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
2022-07-18 00:56:09 +00:00
2023-05-07 06:39:17 +00:00
suite . Equal ( mail . Address { Name : "Authelia Test" , Address : "test@authelia.com" } , suite . config . SMTP . StartupCheckAddress )
2022-07-18 00:56:09 +00:00
}
2021-11-30 11:15:21 +00:00
func ( suite * NotifierSuite ) TestSMTPShouldDefaultTLSServerNameToHost ( ) {
2023-05-07 06:39:17 +00:00
suite . config . SMTP . Address . SetHostname ( "google.com" )
2022-02-28 03:15:01 +00:00
suite . config . SMTP . TLS = & schema . TLSConfig {
2022-10-21 08:41:33 +00:00
MinimumVersion : schema . TLSVersion { Value : tls . VersionTLS11 } ,
2021-11-30 11:15:21 +00:00
}
2021-01-04 10:28:55 +00:00
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . Equal ( "google.com" , suite . config . SMTP . TLS . ServerName )
suite . Equal ( uint16 ( tls . VersionTLS11 ) , suite . config . SMTP . TLS . MinimumVersion . MinVersion ( ) )
suite . False ( suite . config . SMTP . TLS . SkipVerify )
2021-01-04 10:28:55 +00:00
}
2022-10-21 08:41:33 +00:00
func ( suite * NotifierSuite ) TestSMTPShouldErrorOnSSL30 ( ) {
suite . config . SMTP . TLS = & schema . TLSConfig {
MinimumVersion : schema . TLSVersion { Value : tls . VersionSSL30 } , //nolint:staticcheck
}
ValidateNotifier ( & suite . config , suite . validator )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
2022-10-21 08:41:33 +00:00
suite . Require ( ) . Len ( suite . validator . Errors ( ) , 1 )
2023-05-07 06:39:17 +00:00
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , "notifier: smtp: tls: option 'minimum_version' is invalid: minimum version is TLS1.0 but SSL3.0 was configured" )
2022-10-21 08:41:33 +00:00
}
func ( suite * NotifierSuite ) TestSMTPShouldErrorOnTLSMinVerGreaterThanMaxVer ( ) {
suite . config . SMTP . TLS = & schema . TLSConfig {
MinimumVersion : schema . TLSVersion { Value : tls . VersionTLS13 } ,
MaximumVersion : schema . TLSVersion { Value : tls . VersionTLS10 } ,
}
ValidateNotifier ( & suite . config , suite . validator )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
2022-10-21 08:41:33 +00:00
suite . Require ( ) . Len ( suite . validator . Errors ( ) , 1 )
2023-05-07 06:39:17 +00:00
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , "notifier: smtp: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.0" )
2022-10-21 08:41:33 +00:00
}
func ( suite * NotifierSuite ) TestSMTPShouldWarnOnDisabledSTARTTLS ( ) {
suite . config . SMTP . DisableStartTLS = true
ValidateNotifier ( & suite . config , suite . validator )
suite . Require ( ) . Len ( suite . validator . Warnings ( ) , 1 )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Errors ( ) , 0 )
2022-10-21 08:41:33 +00:00
2023-05-07 06:39:17 +00:00
suite . EqualError ( suite . validator . Warnings ( ) [ 0 ] , "notifier: smtp: option 'disable_starttls' is enabled: opportunistic STARTTLS is explicitly disabled which means all emails will be sent insecurely over plaintext and this setting is only necessary for non-compliant SMTP servers which advertise they support STARTTLS when they actually don't support STARTTLS" )
2022-10-21 08:41:33 +00:00
}
2021-11-30 11:15:21 +00:00
func ( suite * NotifierSuite ) TestSMTPShouldEnsureHostAndPortAreProvided ( ) {
2022-02-28 03:15:01 +00:00
suite . config . FileSystem = nil
ValidateNotifier ( & suite . config , suite . validator )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . config . SMTP . Address = nil
2021-01-04 10:28:55 +00:00
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2021-01-04 10:28:55 +00:00
errors := suite . validator . Errors ( )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Require ( ) . Len ( errors , 1 )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . EqualError ( errors [ 0 ] , "notifier: smtp: option 'address' is required" )
2020-01-21 20:15:40 +00:00
}
2021-11-30 11:15:21 +00:00
func ( suite * NotifierSuite ) TestSMTPShouldEnsureSenderIsProvided ( ) {
2022-02-28 03:15:01 +00:00
suite . config . SMTP . Sender = mail . Address { }
2021-11-30 11:15:21 +00:00
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2021-11-30 11:15:21 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
2021-11-30 11:15:21 +00:00
suite . Require ( ) . True ( suite . validator . HasErrors ( ) )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Errors ( ) , 1 )
2021-11-30 11:15:21 +00:00
2023-05-07 06:39:17 +00:00
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , fmt . Sprintf ( errFmtNotifierSMTPNotConfigured , "sender" ) )
2021-11-30 11:15:21 +00:00
}
2020-01-21 20:15:40 +00:00
2023-04-13 10:58:18 +00:00
func ( suite * NotifierSuite ) TestTemplatesEmptyDir ( ) {
dir := suite . T ( ) . TempDir ( )
suite . config . TemplatePath = dir
ValidateNotifier ( & suite . config , suite . validator )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
2023-04-13 10:58:18 +00:00
}
func ( suite * NotifierSuite ) TestTemplatesEmptyDirNoExist ( ) {
dir := suite . T ( ) . TempDir ( )
p := filepath . Join ( dir , "notexist" )
suite . config . TemplatePath = p
ValidateNotifier ( & suite . config , suite . validator )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 1 )
2023-04-13 10:58:18 +00:00
assert . EqualError ( suite . T ( ) , suite . validator . Errors ( ) [ 0 ] , fmt . Sprintf ( "notifier: option 'template_path' refers to location '%s' which does not exist" , p ) )
}
2021-11-30 11:15:21 +00:00
/ *
2022-08-07 01:24:00 +00:00
File Tests .
2021-11-30 11:15:21 +00:00
* /
func ( suite * NotifierSuite ) TestFileShouldEnsureFilenameIsProvided ( ) {
2022-02-28 03:15:01 +00:00
suite . config . SMTP = nil
suite . config . FileSystem = & schema . FileSystemNotifierConfiguration {
2021-11-30 11:15:21 +00:00
Filename : "test" ,
}
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2020-01-21 20:15:40 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
suite . Len ( suite . validator . Errors ( ) , 0 )
2020-01-21 20:15:40 +00:00
2022-02-28 03:15:01 +00:00
suite . config . FileSystem . Filename = ""
2020-01-21 20:15:40 +00:00
2022-02-28 03:15:01 +00:00
ValidateNotifier ( & suite . config , suite . validator )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Warnings ( ) , 0 )
2021-01-04 10:28:55 +00:00
suite . Require ( ) . True ( suite . validator . HasErrors ( ) )
2023-05-07 06:39:17 +00:00
suite . Len ( suite . validator . Errors ( ) , 1 )
2021-01-04 10:28:55 +00:00
2023-05-07 06:39:17 +00:00
suite . EqualError ( suite . validator . Errors ( ) [ 0 ] , errFmtNotifierFileSystemFileNameNotConfigured )
2020-01-21 20:15:40 +00:00
}
func TestNotifierSuite ( t * testing . T ) {
suite . Run ( t , new ( NotifierSuite ) )
}
2023-04-19 04:27:10 +00:00
func TestNotifierMiscMissingTemplateTests ( t * testing . T ) {
config := & schema . NotifierConfiguration {
TemplatePath : string ( [ ] byte { 0x0 , 0x1 } ) ,
}
val := schema . NewStructValidator ( )
validateNotifierTemplates ( config , val )
require . Len ( t , val . Errors ( ) , 1 )
assert . EqualError ( t , val . Errors ( ) [ 0 ] , "notifier: option 'template_path' refers to location '\x00\x01' which couldn't be opened: stat \x00\x01: invalid argument" )
}