2019-04-24 21:52:08 +00:00
package validator
import (
2022-04-17 23:58:24 +00:00
"fmt"
2021-03-22 09:04:09 +00:00
"runtime"
2019-04-24 21:52:08 +00:00
"testing"
"github.com/stretchr/testify/assert"
2020-01-21 20:15:40 +00:00
"github.com/stretchr/testify/require"
2020-04-05 12:37:21 +00:00
2021-08-11 01:04:35 +00:00
"github.com/authelia/authelia/v4/internal/configuration/schema"
2019-04-24 21:52:08 +00:00
)
func newDefaultConfig ( ) schema . Configuration {
config := schema . Configuration { }
2021-08-02 11:55:30 +00:00
config . Server . Host = loopback
config . Server . Port = 9090
2021-08-03 09:55:21 +00:00
config . Log . Level = "info"
config . Log . Format = "text"
2020-05-02 16:20:40 +00:00
config . JWTSecret = testJWTSecret
2022-10-17 10:51:59 +00:00
config . AuthenticationBackend . File = & schema . FileAuthenticationBackend {
2021-04-14 10:53:23 +00:00
Path : "/a/path" ,
}
config . AccessControl = schema . AccessControlConfiguration {
DefaultPolicy : "two_factor" ,
}
2019-04-24 21:52:08 +00:00
config . Session = schema . SessionConfiguration {
Secret : "secret" ,
2023-01-12 10:57:44 +00:00
Cookies : [ ] schema . SessionCookieConfiguration {
{
SessionCookieCommonConfiguration : schema . SessionCookieCommonConfiguration {
Name : "authelia_session" ,
Domain : exampleDotCom ,
} ,
} ,
} ,
2019-04-24 21:52:08 +00:00
}
2021-11-25 01:56:58 +00:00
config . Storage . EncryptionKey = testEncryptionKey
2020-02-06 02:53:02 +00:00
config . Storage . Local = & schema . LocalStorageConfiguration {
Path : "abc" ,
2019-11-16 19:50:58 +00:00
}
2022-04-15 23:34:26 +00:00
config . Notifier = schema . NotifierConfiguration {
2020-01-21 20:15:40 +00:00
FileSystem : & schema . FileSystemNotifierConfiguration {
Filename : "/tmp/file" ,
} ,
}
2020-05-05 19:35:32 +00:00
2019-04-24 21:52:08 +00:00
return config
}
2020-01-21 20:15:40 +00:00
func TestShouldEnsureNotifierConfigIsProvided ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := newDefaultConfig ( )
2020-04-23 01:11:32 +00:00
ValidateConfiguration ( & config , validator )
2020-01-21 20:15:40 +00:00
require . Len ( t , validator . Errors ( ) , 0 )
2023-01-12 10:57:44 +00:00
config = newDefaultConfig ( )
2022-04-15 23:34:26 +00:00
config . Notifier . SMTP = nil
config . Notifier . FileSystem = nil
2020-01-21 20:15:40 +00:00
2020-04-23 01:11:32 +00:00
ValidateConfiguration ( & config , validator )
2020-01-21 20:15:40 +00:00
require . Len ( t , validator . Errors ( ) , 1 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "notifier: you must ensure either the 'smtp' or 'filesystem' notifier is configured" )
2020-01-21 20:15:40 +00:00
}
2020-02-04 21:18:02 +00:00
func TestShouldAddDefaultAccessControl ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := newDefaultConfig ( )
2021-04-14 10:53:23 +00:00
config . AccessControl . DefaultPolicy = ""
config . AccessControl . Rules = [ ] schema . ACLRule {
{
Policy : "bypass" ,
Domains : [ ] string {
"public.example.com" ,
} ,
} ,
}
2020-04-23 01:11:32 +00:00
ValidateConfiguration ( & config , validator )
2020-02-04 21:18:02 +00:00
require . Len ( t , validator . Errors ( ) , 0 )
assert . NotNil ( t , config . AccessControl )
assert . Equal ( t , "deny" , config . AccessControl . DefaultPolicy )
}
2020-03-03 07:18:25 +00:00
2020-04-05 12:37:21 +00:00
func TestShouldRaiseErrorWithUndefinedJWTSecretKey ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := newDefaultConfig ( )
config . JWTSecret = ""
2020-04-23 01:11:32 +00:00
ValidateConfiguration ( & config , validator )
2020-04-05 12:37:21 +00:00
require . Len ( t , validator . Errors ( ) , 1 )
2021-08-03 09:55:21 +00:00
require . Len ( t , validator . Warnings ( ) , 1 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "option 'jwt_secret' is required" )
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "access control: no rules have been specified so the 'default_policy' of 'two_factor' is going to be applied to all requests" )
2020-04-05 12:37:21 +00:00
}
func TestShouldRaiseErrorWithBadDefaultRedirectionURL ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := newDefaultConfig ( )
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
config . DefaultRedirectionURL = "bad_default_redirection_url"
2020-04-05 12:37:21 +00:00
2020-04-23 01:11:32 +00:00
ValidateConfiguration ( & config , validator )
2020-04-05 12:37:21 +00:00
require . Len ( t , validator . Errors ( ) , 1 )
2021-08-03 09:55:21 +00:00
require . Len ( t , validator . Warnings ( ) , 1 )
2022-09-03 01:51:02 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "option 'default_redirection_url' is invalid: could not parse 'bad_default_redirection_url' as a URL" )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "access control: no rules have been specified so the 'default_policy' of 'two_factor' is going to be applied to all requests" )
2020-04-05 12:37:21 +00:00
}
2021-01-04 10:28:55 +00:00
func TestShouldNotOverrideCertificatesDirectoryAndShouldPassWhenBlank ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := newDefaultConfig ( )
2021-08-03 09:55:21 +00:00
2021-01-04 10:28:55 +00:00
ValidateConfiguration ( & config , validator )
2021-08-03 09:55:21 +00:00
assert . Len ( t , validator . Errors ( ) , 0 )
require . Len ( t , validator . Warnings ( ) , 1 )
2021-01-04 10:28:55 +00:00
require . Equal ( t , "" , config . CertificatesDirectory )
2021-08-03 09:55:21 +00:00
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "access control: no rules have been specified so the 'default_policy' of 'two_factor' is going to be applied to all requests" )
2021-01-04 10:28:55 +00:00
}
func TestShouldRaiseErrorOnInvalidCertificatesDirectory ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := newDefaultConfig ( )
config . CertificatesDirectory = "not-a-real-file.go"
ValidateConfiguration ( & config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2021-08-03 09:55:21 +00:00
require . Len ( t , validator . Warnings ( ) , 1 )
2021-03-22 09:04:09 +00:00
if runtime . GOOS == "windows" {
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "the location 'certificates_directory' could not be inspected: CreateFile not-a-real-file.go: The system cannot find the file specified." )
2021-03-22 09:04:09 +00:00
} else {
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "the location 'certificates_directory' could not be inspected: stat not-a-real-file.go: no such file or directory" )
2021-03-22 09:04:09 +00:00
}
2021-01-04 10:28:55 +00:00
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "access control: no rules have been specified so the 'default_policy' of 'two_factor' is going to be applied to all requests" )
2021-08-03 09:55:21 +00:00
2023-01-12 10:57:44 +00:00
config = newDefaultConfig ( )
2021-01-04 10:28:55 +00:00
validator = schema . NewStructValidator ( )
config . CertificatesDirectory = "const.go"
2021-08-03 09:55:21 +00:00
2021-01-04 10:28:55 +00:00
ValidateConfiguration ( & config , validator )
require . Len ( t , validator . Errors ( ) , 1 )
2021-08-03 09:55:21 +00:00
require . Len ( t , validator . Warnings ( ) , 1 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Errors ( ) [ 0 ] , "the location 'certificates_directory' refers to 'const.go' is not a directory" )
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "access control: no rules have been specified so the 'default_policy' of 'two_factor' is going to be applied to all requests" )
2021-01-04 10:28:55 +00:00
}
func TestShouldNotRaiseErrorOnValidCertificatesDirectory ( t * testing . T ) {
validator := schema . NewStructValidator ( )
config := newDefaultConfig ( )
2023-02-11 03:11:40 +00:00
config . CertificatesDirectory = "../../suites/common/pki"
2021-01-04 10:28:55 +00:00
ValidateConfiguration ( & config , validator )
2021-08-03 09:55:21 +00:00
assert . Len ( t , validator . Errors ( ) , 0 )
require . Len ( t , validator . Warnings ( ) , 1 )
2022-02-28 03:15:01 +00:00
assert . EqualError ( t , validator . Warnings ( ) [ 0 ] , "access control: no rules have been specified so the 'default_policy' of 'two_factor' is going to be applied to all requests" )
2021-01-04 10:28:55 +00:00
}
2022-04-17 23:58:24 +00:00
func TestValidateDefault2FAMethod ( t * testing . T ) {
testCases := [ ] struct {
desc string
have * schema . Configuration
expectedErrs [ ] string
} {
{
desc : "ShouldAllowConfiguredMethodTOTP" ,
have : & schema . Configuration {
Default2FAMethod : "totp" ,
DuoAPI : schema . DuoAPIConfiguration {
SecretKey : "a key" ,
IntegrationKey : "another key" ,
Hostname : "none" ,
} ,
} ,
} ,
{
2023-04-11 04:40:09 +00:00
desc : "ShouldAllowConfiguredMethodWebAuthn" ,
2022-04-17 23:58:24 +00:00
have : & schema . Configuration {
Default2FAMethod : "webauthn" ,
DuoAPI : schema . DuoAPIConfiguration {
SecretKey : "a key" ,
IntegrationKey : "another key" ,
Hostname : "none" ,
} ,
} ,
} ,
{
desc : "ShouldAllowConfiguredMethodMobilePush" ,
have : & schema . Configuration {
Default2FAMethod : "mobile_push" ,
DuoAPI : schema . DuoAPIConfiguration {
SecretKey : "a key" ,
IntegrationKey : "another key" ,
Hostname : "none" ,
} ,
} ,
} ,
{
desc : "ShouldNotAllowDisabledMethodTOTP" ,
have : & schema . Configuration {
Default2FAMethod : "totp" ,
DuoAPI : schema . DuoAPIConfiguration {
SecretKey : "a key" ,
IntegrationKey : "another key" ,
Hostname : "none" ,
} ,
TOTP : schema . TOTPConfiguration { Disable : true } ,
} ,
expectedErrs : [ ] string {
2023-04-13 10:58:18 +00:00
"option 'default_2fa_method' must be one of the enabled options 'webauthn' or 'mobile_push' but it's configured as 'totp'" ,
2022-04-17 23:58:24 +00:00
} ,
} ,
{
2023-04-11 04:40:09 +00:00
desc : "ShouldNotAllowDisabledMethodWebAuthn" ,
2022-04-17 23:58:24 +00:00
have : & schema . Configuration {
Default2FAMethod : "webauthn" ,
DuoAPI : schema . DuoAPIConfiguration {
SecretKey : "a key" ,
IntegrationKey : "another key" ,
Hostname : "none" ,
} ,
2023-04-11 04:40:09 +00:00
WebAuthn : schema . WebAuthnConfiguration { Disable : true } ,
2022-04-17 23:58:24 +00:00
} ,
expectedErrs : [ ] string {
2023-04-13 10:58:18 +00:00
"option 'default_2fa_method' must be one of the enabled options 'totp' or 'mobile_push' but it's configured as 'webauthn'" ,
2022-04-17 23:58:24 +00:00
} ,
} ,
{
desc : "ShouldNotAllowDisabledMethodMobilePush" ,
have : & schema . Configuration {
Default2FAMethod : "mobile_push" ,
DuoAPI : schema . DuoAPIConfiguration { Disable : true } ,
} ,
expectedErrs : [ ] string {
2023-04-13 10:58:18 +00:00
"option 'default_2fa_method' must be one of the enabled options 'totp' or 'webauthn' but it's configured as 'mobile_push'" ,
2022-04-17 23:58:24 +00:00
} ,
} ,
{
desc : "ShouldNotAllowInvalidMethodDuo" ,
have : & schema . Configuration {
Default2FAMethod : "duo" ,
} ,
expectedErrs : [ ] string {
2023-04-13 10:58:18 +00:00
"option 'default_2fa_method' must be one of 'totp', 'webauthn', or 'mobile_push' but it's configured as 'duo'" ,
2022-04-17 23:58:24 +00:00
} ,
} ,
}
for _ , tc := range testCases {
t . Run ( tc . desc , func ( t * testing . T ) {
validator := schema . NewStructValidator ( )
validateDefault2FAMethod ( tc . have , validator )
assert . Len ( t , validator . Warnings ( ) , 0 )
errs := validator . Errors ( )
require . Len ( t , errs , len ( tc . expectedErrs ) )
for i , expected := range tc . expectedErrs {
t . Run ( fmt . Sprintf ( "Err%d" , i + 1 ) , func ( t * testing . T ) {
assert . EqualError ( t , errs [ i ] , expected )
} )
}
} )
}
}