mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
ce7b6b8167
* Build docker image upfront in CI and use it in integration tests. Previously, the development workflow was broken because the container generated from Dockerfile.CI was used in dev environments but the binary was not pre-built as it is on buildkite. I propose to just remove that image and use the "to be published" image instead in integration tests. This will have several advantages: - Fix the dev workflow. - Remove CI arch from authelia-scripts build command - Optimize CI time in buildkite since we'll cache a way small artifact - We don't build authelia more than once for earch arch. * Fix suites and only build ARM images on master or tagged commits * Optimise pipeline dependencies and Kubernetes suite to utilise cache * Run unit tests and docker image build in parallel. * Fix suite trying to write on read only fs. Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
186 lines
5.1 KiB
Go
186 lines
5.1 KiB
Go
package suites
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/authelia/authelia/internal/storage"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
type StandaloneWebDriverSuite struct {
|
|
*SeleniumSuite
|
|
}
|
|
|
|
func NewStandaloneWebDriverSuite() *StandaloneWebDriverSuite {
|
|
return &StandaloneWebDriverSuite{SeleniumSuite: new(SeleniumSuite)}
|
|
}
|
|
|
|
func (s *StandaloneWebDriverSuite) SetupSuite() {
|
|
wds, err := StartWebDriver()
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
s.WebDriverSession = wds
|
|
}
|
|
|
|
func (s *StandaloneWebDriverSuite) TearDownSuite() {
|
|
err := s.WebDriverSession.Stop()
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func (s *StandaloneWebDriverSuite) SetupTest() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
s.doLogout(ctx, s.T())
|
|
s.WebDriverSession.doVisit(s.T(), HomeBaseURL)
|
|
s.verifyIsHome(ctx, s.T())
|
|
}
|
|
|
|
func (s *StandaloneWebDriverSuite) TestShouldLetUserKnowHeIsAlreadyAuthenticated() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
|
defer cancel()
|
|
|
|
_ = s.doRegisterAndLogin2FA(ctx, s.T(), "john", "password", false, "")
|
|
|
|
// Visit home page to change context
|
|
s.doVisit(s.T(), HomeBaseURL)
|
|
s.verifyIsHome(ctx, s.T())
|
|
|
|
// Visit the login page and wait for redirection to 2FA page with success icon displayed
|
|
s.doVisit(s.T(), LoginBaseURL)
|
|
s.verifyIsSecondFactorPage(ctx, s.T())
|
|
|
|
// Check whether the success icon is displayed
|
|
s.WaitElementLocatedByClassName(ctx, s.T(), "success-icon")
|
|
}
|
|
|
|
func (s *StandaloneWebDriverSuite) TestShouldCheckUserIsAskedToRegisterDevice() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer cancel()
|
|
|
|
username := "john"
|
|
password := "password"
|
|
|
|
// Clean up any TOTP secret already in DB
|
|
provider := storage.NewSQLiteProvider("/tmp/db.sqlite3")
|
|
require.NoError(s.T(), provider.DeleteTOTPSecret(username))
|
|
|
|
// Login one factor
|
|
s.doLoginOneFactor(ctx, s.T(), username, password, false, "")
|
|
|
|
// Check the user is asked to register a new device
|
|
s.WaitElementLocatedByClassName(ctx, s.T(), "state-not-registered")
|
|
|
|
// Then register the TOTP factor
|
|
s.doRegisterTOTP(ctx, s.T())
|
|
// And logout
|
|
s.doLogout(ctx, s.T())
|
|
|
|
// Login one factor again
|
|
s.doLoginOneFactor(ctx, s.T(), username, password, false, "")
|
|
|
|
// now the user should be asked to perform 2FA
|
|
s.WaitElementLocatedByClassName(ctx, s.T(), "state-method")
|
|
}
|
|
|
|
type StandaloneSuite struct {
|
|
suite.Suite
|
|
}
|
|
|
|
func NewStandaloneSuite() *StandaloneSuite {
|
|
return &StandaloneSuite{}
|
|
}
|
|
|
|
// Standard case using nginx
|
|
func (s *StandaloneSuite) TestShouldVerifyAPIVerifyUnauthorize() {
|
|
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/verify", AutheliaBaseURL), nil)
|
|
s.Assert().NoError(err)
|
|
req.Header.Set("X-Forwarded-Proto", "https")
|
|
req.Header.Set("X-Original-URL", AdminBaseURL)
|
|
|
|
client := NewHTTPClient()
|
|
res, err := client.Do(req)
|
|
s.Assert().NoError(err)
|
|
s.Assert().Equal(res.StatusCode, 401)
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
s.Assert().NoError(err)
|
|
s.Assert().Equal(string(body), "Unauthorized")
|
|
}
|
|
|
|
// Standard case using Kubernetes
|
|
func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalURL() {
|
|
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/verify?rd=%s", AutheliaBaseURL, LoginBaseURL), nil)
|
|
s.Assert().NoError(err)
|
|
req.Header.Set("X-Forwarded-Proto", "https")
|
|
req.Header.Set("X-Original-URL", AdminBaseURL)
|
|
|
|
client := NewHTTPClient()
|
|
res, err := client.Do(req)
|
|
s.Assert().NoError(err)
|
|
s.Assert().Equal(res.StatusCode, 302)
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
s.Assert().NoError(err)
|
|
s.Assert().Equal(string(body), fmt.Sprintf("Found. Redirecting to %s?rd=%s", LoginBaseURL, AdminBaseURL))
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestShouldVerifyAPIVerifyRedirectFromXOriginalHostURI() {
|
|
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/verify?rd=%s", AutheliaBaseURL, LoginBaseURL), nil)
|
|
s.Assert().NoError(err)
|
|
req.Header.Set("X-Forwarded-Proto", "https")
|
|
req.Header.Set("X-Forwarded-Host", "secure.example.com:8080")
|
|
req.Header.Set("X-Forwarded-URI", "/")
|
|
|
|
client := NewHTTPClient()
|
|
res, err := client.Do(req)
|
|
s.Assert().NoError(err)
|
|
s.Assert().Equal(res.StatusCode, 302)
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
s.Assert().NoError(err)
|
|
s.Assert().Equal(string(body), fmt.Sprintf("Found. Redirecting to %s?rd=https://secure.example.com:8080/", LoginBaseURL))
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestStandaloneWebDriverScenario() {
|
|
suite.Run(s.T(), NewStandaloneWebDriverSuite())
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestOneFactorScenario() {
|
|
suite.Run(s.T(), NewOneFactorScenario())
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestTwoFactorScenario() {
|
|
suite.Run(s.T(), NewTwoFactorScenario())
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestBypassPolicyScenario() {
|
|
suite.Run(s.T(), NewBypassPolicyScenario())
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestBackendProtectionScenario() {
|
|
suite.Run(s.T(), NewBackendProtectionScenario())
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestResetPasswordScenario() {
|
|
suite.Run(s.T(), NewResetPasswordScenario())
|
|
}
|
|
|
|
func (s *StandaloneSuite) TestAvailableMethodsScenario() {
|
|
suite.Run(s.T(), NewAvailableMethodsScenario([]string{"ONE-TIME PASSWORD"}))
|
|
}
|
|
|
|
func TestStandaloneSuite(t *testing.T) {
|
|
suite.Run(t, NewStandaloneSuite())
|
|
}
|