test(suites): load environment into suites (#4762)
* test(suites): load environment into suites * test(suites): default setup suite * test(suites): create base suite * test(suites): fix nil ptr * test(suites): add logging * test: fix missing devworkflow path * refactor: apply suggestions * refactor: log * fix: dev workflow requires env file to trigger vite hmr * fix(suites): fix dynamic configuration in dev workflow for all proxies * refactor: apply final suggestions * fix: pass log level to suites * fix(suites): include pathprefix to prevent react router basename issues * fix: missing setup logging calls * fix: gate suite setup funcs * test: fix lint * test: fix tmp dir * fix(suites): fix gitignore of .env.development with vite hmr Co-authored-by: Amir Zarrinkafsh <nightah@me.com>pull/4818/head
parent
74995264e2
commit
36e817df92
|
@ -348,6 +348,8 @@ func runSuiteTests(suiteName string, withEnv bool) error {
|
|||
cmd.Env = append(cmd.Env, "HEADLESS=y")
|
||||
}
|
||||
|
||||
cmd.Env = append(cmd.Env, "SUITES_LOG_LEVEL="+log.GetLevel().String())
|
||||
|
||||
testErr := cmd.Run()
|
||||
|
||||
// If the tests failed, run the error hook.
|
||||
|
|
|
@ -140,9 +140,7 @@ func setupSuite(cmd *cobra.Command, args []string) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = s.SetUp(suiteTmpDirectory)
|
||||
|
||||
if err != nil {
|
||||
if err = s.SetUp(suiteTmpDirectory); err != nil {
|
||||
log.Error("Failure during environment deployment.")
|
||||
teardownSuite(nil, args)
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -2,7 +2,6 @@ package suites
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
||||
)
|
||||
|
@ -14,9 +13,6 @@ var (
|
|||
Example3DotCom = "example3.com:8080"
|
||||
)
|
||||
|
||||
// PathPrefix the prefix/url_base of the login portal.
|
||||
var PathPrefix = os.Getenv("PathPrefix")
|
||||
|
||||
// LoginBaseURLFmt the base URL of the login portal for specified baseDomain.
|
||||
func LoginBaseURLFmt(baseDomain string) string {
|
||||
if baseDomain == "" {
|
||||
|
@ -81,6 +77,8 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
envFileProd = "./web/.env.production"
|
||||
envFileDev = "./web/.env.development"
|
||||
namespaceAuthelia = "authelia"
|
||||
namespaceDashboard = "kubernetes-dashboard"
|
||||
namespaceKube = "kube-system"
|
||||
|
|
|
@ -21,11 +21,11 @@ services:
|
|||
- '${GOPATH}:/go'
|
||||
labels:
|
||||
# Traefik 1.x
|
||||
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/api,/locales'
|
||||
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/.well-known,/api,/locales,/devworkflow,/jwks.json'
|
||||
- 'traefik.protocol=https'
|
||||
# Traefik 2.x
|
||||
- 'traefik.enable=true'
|
||||
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/.well-known`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/.well-known`) || Host(`login.example.com`) && PathPrefix(`/api`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/api`) || Host(`login.example.com`) && PathPrefix(`/locales`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/locales`) || Host(`login.example.com`) && Path(`/jwks.json`) || Host(`login.example.com`) && Path(`${PathPrefix}/jwks.json`)' # yamllint disable-line rule:line-length
|
||||
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/.well-known`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/.well-known`) || Host(`login.example.com`) && PathPrefix(`/api`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/api`) || Host(`login.example.com`) && PathPrefix(`/locales`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/locales`) || Host(`login.example.com`) && Path(`/devworkflow`) || Host(`login.example.com`) && Path(`${PathPrefix}/devworkflow`) || Host(`login.example.com`) && Path(`/jwks.json`) || Host(`login.example.com`) && Path(`${PathPrefix}/jwks.json`) || Host(`login.example.com`) && Path(`/static/media/logo.png`) || Host(`login.example.com`) && Path(`${PathPrefix}/static/media/logo.png`)' # yamllint disable-line rule:line-length
|
||||
- 'traefik.http.routers.authelia_backend.entrypoints=https'
|
||||
- 'traefik.http.routers.authelia_backend.tls=true'
|
||||
- 'traefik.http.services.authelia_backend.loadbalancer.server.scheme=https'
|
||||
|
|
|
@ -29,6 +29,10 @@ login.example.com:8080 {
|
|||
import tls-transport
|
||||
}
|
||||
|
||||
reverse_proxy /devworkflow authelia-backend:9091 {
|
||||
import tls-transport
|
||||
}
|
||||
|
||||
reverse_proxy /jwks.json authelia-backend:9091 {
|
||||
import tls-transport
|
||||
}
|
||||
|
|
|
@ -40,6 +40,10 @@ static_resources:
|
|||
prefix: "/locales/"
|
||||
route:
|
||||
cluster: authelia-backend
|
||||
- match:
|
||||
path: "/devworkflow"
|
||||
route:
|
||||
cluster: authelia-backend
|
||||
- match:
|
||||
path: "/jwks.json"
|
||||
route:
|
||||
|
|
|
@ -25,6 +25,10 @@ frontend fe_http
|
|||
bind *:8080 ssl crt /usr/local/etc/haproxy/haproxy.pem
|
||||
|
||||
acl api-path path_beg -i /api
|
||||
acl wellknown-path path_beg -i /.well-known
|
||||
acl locales-path path_beg -i /locales
|
||||
acl devworkflow-path path -i -m end /devworkflow
|
||||
acl jwks-path path -i -m end /jwks.json
|
||||
acl headers-path path -i -m end /headers
|
||||
acl host-authelia-portal hdr(host) -i login.example.com:8080
|
||||
acl protected-frontends hdr(host) -m reg -i ^(?i)(admin|home|public|secure|singlefactor)\.example\.com
|
||||
|
@ -54,18 +58,16 @@ frontend fe_http
|
|||
|
||||
http-request redirect location https://login.example.com:8080/?rd=%[var(req.scheme)]://%[base]%[var(req.questionmark)]%[query] if protected-frontends !{ var(txn.auth_response_successful) -m bool }
|
||||
|
||||
use_backend be_authelia if host-authelia-portal api-path
|
||||
use_backend be_authelia if host-authelia-portal api-path || wellknown-path || locales-path || devworkflow-path || jwks-path
|
||||
use_backend fe_authelia if host-authelia-portal !api-path
|
||||
use_backend be_httpbin if protected-frontends headers-path
|
||||
use_backend be_mail if { hdr(host) -i mail.example.com:8080 }
|
||||
use_backend be_protected if protected-frontends
|
||||
|
||||
backend be_auth_request
|
||||
mode http
|
||||
server proxy 127.0.0.1:8085
|
||||
|
||||
listen be_auth_request_proxy
|
||||
mode http
|
||||
bind 127.0.0.1:8085
|
||||
server authelia-backend authelia-backend:9091 resolvers docker ssl verify none
|
||||
|
||||
|
@ -73,6 +75,9 @@ backend be_authelia
|
|||
server authelia-backend authelia-backend:9091 resolvers docker ssl verify none
|
||||
|
||||
backend fe_authelia
|
||||
option httpchk
|
||||
http-check expect rstatus ^2
|
||||
|
||||
server authelia-frontend authelia-frontend:3000 check resolvers docker
|
||||
server authelia-backend authelia-backend:9091 check backup resolvers docker ssl verify none
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ type AvailableMethodsScenario struct {
|
|||
|
||||
func NewAvailableMethodsScenario(methods []string) *AvailableMethodsScenario {
|
||||
return &AvailableMethodsScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
methods: methods,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ type BypassPolicyScenario struct {
|
|||
|
||||
func NewBypassPolicyScenario() *BypassPolicyScenario {
|
||||
return &BypassPolicyScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ type CustomHeadersScenario struct {
|
|||
|
||||
func NewCustomHeadersScenario() *CustomHeadersScenario {
|
||||
return &CustomHeadersScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ type DefaultRedirectionURLScenario struct {
|
|||
|
||||
func NewDefaultRedirectionURLScenario() *DefaultRedirectionURLScenario {
|
||||
return &DefaultRedirectionURLScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ type InactivityScenario struct {
|
|||
|
||||
func NewInactivityScenario() *InactivityScenario {
|
||||
return &InactivityScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ type MultiCookieDomainScenario struct {
|
|||
// NewMultiCookieDomainScenario returns a new Multi Cookie Domain Test Scenario.
|
||||
func NewMultiCookieDomainScenario(domain, nextDomain string, remember bool) *MultiCookieDomainScenario {
|
||||
return &MultiCookieDomainScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
domain: domain,
|
||||
nextDomain: nextDomain,
|
||||
remember: remember,
|
||||
|
|
|
@ -22,7 +22,7 @@ type OIDCScenario struct {
|
|||
|
||||
func NewOIDCScenario() *OIDCScenario {
|
||||
return &OIDCScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ type OneFactorSuite struct {
|
|||
|
||||
func New1FAScenario() *OneFactorSuite {
|
||||
return &OneFactorSuite{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ func (s *OneFactorSuite) TearDownTest() {
|
|||
}
|
||||
|
||||
func (s *OneFactorSuite) TestShouldAuthorizeSecretAfterOneFactor() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer func() {
|
||||
cancel()
|
||||
s.collectScreenshot(ctx.Err(), s.Page)
|
||||
|
|
|
@ -14,7 +14,7 @@ type PasswordComplexityScenario struct {
|
|||
}
|
||||
|
||||
func NewPasswordComplexityScenario() *PasswordComplexityScenario {
|
||||
return &PasswordComplexityScenario{RodSuite: new(RodSuite)}
|
||||
return &PasswordComplexityScenario{RodSuite: NewRodSuite("")}
|
||||
}
|
||||
|
||||
func (s *PasswordComplexityScenario) SetupSuite() {
|
||||
|
|
|
@ -15,7 +15,7 @@ type RedirectionCheckScenario struct {
|
|||
|
||||
func NewRedirectionCheckScenario() *RedirectionCheckScenario {
|
||||
return &RedirectionCheckScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ type RedirectionURLScenario struct {
|
|||
|
||||
func NewRedirectionURLScenario() *RedirectionURLScenario {
|
||||
return &RedirectionURLScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ type RegulationScenario struct {
|
|||
|
||||
func NewRegulationScenario() *RegulationScenario {
|
||||
return &RegulationScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ type ResetPasswordScenario struct {
|
|||
}
|
||||
|
||||
func NewResetPasswordScenario() *ResetPasswordScenario {
|
||||
return &ResetPasswordScenario{RodSuite: new(RodSuite)}
|
||||
return &ResetPasswordScenario{RodSuite: NewRodSuite("")}
|
||||
}
|
||||
|
||||
func (s *ResetPasswordScenario) SetupSuite() {
|
||||
|
|
|
@ -18,7 +18,7 @@ type SigninEmailScenario struct {
|
|||
|
||||
func NewSigninEmailScenario() *SigninEmailScenario {
|
||||
return &SigninEmailScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ type TwoFactorSuite struct {
|
|||
|
||||
func New2FAScenario() *TwoFactorSuite {
|
||||
return &TwoFactorSuite{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ type UserPreferencesScenario struct {
|
|||
|
||||
func NewUserPreferencesScenario() *UserPreferencesScenario {
|
||||
return &UserPreferencesScenario{
|
||||
RodSuite: new(RodSuite),
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@ type ActiveDirectorySuite struct {
|
|||
}
|
||||
|
||||
func NewActiveDirectorySuite() *ActiveDirectorySuite {
|
||||
return &ActiveDirectorySuite{RodSuite: new(RodSuite)}
|
||||
return &ActiveDirectorySuite{
|
||||
RodSuite: NewRodSuite(activedirectorySuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ActiveDirectorySuite) Test1FAScenario() {
|
||||
|
|
|
@ -15,10 +15,14 @@ type BypassAllWebDriverSuite struct {
|
|||
}
|
||||
|
||||
func NewBypassAllWebDriverSuite() *BypassAllWebDriverSuite {
|
||||
return &BypassAllWebDriverSuite{RodSuite: new(RodSuite)}
|
||||
return &BypassAllWebDriverSuite{
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BypassAllWebDriverSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
browser, err := StartRod()
|
||||
|
||||
if err != nil {
|
||||
|
@ -61,11 +65,15 @@ func (s *BypassAllWebDriverSuite) TestShouldAccessPublicResource() {
|
|||
}
|
||||
|
||||
type BypassAllSuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
}
|
||||
|
||||
func NewBypassAllSuite() *BypassAllSuite {
|
||||
return &BypassAllSuite{}
|
||||
return &BypassAllSuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: bypassAllSuiteName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BypassAllSuite) TestBypassAllWebDriverSuite() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type CaddySuite struct {
|
|||
}
|
||||
|
||||
func NewCaddySuite() *CaddySuite {
|
||||
return &CaddySuite{RodSuite: new(RodSuite)}
|
||||
return &CaddySuite{
|
||||
RodSuite: NewRodSuite(caddySuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CaddySuite) Test1FAScenario() {
|
||||
|
|
|
@ -23,10 +23,18 @@ type CLISuite struct {
|
|||
}
|
||||
|
||||
func NewCLISuite() *CLISuite {
|
||||
return &CLISuite{CommandSuite: new(CommandSuite)}
|
||||
return &CLISuite{
|
||||
CommandSuite: &CommandSuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: cliSuiteName,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CLISuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
dockerEnvironment := NewDockerEnvironment([]string{
|
||||
"internal/suites/docker-compose.yml",
|
||||
"internal/suites/CLI/docker-compose.yml",
|
||||
|
|
|
@ -11,7 +11,9 @@ type DockerSuite struct {
|
|||
}
|
||||
|
||||
func NewDockerSuite() *DockerSuite {
|
||||
return &DockerSuite{RodSuite: new(RodSuite)}
|
||||
return &DockerSuite{
|
||||
RodSuite: NewRodSuite(dockerSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) Test1FAScenario() {
|
||||
|
|
|
@ -20,7 +20,9 @@ type DuoPushWebDriverSuite struct {
|
|||
}
|
||||
|
||||
func NewDuoPushWebDriverSuite() *DuoPushWebDriverSuite {
|
||||
return &DuoPushWebDriverSuite{RodSuite: new(RodSuite)}
|
||||
return &DuoPushWebDriverSuite{
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DuoPushWebDriverSuite) SetupSuite() {
|
||||
|
@ -386,10 +388,12 @@ type DuoPushDefaultRedirectionSuite struct {
|
|||
}
|
||||
|
||||
func NewDuoPushDefaultRedirectionSuite() *DuoPushDefaultRedirectionSuite {
|
||||
return &DuoPushDefaultRedirectionSuite{RodSuite: new(RodSuite)}
|
||||
return &DuoPushDefaultRedirectionSuite{RodSuite: NewRodSuite(duoPushSuiteName)}
|
||||
}
|
||||
|
||||
func (s *DuoPushDefaultRedirectionSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
browser, err := StartRod()
|
||||
|
||||
if err != nil {
|
||||
|
@ -444,11 +448,15 @@ func (s *DuoPushDefaultRedirectionSuite) TestUserIsRedirectedToDefaultURL() {
|
|||
}
|
||||
|
||||
type DuoPushSuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
}
|
||||
|
||||
func NewDuoPushSuite() *DuoPushSuite {
|
||||
return &DuoPushSuite{}
|
||||
return &DuoPushSuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: duoPushSuiteName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DuoPushSuite) TestDuoPushWebDriverSuite() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type EnvoySuite struct {
|
|||
}
|
||||
|
||||
func NewEnvoySuite() *EnvoySuite {
|
||||
return &EnvoySuite{RodSuite: new(RodSuite)}
|
||||
return &EnvoySuite{
|
||||
RodSuite: NewRodSuite(envoySuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EnvoySuite) Test1FAScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type HAProxySuite struct {
|
|||
}
|
||||
|
||||
func NewHAProxySuite() *HAProxySuite {
|
||||
return &HAProxySuite{RodSuite: new(RodSuite)}
|
||||
return &HAProxySuite{
|
||||
RodSuite: NewRodSuite(haproxySuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HAProxySuite) Test1FAScenario() {
|
||||
|
|
|
@ -17,10 +17,14 @@ type HighAvailabilityWebDriverSuite struct {
|
|||
}
|
||||
|
||||
func NewHighAvailabilityWebDriverSuite() *HighAvailabilityWebDriverSuite {
|
||||
return &HighAvailabilityWebDriverSuite{RodSuite: new(RodSuite)}
|
||||
return &HighAvailabilityWebDriverSuite{
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HighAvailabilityWebDriverSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
browser, err := StartRod()
|
||||
|
||||
if err != nil {
|
||||
|
@ -183,7 +187,9 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldKeepSessionAfterAutheliaResta
|
|||
}
|
||||
|
||||
var UserJohn = "john"
|
||||
|
||||
var UserBob = "bob"
|
||||
|
||||
var UserHarry = "harry"
|
||||
|
||||
var Users = []string{UserJohn, UserBob, UserHarry}
|
||||
|
@ -263,11 +269,15 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldVerifyAccessControl() {
|
|||
}
|
||||
|
||||
type HighAvailabilitySuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
}
|
||||
|
||||
func NewHighAvailabilitySuite() *HighAvailabilitySuite {
|
||||
return &HighAvailabilitySuite{}
|
||||
return &HighAvailabilitySuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: highAvailabilitySuiteName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func DoGetWithAuth(t *testing.T, username, password string) int {
|
||||
|
|
|
@ -11,7 +11,9 @@ type KubernetesSuite struct {
|
|||
}
|
||||
|
||||
func NewKubernetesSuite() *KubernetesSuite {
|
||||
return &KubernetesSuite{RodSuite: new(RodSuite)}
|
||||
return &KubernetesSuite{
|
||||
RodSuite: NewRodSuite(kubernetesSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *KubernetesSuite) Test1FAScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type LDAPSuite struct {
|
|||
}
|
||||
|
||||
func NewLDAPSuite() *LDAPSuite {
|
||||
return &LDAPSuite{RodSuite: new(RodSuite)}
|
||||
return &LDAPSuite{
|
||||
RodSuite: NewRodSuite(ldapSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LDAPSuite) Test1FAScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type MariaDBSuite struct {
|
|||
}
|
||||
|
||||
func NewMariaDBSuite() *MariaDBSuite {
|
||||
return &MariaDBSuite{RodSuite: new(RodSuite)}
|
||||
return &MariaDBSuite{
|
||||
RodSuite: NewRodSuite(mariadbSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MariaDBSuite) Test1FAScenario() {
|
||||
|
|
|
@ -7,11 +7,15 @@ import (
|
|||
)
|
||||
|
||||
func NewMultiCookieDomainSuite() *MultiCookieDomainSuite {
|
||||
return &MultiCookieDomainSuite{}
|
||||
return &MultiCookieDomainSuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: multiCookieDomainSuiteName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type MultiCookieDomainSuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
}
|
||||
|
||||
func (s *MultiCookieDomainSuite) TestMultiCookieDomainFirstDomainScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type MySQLSuite struct {
|
|||
}
|
||||
|
||||
func NewMySQLSuite() *MySQLSuite {
|
||||
return &MySQLSuite{RodSuite: new(RodSuite)}
|
||||
return &MySQLSuite{
|
||||
RodSuite: NewRodSuite(mysqlSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MySQLSuite) Test1FAScenario() {
|
||||
|
|
|
@ -10,11 +10,15 @@ import (
|
|||
)
|
||||
|
||||
type NetworkACLSuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
}
|
||||
|
||||
func NewNetworkACLSuite() *NetworkACLSuite {
|
||||
return &NetworkACLSuite{}
|
||||
return &NetworkACLSuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: networkACLSuiteName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *NetworkACLSuite) TestShouldAccessSecretUpon2FA() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type OIDCSuite struct {
|
|||
}
|
||||
|
||||
func NewOIDCSuite() *OIDCSuite {
|
||||
return &OIDCSuite{RodSuite: new(RodSuite)}
|
||||
return &OIDCSuite{
|
||||
RodSuite: NewRodSuite(oidcSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *OIDCSuite) TestOIDCScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type OIDCTraefikSuite struct {
|
|||
}
|
||||
|
||||
func NewOIDCTraefikSuite() *OIDCTraefikSuite {
|
||||
return &OIDCTraefikSuite{RodSuite: new(RodSuite)}
|
||||
return &OIDCTraefikSuite{
|
||||
RodSuite: NewRodSuite(oidcTraefikSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *OIDCTraefikSuite) TestOIDCScenario() {
|
||||
|
|
|
@ -11,18 +11,18 @@ import (
|
|||
)
|
||||
|
||||
type OneFactorOnlySuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
type OneFactorOnlyWebSuite struct {
|
||||
*RodSuite
|
||||
}
|
||||
|
||||
func NewOneFactorOnlyWebSuite() *OneFactorOnlyWebSuite {
|
||||
return &OneFactorOnlyWebSuite{RodSuite: new(RodSuite)}
|
||||
func NewOneFactorOnlySuite() *OneFactorOnlySuite {
|
||||
return &OneFactorOnlySuite{
|
||||
RodSuite: NewRodSuite(oneFactorOnlySuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *OneFactorOnlyWebSuite) SetupSuite() {
|
||||
func (s *OneFactorOnlySuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
browser, err := StartRod()
|
||||
|
||||
if err != nil {
|
||||
|
@ -32,7 +32,7 @@ func (s *OneFactorOnlyWebSuite) SetupSuite() {
|
|||
s.RodSession = browser
|
||||
}
|
||||
|
||||
func (s *OneFactorOnlyWebSuite) TearDownSuite() {
|
||||
func (s *OneFactorOnlySuite) TearDownSuite() {
|
||||
err := s.RodSession.Stop()
|
||||
|
||||
if err != nil {
|
||||
|
@ -40,18 +40,18 @@ func (s *OneFactorOnlyWebSuite) TearDownSuite() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *OneFactorOnlyWebSuite) SetupTest() {
|
||||
func (s *OneFactorOnlySuite) SetupTest() {
|
||||
s.Page = s.doCreateTab(s.T(), HomeBaseURL)
|
||||
s.verifyIsHome(s.T(), s.Page)
|
||||
}
|
||||
|
||||
func (s *OneFactorOnlyWebSuite) TearDownTest() {
|
||||
func (s *OneFactorOnlySuite) TearDownTest() {
|
||||
s.collectCoverage(s.Page)
|
||||
s.MustClose()
|
||||
}
|
||||
|
||||
// No target url is provided, then the user should be redirect to the default url.
|
||||
func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURL() {
|
||||
func (s *OneFactorOnlySuite) TestShouldRedirectUserToDefaultURL() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer func() {
|
||||
cancel()
|
||||
|
@ -63,7 +63,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURL() {
|
|||
}
|
||||
|
||||
// Unsafe URL is provided, then the user should be redirect to the default url.
|
||||
func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURLWhenURLIsUnsafe() {
|
||||
func (s *OneFactorOnlySuite) TestShouldRedirectUserToDefaultURLWhenURLIsUnsafe() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer func() {
|
||||
cancel()
|
||||
|
@ -75,7 +75,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldRedirectUserToDefaultURLWhenURLIsUnsaf
|
|||
}
|
||||
|
||||
// When use logged in and visit the portal again, she gets redirect to the authenticated view.
|
||||
func (s *OneFactorOnlyWebSuite) TestShouldDisplayAuthenticatedView() {
|
||||
func (s *OneFactorOnlySuite) TestShouldDisplayAuthenticatedView() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer func() {
|
||||
cancel()
|
||||
|
@ -88,7 +88,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldDisplayAuthenticatedView() {
|
|||
s.verifyIsAuthenticatedPage(s.T(), s.Context(ctx))
|
||||
}
|
||||
|
||||
func (s *OneFactorOnlyWebSuite) TestShouldRedirectAlreadyAuthenticatedUser() {
|
||||
func (s *OneFactorOnlySuite) TestShouldRedirectAlreadyAuthenticatedUser() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer func() {
|
||||
cancel()
|
||||
|
@ -103,7 +103,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldRedirectAlreadyAuthenticatedUser() {
|
|||
s.verifyURLIs(s.T(), s.Context(ctx), "https://singlefactor.example.com:8080/secret.html")
|
||||
}
|
||||
|
||||
func (s *OneFactorOnlyWebSuite) TestShouldNotRedirectAlreadyAuthenticatedUserToUnsafeURL() {
|
||||
func (s *OneFactorOnlySuite) TestShouldNotRedirectAlreadyAuthenticatedUserToUnsafeURL() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer func() {
|
||||
cancel()
|
||||
|
@ -118,14 +118,10 @@ func (s *OneFactorOnlyWebSuite) TestShouldNotRedirectAlreadyAuthenticatedUserToU
|
|||
s.verifyNotificationDisplayed(s.T(), s.Context(ctx), "Redirection was determined to be unsafe and aborted. Ensure the redirection URL is correct.")
|
||||
}
|
||||
|
||||
func (s *OneFactorOnlySuite) TestWeb() {
|
||||
suite.Run(s.T(), NewOneFactorOnlyWebSuite())
|
||||
}
|
||||
|
||||
func TestOneFactorOnlySuite(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping suite test in short mode")
|
||||
}
|
||||
|
||||
suite.Run(t, new(OneFactorOnlySuite))
|
||||
suite.Run(t, NewOneFactorOnlySuite())
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ type PathPrefixSuite struct {
|
|||
}
|
||||
|
||||
func NewPathPrefixSuite() *PathPrefixSuite {
|
||||
return &PathPrefixSuite{RodSuite: new(RodSuite)}
|
||||
return &PathPrefixSuite{
|
||||
RodSuite: NewRodSuite(pathPrefixSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PathPrefixSuite) Test1FAScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type PostgresSuite struct {
|
|||
}
|
||||
|
||||
func NewPostgresSuite() *PostgresSuite {
|
||||
return &PostgresSuite{RodSuite: new(RodSuite)}
|
||||
return &PostgresSuite{
|
||||
RodSuite: NewRodSuite(postgresSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PostgresSuite) Test1FAScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type ShortTimeoutsSuite struct {
|
|||
}
|
||||
|
||||
func NewShortTimeoutsSuite() *ShortTimeoutsSuite {
|
||||
return &ShortTimeoutsSuite{RodSuite: new(RodSuite)}
|
||||
return &ShortTimeoutsSuite{
|
||||
RodSuite: NewRodSuite(shortTimeoutsSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ShortTimeoutsSuite) TestDefaultRedirectionURLScenario() {
|
||||
|
|
|
@ -22,10 +22,14 @@ type StandaloneWebDriverSuite struct {
|
|||
}
|
||||
|
||||
func NewStandaloneWebDriverSuite() *StandaloneWebDriverSuite {
|
||||
return &StandaloneWebDriverSuite{RodSuite: new(RodSuite)}
|
||||
return &StandaloneWebDriverSuite{
|
||||
RodSuite: NewRodSuite(""),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StandaloneWebDriverSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
browser, err := StartRod()
|
||||
|
||||
if err != nil {
|
||||
|
@ -169,11 +173,15 @@ func (s *StandaloneWebDriverSuite) TestShouldCheckUserIsAskedToRegisterDevice()
|
|||
}
|
||||
|
||||
type StandaloneSuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
}
|
||||
|
||||
func NewStandaloneSuite() *StandaloneSuite {
|
||||
return &StandaloneSuite{}
|
||||
return &StandaloneSuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: standaloneSuiteName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StandaloneSuite) TestShouldRespectMethodsACL() {
|
||||
|
|
|
@ -14,7 +14,9 @@ type Traefik2Suite struct {
|
|||
}
|
||||
|
||||
func NewTraefik2Suite() *Traefik2Suite {
|
||||
return &Traefik2Suite{RodSuite: new(RodSuite)}
|
||||
return &Traefik2Suite{
|
||||
RodSuite: NewRodSuite(traefik2SuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Traefik2Suite) Test1FAScenario() {
|
||||
|
|
|
@ -11,7 +11,9 @@ type TraefikSuite struct {
|
|||
}
|
||||
|
||||
func NewTraefikSuite() *TraefikSuite {
|
||||
return &TraefikSuite{RodSuite: new(RodSuite)}
|
||||
return &TraefikSuite{
|
||||
RodSuite: NewRodSuite(traefikSuiteName),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *TraefikSuite) Test1FAScenario() {
|
||||
|
|
|
@ -5,17 +5,31 @@ import (
|
|||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func NewRodSuite(name string) *RodSuite {
|
||||
return &RodSuite{
|
||||
BaseSuite: &BaseSuite{
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// RodSuite is a go-rod suite.
|
||||
type RodSuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
|
||||
*RodSession
|
||||
*rod.Page
|
||||
}
|
||||
|
||||
type BaseSuite struct {
|
||||
suite.Suite
|
||||
|
||||
Name string
|
||||
}
|
||||
|
||||
// CommandSuite is a command line interface suite.
|
||||
type CommandSuite struct {
|
||||
suite.Suite
|
||||
*BaseSuite
|
||||
|
||||
testArg string //nolint:structcheck // TODO: Remove when bug fixed: https://github.com/golangci/golangci-lint/issues/537.
|
||||
coverageArg string //nolint:structcheck // TODO: Remove when bug fixed: https://github.com/golangci/golangci-lint/issues/537.
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package suites
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -16,6 +16,7 @@ import (
|
|||
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var browserPaths = []string{"/usr/bin/chromium-browser", "/usr/bin/chromium"}
|
||||
|
@ -52,8 +53,8 @@ func GetBrowserPath() (path string, err error) {
|
|||
|
||||
// GetLoginBaseURL returns the URL of the login portal and the path prefix if specified.
|
||||
func GetLoginBaseURL(baseDomain string) string {
|
||||
if PathPrefix != "" {
|
||||
return LoginBaseURLFmt(baseDomain) + PathPrefix
|
||||
if pathPrefix := os.Getenv("PathPrefix"); pathPrefix != "" {
|
||||
return LoginBaseURLFmt(baseDomain) + pathPrefix
|
||||
}
|
||||
|
||||
return LoginBaseURLFmt(baseDomain)
|
||||
|
@ -84,6 +85,87 @@ func (rs *RodSession) collectCoverage(page *rod.Page) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *BaseSuite) SetupSuite() {
|
||||
s.SetupLogging()
|
||||
s.SetupEnvironment()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) SetupLogging() {
|
||||
if os.Getenv("SUITE_SETUP_LOGGING") == t {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
level string
|
||||
ok bool
|
||||
)
|
||||
|
||||
if level, ok = os.LookupEnv("SUITES_LOG_LEVEL"); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
l, err := log.ParseLevel(level)
|
||||
|
||||
s.NoError(err)
|
||||
|
||||
log.SetLevel(l)
|
||||
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
ForceColors: true,
|
||||
})
|
||||
|
||||
s.T().Setenv("SUITE_SETUP_LOGGING", t)
|
||||
}
|
||||
|
||||
func (s *BaseSuite) SetupEnvironment() {
|
||||
if s.Name == "" || os.Getenv("SUITE_SETUP_ENVIRONMENT") == t {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("Checking Suite %s for .env file", s.Name)
|
||||
|
||||
path := filepath.Join(s.Name, ".env")
|
||||
|
||||
var (
|
||||
info os.FileInfo
|
||||
err error
|
||||
)
|
||||
|
||||
path, err = filepath.Abs(path)
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
if info, err = os.Stat(path); err != nil {
|
||||
s.Assert().True(os.IsNotExist(err))
|
||||
|
||||
log.Debugf("Suite %s does not have an .env file or it can't be read: %v", s.Name, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
s.Require().False(info.IsDir())
|
||||
|
||||
log.Debugf("Suite %s does have an .env file at path: %s", s.Name, path)
|
||||
|
||||
var file *os.File
|
||||
|
||||
file, err = os.Open(path)
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
for scanner.Scan() {
|
||||
v := strings.Split(scanner.Text(), "=")
|
||||
|
||||
s.Require().Len(v, 2)
|
||||
|
||||
s.T().Setenv(v[0], v[1])
|
||||
}
|
||||
|
||||
s.T().Setenv("SUITE_SETUP_ENVIRONMENT", t)
|
||||
}
|
||||
|
||||
func (rs *RodSession) collectScreenshot(err error, page *rod.Page) {
|
||||
if err == context.DeadlineExceeded && os.Getenv("CI") == t {
|
||||
base := "/buildkite/screenshots"
|
||||
|
@ -140,7 +222,7 @@ func fixCoveragePath(path string, file os.FileInfo, err error) error {
|
|||
}
|
||||
|
||||
// getEnvInfoFromURL gets environments variables for specified cookie domain
|
||||
// this func makes a http call to https://login.<domain>/override and is only useful for suite tests.
|
||||
// this func makes a http call to https://login.<domain>/devworkflow and is only useful for suite tests.
|
||||
func getDomainEnvInfo(domain string) (map[string]string, error) {
|
||||
info := make(map[string]string)
|
||||
|
||||
|
@ -186,18 +268,12 @@ func getDomainEnvInfo(domain string) (map[string]string, error) {
|
|||
|
||||
// generateDevEnvFile generates web/.env.development based on opts.
|
||||
func generateDevEnvFile(opts map[string]string) error {
|
||||
wd, _ := os.Getwd()
|
||||
path := strings.TrimSuffix(wd, "internal/suites")
|
||||
|
||||
src := fmt.Sprintf("%s/web/.env.production", path)
|
||||
dst := fmt.Sprintf("%s/web/.env.development", path)
|
||||
|
||||
tmpl, err := template.ParseFiles(src)
|
||||
tmpl, err := template.ParseFiles(envFileProd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, _ := os.Create(dst)
|
||||
file, _ := os.Create(envFileDev)
|
||||
defer file.Close()
|
||||
|
||||
if err := tmpl.Execute(file, opts); err != nil {
|
||||
|
@ -210,10 +286,15 @@ func generateDevEnvFile(opts map[string]string) error {
|
|||
// updateDevEnvFileForDomain updates web/.env.development.
|
||||
// this function only affects local dev environments.
|
||||
func updateDevEnvFileForDomain(domain string, setup bool) error {
|
||||
if os.Getenv("CI") == "true" {
|
||||
if os.Getenv("CI") == t {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := os.Stat(envFileDev); err != nil && os.IsNotExist(err) {
|
||||
file, _ := os.Create(envFileDev)
|
||||
file.Close()
|
||||
}
|
||||
|
||||
info, err := getDomainEnvInfo(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -36,7 +36,9 @@ func TestShouldReturnErrWhenX509DirectoryNotExist(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestShouldNotReturnErrWhenX509DirectoryExist(t *testing.T) {
|
||||
pool, warnings, errors := NewX509CertPool("/tmp")
|
||||
dir := t.TempDir()
|
||||
|
||||
pool, warnings, errors := NewX509CertPool(dir)
|
||||
assert.NotNil(t, pool)
|
||||
|
||||
if runtime.GOOS == windows {
|
||||
|
|
Loading…
Reference in New Issue