[CI] Add PathPrefix integration test suite (#1052)
Add a suite for testing the PathPrefix feature implemented earlier to serve authelia under a multi-purpose domain. Co-authored-by: Clément Michaud <clement.michaud34@gmail.com>pull/1058/head
parent
54fe2a9abd
commit
b27c1fbae9
|
@ -1,9 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/otiai10/copy"
|
"github.com/otiai10/copy"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
@ -87,6 +89,27 @@ func setupSuite(cmd *cobra.Command, args []string) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suiteEnv := suiteResourcePath + "/.env"
|
||||||
|
|
||||||
|
_, err = os.Stat(suiteEnv)
|
||||||
|
if err == nil {
|
||||||
|
file, err := os.Open(suiteEnv)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
env := bufio.NewScanner(file)
|
||||||
|
|
||||||
|
for env.Scan() {
|
||||||
|
v := strings.Split(env.Text(), "=")
|
||||||
|
|
||||||
|
err := os.Setenv(v[0], v[1])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suiteTmpDirectory := tmpDirectory + suiteName
|
suiteTmpDirectory := tmpDirectory + suiteName
|
||||||
|
|
||||||
if exist {
|
if exist {
|
||||||
|
|
|
@ -131,10 +131,10 @@ func StartServer(configuration schema.Configuration, providers middlewares.Provi
|
||||||
addrPattern := fmt.Sprintf("%s:%d", configuration.Host, configuration.Port)
|
addrPattern := fmt.Sprintf("%s:%d", configuration.Host, configuration.Port)
|
||||||
|
|
||||||
if configuration.TLSCert != "" && configuration.TLSKey != "" {
|
if configuration.TLSCert != "" && configuration.TLSKey != "" {
|
||||||
logging.Logger().Infof("Authelia is listening for TLS connections on %s", addrPattern)
|
logging.Logger().Infof("Authelia is listening for TLS connections on %s%s", addrPattern, configuration.Server.Path)
|
||||||
logging.Logger().Fatal(server.ListenAndServeTLS(addrPattern, configuration.TLSCert, configuration.TLSKey))
|
logging.Logger().Fatal(server.ListenAndServeTLS(addrPattern, configuration.TLSCert, configuration.TLSKey))
|
||||||
} else {
|
} else {
|
||||||
logging.Logger().Infof("Authelia is listening for non-TLS connections on %s", addrPattern)
|
logging.Logger().Infof("Authelia is listening for non-TLS connections on %s%s", addrPattern, configuration.Server.Path)
|
||||||
logging.Logger().Fatal(server.ListenAndServe(addrPattern))
|
logging.Logger().Fatal(server.ListenAndServe(addrPattern))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
PathPrefix=/auth
|
|
@ -0,0 +1,48 @@
|
||||||
|
###############################################################
|
||||||
|
# Authelia minimal configuration #
|
||||||
|
###############################################################
|
||||||
|
|
||||||
|
port: 9091
|
||||||
|
tls_cert: /var/lib/authelia/ssl/cert.pem
|
||||||
|
tls_key: /var/lib/authelia/ssl/key.pem
|
||||||
|
|
||||||
|
server:
|
||||||
|
path: auth
|
||||||
|
|
||||||
|
log_level: debug
|
||||||
|
|
||||||
|
jwt_secret: unsecure_secret
|
||||||
|
|
||||||
|
authentication_backend:
|
||||||
|
file:
|
||||||
|
path: /var/lib/authelia/users.yml
|
||||||
|
|
||||||
|
session:
|
||||||
|
secret: unsecure_session_secret
|
||||||
|
domain: example.com
|
||||||
|
expiration: 3600 # 1 hour
|
||||||
|
inactivity: 300 # 5 minutes
|
||||||
|
remember_me_duration: 1y
|
||||||
|
|
||||||
|
storage:
|
||||||
|
local:
|
||||||
|
path: /var/lib/authelia/db.sqlite
|
||||||
|
|
||||||
|
access_control:
|
||||||
|
default_policy: bypass
|
||||||
|
rules:
|
||||||
|
- domain: "public.example.com"
|
||||||
|
policy: bypass
|
||||||
|
- domain: "admin.example.com"
|
||||||
|
policy: two_factor
|
||||||
|
- domain: "secure.example.com"
|
||||||
|
policy: two_factor
|
||||||
|
- domain: "singlefactor.example.com"
|
||||||
|
policy: one_factor
|
||||||
|
|
||||||
|
notifier:
|
||||||
|
smtp:
|
||||||
|
host: smtp
|
||||||
|
port: 1025
|
||||||
|
sender: admin@example.com
|
||||||
|
disable_require_tls: true
|
|
@ -0,0 +1,7 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
authelia-backend:
|
||||||
|
volumes:
|
||||||
|
- './PathPrefix/configuration.yml:/etc/authelia/configuration.yml:ro'
|
||||||
|
- './PathPrefix/users.yml:/var/lib/authelia/users.yml'
|
||||||
|
- './common/ssl:/var/lib/authelia/ssl:ro'
|
|
@ -0,0 +1,29 @@
|
||||||
|
###############################################################
|
||||||
|
# Users Database #
|
||||||
|
###############################################################
|
||||||
|
|
||||||
|
# This file can be used if you do not have an LDAP set up.
|
||||||
|
|
||||||
|
# List of users
|
||||||
|
users:
|
||||||
|
john:
|
||||||
|
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: john.doe@authelia.com
|
||||||
|
groups:
|
||||||
|
- admins
|
||||||
|
- dev
|
||||||
|
|
||||||
|
harry:
|
||||||
|
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: harry.potter@authelia.com
|
||||||
|
groups: []
|
||||||
|
|
||||||
|
bob:
|
||||||
|
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: bob.dylan@authelia.com
|
||||||
|
groups:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
james:
|
||||||
|
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: james.dean@authelia.com
|
|
@ -49,7 +49,7 @@ func (wds *WebDriverSession) doLoginTwoFactor(ctx context.Context, t *testing.T,
|
||||||
func (wds *WebDriverSession) doLoginAndRegisterTOTP(ctx context.Context, t *testing.T, username, password string, keepMeLoggedIn bool) string {
|
func (wds *WebDriverSession) doLoginAndRegisterTOTP(ctx context.Context, t *testing.T, username, password string, keepMeLoggedIn bool) string {
|
||||||
wds.doLoginOneFactor(ctx, t, username, password, keepMeLoggedIn, "")
|
wds.doLoginOneFactor(ctx, t, username, password, keepMeLoggedIn, "")
|
||||||
secret := wds.doRegisterTOTP(ctx, t)
|
secret := wds.doRegisterTOTP(ctx, t)
|
||||||
wds.doVisit(t, LoginBaseURL)
|
wds.doVisit(t, GetLoginBaseURL())
|
||||||
wds.verifyIsSecondFactorPage(ctx, t)
|
wds.verifyIsSecondFactorPage(ctx, t)
|
||||||
|
|
||||||
return secret
|
return secret
|
||||||
|
|
|
@ -7,6 +7,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (wds *WebDriverSession) doLogout(ctx context.Context, t *testing.T) {
|
func (wds *WebDriverSession) doLogout(ctx context.Context, t *testing.T) {
|
||||||
wds.doVisit(t, fmt.Sprintf("%s%s", LoginBaseURL, "/logout"))
|
wds.doVisit(t, fmt.Sprintf("%s%s", GetLoginBaseURL(), "/logout"))
|
||||||
wds.verifyIsFirstFactorPage(ctx, t)
|
wds.verifyIsFirstFactorPage(ctx, t)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,5 @@ func (wds *WebDriverSession) doVisitLoginPage(ctx context.Context, t *testing.T,
|
||||||
suffix = fmt.Sprintf("?rd=%s", targetURL)
|
suffix = fmt.Sprintf("?rd=%s", targetURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
wds.doVisitAndVerifyOneFactorStep(ctx, t, fmt.Sprintf("%s/%s", LoginBaseURL, suffix))
|
wds.doVisitAndVerifyOneFactorStep(ctx, t, fmt.Sprintf("%s/%s", GetLoginBaseURL(), suffix))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
package suites
|
package suites
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
// BaseDomain the base domain.
|
// BaseDomain the base domain.
|
||||||
var BaseDomain = "example.com:8080"
|
var BaseDomain = "example.com:8080"
|
||||||
|
|
||||||
|
// PathPrefix the prefix/url_base of the login portal.
|
||||||
|
var PathPrefix = os.Getenv("PathPrefix")
|
||||||
|
|
||||||
// LoginBaseURL the base URL of the login portal.
|
// LoginBaseURL the base URL of the login portal.
|
||||||
var LoginBaseURL = fmt.Sprintf("https://login.%s", BaseDomain)
|
var LoginBaseURL = fmt.Sprintf("https://login.%s", BaseDomain)
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ services:
|
||||||
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/api'
|
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/api'
|
||||||
- 'traefik.protocol=https'
|
- 'traefik.protocol=https'
|
||||||
# Traefik 2.x
|
# Traefik 2.x
|
||||||
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/api`)'
|
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/api`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/api`)'
|
||||||
- 'traefik.http.routers.authelia_backend.entrypoints=https'
|
- 'traefik.http.routers.authelia_backend.entrypoints=https'
|
||||||
- 'traefik.http.routers.authelia_backend.tls=true'
|
- 'traefik.http.routers.authelia_backend.tls=true'
|
||||||
- 'traefik.http.services.authelia_backend.loadbalancer.server.scheme=https'
|
- 'traefik.http.services.authelia_backend.loadbalancer.server.scheme=https'
|
||||||
|
|
|
@ -7,7 +7,7 @@ services:
|
||||||
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/api'
|
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/api'
|
||||||
- 'traefik.protocol=https'
|
- 'traefik.protocol=https'
|
||||||
# Traefik 2.x
|
# Traefik 2.x
|
||||||
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/api`)'
|
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/api`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}/api`)'
|
||||||
- 'traefik.http.routers.authelia_backend.entrypoints=https'
|
- 'traefik.http.routers.authelia_backend.entrypoints=https'
|
||||||
- 'traefik.http.routers.authelia_backend.tls=true'
|
- 'traefik.http.routers.authelia_backend.tls=true'
|
||||||
- 'traefik.http.services.authelia_backend.loadbalancer.server.scheme=https'
|
- 'traefik.http.services.authelia_backend.loadbalancer.server.scheme=https'
|
||||||
|
|
|
@ -17,8 +17,10 @@ services:
|
||||||
# Traefik 1.x
|
# Traefik 1.x
|
||||||
- 'traefik.frontend.rule=Host:login.example.com'
|
- 'traefik.frontend.rule=Host:login.example.com'
|
||||||
# Traefik 2.x
|
# Traefik 2.x
|
||||||
- 'traefik.http.routers.authelia_frontend.rule=Host(`login.example.com`)'
|
- 'traefik.http.routers.authelia_frontend.rule=Host(`login.example.com`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}`)'
|
||||||
- 'traefik.http.routers.authelia_frontend.entrypoints=https'
|
- 'traefik.http.routers.authelia_frontend.entrypoints=https'
|
||||||
- 'traefik.http.routers.authelia_frontend.tls=true'
|
- 'traefik.http.routers.authelia_frontend.tls=true'
|
||||||
|
environment:
|
||||||
|
- PUBLIC_URL=${PathPrefix}
|
||||||
networks:
|
networks:
|
||||||
- authelianet
|
- authelianet
|
||||||
|
|
|
@ -8,7 +8,7 @@ services:
|
||||||
# Traefik 1.x
|
# Traefik 1.x
|
||||||
- 'traefik.frontend.rule=Host:login.example.com'
|
- 'traefik.frontend.rule=Host:login.example.com'
|
||||||
# Traefik 2.x
|
# Traefik 2.x
|
||||||
- 'traefik.http.routers.authelia_frontend.rule=Host(`login.example.com`)'
|
- 'traefik.http.routers.authelia_frontend.rule=Host(`login.example.com`) || Host(`login.example.com`) && PathPrefix(`${PathPrefix}`)'
|
||||||
- 'traefik.http.routers.authelia_frontend.entrypoints=https'
|
- 'traefik.http.routers.authelia_frontend.entrypoints=https'
|
||||||
- 'traefik.http.routers.authelia_frontend.tls=true'
|
- 'traefik.http.routers.authelia_frontend.tls=true'
|
||||||
- 'traefik.http.services.authelia_frontend.loadbalancer.server.port=3000'
|
- 'traefik.http.services.authelia_frontend.loadbalancer.server.port=3000'
|
||||||
|
|
|
@ -16,8 +16,4 @@ services:
|
||||||
- 'traefik.http.routers.httpbin.rule=Host(`public.example.com`) && Path(`/headers`)'
|
- 'traefik.http.routers.httpbin.rule=Host(`public.example.com`) && Path(`/headers`)'
|
||||||
- 'traefik.http.routers.httpbin.priority=150'
|
- 'traefik.http.routers.httpbin.priority=150'
|
||||||
- 'traefik.http.routers.httpbin.tls=true'
|
- 'traefik.http.routers.httpbin.tls=true'
|
||||||
- 'traefik.http.routers.httpbin.middlewares=authelia'
|
- 'traefik.http.routers.httpbin.middlewares=authelia@docker'
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.address=https://authelia-backend:9091/api/verify?rd=https://login.example.com:8080/'
|
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.tls.insecureSkipVerify=true'
|
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true'
|
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups'
|
|
||||||
|
|
|
@ -4,18 +4,14 @@ services:
|
||||||
image: nginx:alpine
|
image: nginx:alpine
|
||||||
labels:
|
labels:
|
||||||
- 'traefik.frontend.rule=Host:home.example.com,public.example.com,secure.example.com,admin.example.com,singlefactor.example.com' # Traefik 1.x
|
- 'traefik.frontend.rule=Host:home.example.com,public.example.com,secure.example.com,admin.example.com,singlefactor.example.com' # Traefik 1.x
|
||||||
- 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/verify?rd=https://login.example.com:8080/' # Traefik 1.x
|
- 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/verify?rd=https://login.example.com:8080' # Traefik 1.x
|
||||||
- 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true' # Traefik 1.x
|
- 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true' # Traefik 1.x
|
||||||
- 'traefik.frontend.auth.forward.trustForwardHeader=true' # Traefik 1.x
|
- 'traefik.frontend.auth.forward.trustForwardHeader=true' # Traefik 1.x
|
||||||
- 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups' # Traefik 1.x
|
- 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups' # Traefik 1.x
|
||||||
- 'traefik.http.routers.protectedapps.rule=Host(`home.example.com`, `public.example.com`, `secure.example.com`, `admin.example.com`, `singlefactor.example.com`)' # Traefik 2.x
|
- 'traefik.http.routers.protectedapps.rule=Host(`home.example.com`, `public.example.com`, `secure.example.com`, `admin.example.com`, `singlefactor.example.com`)' # Traefik 2.x
|
||||||
- 'traefik.http.routers.protectedapps.entrypoints=https' # Traefik 2.x
|
- 'traefik.http.routers.protectedapps.entrypoints=https' # Traefik 2.x
|
||||||
- 'traefik.http.routers.protectedapps.tls=true' # Traefik 2.x
|
- 'traefik.http.routers.protectedapps.tls=true' # Traefik 2.x
|
||||||
- 'traefik.http.routers.protectedapps.middlewares=authelia' # Traefik 2.x
|
- 'traefik.http.routers.protectedapps.middlewares=authelia@docker' # Traefik 2.x
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.address=https://authelia-backend:9091/api/verify?rd=https://login.example.com:8080/' # Traefik 2.x
|
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.tls.insecureSkipVerify=true' # Traefik 2.x
|
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true' # Traefik 2.x
|
|
||||||
- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups' # Traefik 2.x
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./example/compose/nginx/backend/html:/usr/share/nginx/html
|
- ./example/compose/nginx/backend/html:/usr/share/nginx/html
|
||||||
- ./example/compose/nginx/backend/nginx.conf:/etc/nginx/nginx.conf
|
- ./example/compose/nginx/backend/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:v2.1.2
|
image: traefik:v2.2.1
|
||||||
volumes:
|
volumes:
|
||||||
- '/var/run/docker.sock:/var/run/docker.sock'
|
- '/var/run/docker.sock:/var/run/docker.sock'
|
||||||
labels:
|
labels:
|
||||||
|
@ -9,6 +9,10 @@ services:
|
||||||
- 'traefik.http.routers.api.entrypoints=https'
|
- 'traefik.http.routers.api.entrypoints=https'
|
||||||
- 'traefik.http.routers.api.service=api@internal'
|
- 'traefik.http.routers.api.service=api@internal'
|
||||||
- 'traefik.http.routers.api.tls=true'
|
- 'traefik.http.routers.api.tls=true'
|
||||||
|
- 'traefik.http.middlewares.authelia.forwardauth.address=https://authelia-backend:9091${PathPrefix}/api/verify?rd=https://login.example.com:8080${PathPrefix}' # Traefik 2.x
|
||||||
|
- 'traefik.http.middlewares.authelia.forwardauth.tls.insecureSkipVerify=true' # Traefik 2.x
|
||||||
|
- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true' # Traefik 2.x
|
||||||
|
- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups' # Traefik 2.x
|
||||||
command:
|
command:
|
||||||
- '--api'
|
- '--api'
|
||||||
- '--providers.docker=true'
|
- '--providers.docker=true'
|
||||||
|
|
|
@ -48,7 +48,7 @@ func (s *ResetPasswordScenario) TestShouldResetPassword() {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
s.doVisit(s.T(), LoginBaseURL)
|
s.doVisit(s.T(), GetLoginBaseURL())
|
||||||
s.verifyIsFirstFactorPage(ctx, s.T())
|
s.verifyIsFirstFactorPage(ctx, s.T())
|
||||||
|
|
||||||
// Reset the password to abc
|
// Reset the password to abc
|
||||||
|
@ -72,7 +72,7 @@ func (s *ResetPasswordScenario) TestShouldMakeAttackerThinkPasswordResetIsInitia
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
s.doVisit(s.T(), LoginBaseURL)
|
s.doVisit(s.T(), GetLoginBaseURL())
|
||||||
s.verifyIsFirstFactorPage(ctx, s.T())
|
s.verifyIsFirstFactorPage(ctx, s.T())
|
||||||
|
|
||||||
// Try to initiate a password reset of an nonexistent user.
|
// Try to initiate a password reset of an nonexistent user.
|
||||||
|
@ -86,7 +86,7 @@ func (s *ResetPasswordScenario) TestShouldLetUserNoticeThereIsAPasswordMismatch(
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
s.doVisit(s.T(), LoginBaseURL)
|
s.doVisit(s.T(), GetLoginBaseURL())
|
||||||
s.verifyIsFirstFactorPage(ctx, s.T())
|
s.verifyIsFirstFactorPage(ctx, s.T())
|
||||||
|
|
||||||
s.doInitiatePasswordReset(ctx, s.T(), "john")
|
s.doInitiatePasswordReset(ctx, s.T(), "john")
|
||||||
|
|
|
@ -63,7 +63,7 @@ func (s *UserPreferencesScenario) TestShouldRememberLastUsed2FAMethod() {
|
||||||
s.verifyIsHome(ctx, s.T())
|
s.verifyIsHome(ctx, s.T())
|
||||||
|
|
||||||
// Then go back to portal.
|
// Then go back to portal.
|
||||||
s.doVisit(s.T(), LoginBaseURL)
|
s.doVisit(s.T(), GetLoginBaseURL())
|
||||||
s.verifyIsSecondFactorPage(ctx, s.T())
|
s.verifyIsSecondFactorPage(ctx, s.T())
|
||||||
// And check the latest method is still used.
|
// And check the latest method is still used.
|
||||||
s.WaitElementLocatedByID(ctx, s.T(), "push-notification-method")
|
s.WaitElementLocatedByID(ctx, s.T(), "push-notification-method")
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (s *HighAvailabilityWebDriverSuite) TestShouldKeepSessionAfterAutheliaResta
|
||||||
s.verifyIsHome(ctx, s.T())
|
s.verifyIsHome(ctx, s.T())
|
||||||
|
|
||||||
// Verify the user is still authenticated
|
// Verify the user is still authenticated
|
||||||
s.doVisit(s.T(), LoginBaseURL)
|
s.doVisit(s.T(), GetLoginBaseURL())
|
||||||
s.verifyIsSecondFactorPage(ctx, s.T())
|
s.verifyIsSecondFactorPage(ctx, s.T())
|
||||||
|
|
||||||
// Then logout and login again to check the secret is still there
|
// Then logout and login again to check the secret is still there
|
||||||
|
|
|
@ -71,7 +71,7 @@ func (s *OneFactorOnlyWebSuite) TestShouldDisplayAuthenticatedView() {
|
||||||
|
|
||||||
s.doLoginOneFactor(ctx, s.T(), "john", "password", false, "http://unsafe.local")
|
s.doLoginOneFactor(ctx, s.T(), "john", "password", false, "http://unsafe.local")
|
||||||
s.verifyURLIs(ctx, s.T(), HomeBaseURL+"/")
|
s.verifyURLIs(ctx, s.T(), HomeBaseURL+"/")
|
||||||
s.doVisit(s.T(), LoginBaseURL)
|
s.doVisit(s.T(), GetLoginBaseURL())
|
||||||
s.verifyIsAuthenticatedPage(ctx, s.T())
|
s.verifyIsAuthenticatedPage(ctx, s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package suites
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pathPrefixSuiteName = "PathPrefix"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dockerEnvironment := NewDockerEnvironment([]string{
|
||||||
|
"internal/suites/docker-compose.yml",
|
||||||
|
"internal/suites/PathPrefix/docker-compose.yml",
|
||||||
|
"internal/suites/example/compose/authelia/docker-compose.backend.{}.yml",
|
||||||
|
"internal/suites/example/compose/authelia/docker-compose.frontend.{}.yml",
|
||||||
|
"internal/suites/example/compose/nginx/backend/docker-compose.yml",
|
||||||
|
"internal/suites/example/compose/traefik2/docker-compose.yml",
|
||||||
|
"internal/suites/example/compose/smtp/docker-compose.yml",
|
||||||
|
"internal/suites/example/compose/httpbin/docker-compose.yml",
|
||||||
|
})
|
||||||
|
|
||||||
|
setup := func(suitePath string) error {
|
||||||
|
err := dockerEnvironment.Up()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return waitUntilAutheliaIsReady(dockerEnvironment)
|
||||||
|
}
|
||||||
|
|
||||||
|
displayAutheliaLogs := func() error {
|
||||||
|
backendLogs, err := dockerEnvironment.Logs("authelia-backend", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(backendLogs)
|
||||||
|
|
||||||
|
frontendLogs, err := dockerEnvironment.Logs("authelia-frontend", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(frontendLogs)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown := func(suitePath string) error {
|
||||||
|
err := dockerEnvironment.Down()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalRegistry.Register(pathPrefixSuiteName, Suite{
|
||||||
|
SetUp: setup,
|
||||||
|
SetUpTimeout: 5 * time.Minute,
|
||||||
|
OnSetupTimeout: displayAutheliaLogs,
|
||||||
|
OnError: displayAutheliaLogs,
|
||||||
|
TestTimeout: 2 * time.Minute,
|
||||||
|
TearDown: teardown,
|
||||||
|
TearDownTimeout: 2 * time.Minute,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package suites
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PathPrefixSuite struct {
|
||||||
|
*SeleniumSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPathPrefixSuite() *PathPrefixSuite {
|
||||||
|
return &PathPrefixSuite{SeleniumSuite: new(SeleniumSuite)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PathPrefixSuite) TestOneFactorScenario() {
|
||||||
|
suite.Run(s.T(), NewOneFactorScenario())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PathPrefixSuite) TestTwoFactorScenario() {
|
||||||
|
suite.Run(s.T(), NewTwoFactorScenario())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PathPrefixSuite) TestCustomHeaders() {
|
||||||
|
suite.Run(s.T(), NewCustomHeadersScenario())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PathPrefixSuite) TestResetPasswordScenario() {
|
||||||
|
suite.Run(s.T(), NewResetPasswordScenario())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathPrefixSuite(t *testing.T) {
|
||||||
|
suite.Run(t, NewPathPrefixSuite())
|
||||||
|
}
|
|
@ -62,7 +62,7 @@ func (s *StandaloneWebDriverSuite) TestShouldLetUserKnowHeIsAlreadyAuthenticated
|
||||||
s.verifyIsHome(ctx, s.T())
|
s.verifyIsHome(ctx, s.T())
|
||||||
|
|
||||||
// Visit the login page and wait for redirection to 2FA page with success icon displayed.
|
// Visit the login page and wait for redirection to 2FA page with success icon displayed.
|
||||||
s.doVisit(s.T(), LoginBaseURL)
|
s.doVisit(s.T(), GetLoginBaseURL())
|
||||||
s.verifyIsAuthenticatedPage(ctx, s.T())
|
s.verifyIsAuthenticatedPage(ctx, s.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ func (s *StandaloneSuite) TestShouldVerifyAPIVerifyUnauthorize() {
|
||||||
|
|
||||||
// Standard case using Kubernetes.
|
// Standard case using Kubernetes.
|
||||||
func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalURL() {
|
func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalURL() {
|
||||||
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/verify?rd=%s", AutheliaBaseURL, LoginBaseURL), nil)
|
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/verify?rd=%s", AutheliaBaseURL, GetLoginBaseURL()), nil)
|
||||||
s.Assert().NoError(err)
|
s.Assert().NoError(err)
|
||||||
req.Header.Set("X-Forwarded-Proto", "https")
|
req.Header.Set("X-Forwarded-Proto", "https")
|
||||||
req.Header.Set("X-Original-URL", AdminBaseURL)
|
req.Header.Set("X-Original-URL", AdminBaseURL)
|
||||||
|
@ -134,11 +134,11 @@ func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalURL() {
|
||||||
s.Assert().NoError(err)
|
s.Assert().NoError(err)
|
||||||
|
|
||||||
urlEncodedAdminURL := url.QueryEscape(AdminBaseURL)
|
urlEncodedAdminURL := url.QueryEscape(AdminBaseURL)
|
||||||
s.Assert().Equal(fmt.Sprintf("Found. Redirecting to %s?rd=%s", LoginBaseURL, urlEncodedAdminURL), string(body))
|
s.Assert().Equal(fmt.Sprintf("Found. Redirecting to %s?rd=%s", GetLoginBaseURL(), urlEncodedAdminURL), string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalHostURI() {
|
func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalHostURI() {
|
||||||
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/verify?rd=%s", AutheliaBaseURL, LoginBaseURL), nil)
|
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/verify?rd=%s", AutheliaBaseURL, GetLoginBaseURL()), nil)
|
||||||
s.Assert().NoError(err)
|
s.Assert().NoError(err)
|
||||||
req.Header.Set("X-Forwarded-Proto", "https")
|
req.Header.Set("X-Forwarded-Proto", "https")
|
||||||
req.Header.Set("X-Forwarded-Host", "secure.example.com:8080")
|
req.Header.Set("X-Forwarded-Host", "secure.example.com:8080")
|
||||||
|
@ -152,7 +152,7 @@ func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalHostURI(
|
||||||
s.Assert().NoError(err)
|
s.Assert().NoError(err)
|
||||||
|
|
||||||
urlEncodedAdminURL := url.QueryEscape(SecureBaseURL + "/")
|
urlEncodedAdminURL := url.QueryEscape(SecureBaseURL + "/")
|
||||||
s.Assert().Equal(fmt.Sprintf("Found. Redirecting to %s?rd=%s", LoginBaseURL, urlEncodedAdminURL), string(body))
|
s.Assert().Equal(fmt.Sprintf("Found. Redirecting to %s?rd=%s", GetLoginBaseURL(), urlEncodedAdminURL), string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StandaloneSuite) TestStandaloneWebDriverScenario() {
|
func (s *StandaloneSuite) TestStandaloneWebDriverScenario() {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package suites
|
||||||
|
|
||||||
|
// GetLoginBaseURL returns the URL of the login portal and the path prefix if specified.
|
||||||
|
func GetLoginBaseURL() string {
|
||||||
|
if PathPrefix != "" {
|
||||||
|
return LoginBaseURL + PathPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoginBaseURL
|
||||||
|
}
|
Loading…
Reference in New Issue