diff --git a/.travis.yml b/.travis.yml index 1ad015b2f..5dd33a9af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,22 +14,18 @@ addons: packages: - libgif-dev - google-chrome-stable + before_script: - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash -- nvm install v9 && nvm use v9 && npm i +- nvm install v11 && nvm use v11 && npm i script: -- "./scripts/authelia-scripts travis" +- "source bootstrap.sh" +- "authelia-scripts ci" after_success: -- "./scripts/authelia-scripts docker publish" -deploy: - provider: npm - email: clement.michaud34@gmail.com - skip_cleanup: true - api_key: - secure: HpaWykYM6zaTXrDRGvyRvsIhn1BLT5gxdU1VXB6PMlr+FpTUoOXsYqLf+S1ipmR8rfjCGXIM1dRPfp/UmEgeWBSJ8PDjipcjYLEWkJSsW8IAO6GVR+pNPO6TgBQmR5RljZRwBd/uIh43nW9tG1YeoERVxdF4OvqwIeu0+jFrVnMdQngfAhXOiEMDSwH328q8QZIkQUmEhWn+IksHG34rLyo29hQQtJ1OnPkJwB9ZSJ71EEp0VH5UtJBCy5eDxKo9NQgvZpf+t6b2jfmHzp1uHlc8h7frpsCIJ0mborzWgc7P0VT/eaNbiFEC0oYkm+0lYVa0kgwbpxB02b/N/VGNXp8Tg8cWQmDly9NomR2BXeCgoQr4hvwpbXNw/I1FunVHVM66o0lMJmFJllFhqSWYLtqHrJb1qNIIFJGCqkTb6pnj35pTC50HjITAK9hQqvhwQ8v142qEpxu9rIvQ+ao90sY9IPxTedhGRs6gjF32JEeXjzysysecZ16jnae4bxmGVT21VF4zcDabCz6IMPje/aGg4flGxGJ5rwYb9p9vWXcgO2FXQzmNg3USTqCQWL+4oN0aiv9IknStkZ9bHLSK+tQ/SGjSlIpn5ou2CfQgkBSkj1vmmG+M+eJN0x/BzRYwURrQRm2t4BBPpcj+PkLVDoNuw6I8ETfsLf9b/B1mi2E= - on: - tags: true - repo: clems4ever/authelia +- "authelia-scripts docker publish" + +# TODO(c.michaud): publish built artifact on Github. + notifications: email: recipients: diff --git a/authentication/password_hash.go b/authentication/password_hash.go index c4195d002..42203809d 100644 --- a/authentication/password_hash.go +++ b/authentication/password_hash.go @@ -82,7 +82,7 @@ func RandomString(n int) string { func HashPassword(password string, salt *string) string { var generatedSalt string if salt == nil { - generatedSalt = fmt.Sprintf("$6$rounds=5000$%s$", RandomString(16)) + generatedSalt = fmt.Sprintf("$6$rounds=50000$%s$", RandomString(16)) } else { generatedSalt = *salt } diff --git a/bootstrap.sh b/bootstrap.sh index f2618701d..48eff9f60 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,33 +1,19 @@ -export PATH=$(pwd)/scripts:/tmp:$PATH +set -e -export PS1="(authelia) $PS1" +export PATH=./cmd/authelia-scripts/:/tmp:$PATH -npm i +if [ -z "$OLD_PS1" ]; then + OLD_PS1="$PS1" + export PS1="(authelia) $PS1" +fi -pushd client -npm i -popd -echo "[BOOTSTRAP] Checking if Docker is installed..." -if [ ! -x "$(command -v docker)" ]; +echo "[BOOTSTRAP] Checking if Go is installed..." +if [ ! -x "$(command -v go)" ]; then - echo "[ERROR] You must install docker on your machine."; + echo "[ERROR] You must install Go on your machine."; return fi -echo "[BOOTSTRAP] Checking if docker-compose is installed..." -if [ ! -x "$(command -v docker-compose)" ]; -then - echo "[ERROR] You must install docker-compose on your machine."; - return; -fi - -echo "[BOOTSTRAP] Running additional bootstrap steps..." authelia-scripts bootstrap - -# Create temporary directory that will contain the databases used in tests. -mkdir -p /tmp/authelia - -echo "[BOOTSTRAP] Run 'authelia-scripts suites start dockerhub' to start Authelia and visit https://home.example.com:8080." -echo "[BOOTSTRAP] More details at https://github.com/clems4ever/authelia/blob/master/docs/getting-started.md" diff --git a/cmd/authelia-scripts/authelia-scripts b/cmd/authelia-scripts/authelia-scripts new file mode 100755 index 000000000..d9f522641 --- /dev/null +++ b/cmd/authelia-scripts/authelia-scripts @@ -0,0 +1,3 @@ +#!/bin/bash + +go run cmd/authelia-scripts/*.go $* \ No newline at end of file diff --git a/cmd/authelia-scripts/cmd_bootstrap.go b/cmd/authelia-scripts/cmd_bootstrap.go new file mode 100644 index 000000000..a76d007a8 --- /dev/null +++ b/cmd/authelia-scripts/cmd_bootstrap.go @@ -0,0 +1,225 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "strings" + + "github.com/spf13/cobra" +) + +// HostEntry represents an entry in /etc/hosts +type HostEntry struct { + Domain string + IP string +} + +var hostEntries = []HostEntry{ + // For common tests + HostEntry{Domain: "login.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "admin.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "singlefactor.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "dev.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "home.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "mx1.mail.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "mx2.mail.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "public.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "secure.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "mail.example.com", IP: "192.168.240.100"}, + HostEntry{Domain: "duo.example.com", IP: "192.168.240.100"}, + + // For Traefik suite + HostEntry{Domain: "traefik.example.com", IP: "192.168.240.100"}, + + // For testing network ACLs + HostEntry{Domain: "proxy-client1.example.com", IP: "192.168.240.201"}, + HostEntry{Domain: "proxy-client2.example.com", IP: "192.168.240.202"}, + HostEntry{Domain: "proxy-client3.example.com", IP: "192.168.240.203"}, +} + +func runCommand(cmd string, args ...string) { + command := CommandWithStdout(cmd, args...) + err := command.Run() + + if err != nil { + panic(err) + } +} + +func installNpmPackages() { + runCommand("npm", "ci") +} + +func checkCommandExist(cmd string) { + fmt.Print("Checking if '" + cmd + "' command is installed...") + command := exec.Command("bash", "-c", "command -v "+cmd) + err := command.Run() + + if err != nil { + log.Fatal("[ERROR] You must install " + cmd + " on your machine.") + } + + fmt.Println(" OK") +} + +func installClientNpmPackages() { + command := CommandWithStdout("npm", "ci") + command.Dir = "client" + err := command.Run() + + if err != nil { + panic(err) + } +} + +func createTemporaryDirectory() { + err := os.MkdirAll("/tmp/authelia", 0755) + + if err != nil { + panic(err) + } +} + +func bootstrapPrintln(args ...interface{}) { + a := make([]interface{}, 0) + a = append(a, "[BOOTSTRAP]") + a = append(a, args...) + fmt.Println(a...) +} + +func shell(cmd string) { + runCommand("bash", "-c", cmd) +} + +func buildDockerImages() { + shell("docker build -t authelia-example-backend example/compose/nginx/backend") + shell("docker build -t authelia-duo-api example/compose/duo-api") +} + +func installKubernetesDependencies() { + if exist, err := FileExists("/tmp/kind"); err == nil && !exist { + shell("wget -nv https://github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-linux-amd64 -O /tmp/kind && chmod +x /tmp/kind") + } else { + bootstrapPrintln("Skip installing Kind since it's already installed") + } + + if exist, err := FileExists("/tmp/kubectl"); err == nil && !exist { + shell("wget -nv https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl -O /tmp/kubectl && chmod +x /tmp/kubectl") + } else { + bootstrapPrintln("Skip installing Kubectl since it's already installed") + } +} + +func prepareHostsFile() { + contentBytes, err := readHostsFile() + + if err != nil { + panic(err) + } + + lines := strings.Split(string(contentBytes), "\n") + toBeAddedLine := make([]string, 0) + modified := false + + for _, entry := range hostEntries { + domainInHostFile := false + for i, line := range lines { + domainFound := strings.Contains(line, entry.Domain) + ipFound := strings.Contains(line, entry.IP) + + if domainFound { + domainInHostFile = true + + // The IP is not up to date. + if ipFound { + break + } else { + lines[i] = entry.IP + " " + entry.Domain + modified = true + break + } + } + } + + if !domainInHostFile { + toBeAddedLine = append(toBeAddedLine, entry.IP+" "+entry.Domain) + } + } + + if len(toBeAddedLine) > 0 { + lines = append(lines, toBeAddedLine...) + modified = true + } + + err = ioutil.WriteFile("/tmp/authelia/hosts", []byte(strings.Join(lines, "\n")), 0644) + + if err != nil { + panic(err) + } + + if modified { + bootstrapPrintln("/etc/hosts needs to be updated") + shell("/usr/bin/sudo mv /tmp/authelia/hosts /etc/hosts") + } +} + +// ReadHostsFile reads the hosts file. +func readHostsFile() ([]byte, error) { + bs, err := ioutil.ReadFile("/etc/hosts") + if err != nil { + return nil, err + } + return bs, nil +} + +func readVersion(cmd string, args ...string) { + command := exec.Command(cmd, args...) + b, err := command.Output() + + if err != nil { + panic(err) + } + + fmt.Print(cmd + " => " + string(b)) +} + +func readVersions() { + readVersion("go", "version") + readVersion("node", "--version") + readVersion("docker", "--version") + readVersion("docker-compose", "--version") +} + +// Bootstrap bootstrap authelia dev environment +func Bootstrap(cobraCmd *cobra.Command, args []string) { + bootstrapPrintln("Checking command installation...") + checkCommandExist("node") + checkCommandExist("docker") + checkCommandExist("docker-compose") + + bootstrapPrintln("Getting versions of tools") + readVersions() + + bootstrapPrintln("Installing NPM packages for development...") + installNpmPackages() + + bootstrapPrintln("Install NPM packages for frontend...") + installClientNpmPackages() + + bootstrapPrintln("Building development Docker images...") + buildDockerImages() + + bootstrapPrintln("Installing Kubernetes dependencies for testing in /tmp... (no junk installed on host)") + installKubernetesDependencies() + + createTemporaryDirectory() + + bootstrapPrintln("Preparing /etc/hosts to serve subdomains of example.com...") + prepareHostsFile() + + bootstrapPrintln("Run 'authelia-scripts suites start basic' to start Authelia and visit https://home.example.com:8080.") + bootstrapPrintln("More details at https://github.com/clems4ever/authelia/blob/master/docs/getting-started.md") +} diff --git a/cmd/authelia-scripts/cmd_build.go b/cmd/authelia-scripts/cmd_build.go new file mode 100644 index 000000000..3a02b4876 --- /dev/null +++ b/cmd/authelia-scripts/cmd_build.go @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +func buildAutheliaBinary() { + cmd := CommandWithStdout("go", "build", "-o", OutputDir+"/authelia") + cmd.Env = append(os.Environ(), + "GOOS=linux", "GOARCH=amd64", "CGO_ENABLED=1") + + err := cmd.Run() + + if err != nil { + panic(err) + } +} + +func buildFrontend() { + cmd := CommandWithStdout("npm", "run", "build") + cmd.Dir = "client" + err := cmd.Run() + + if err != nil { + panic(err) + } + + err = os.Rename("client/build", OutputDir+"/public_html") + + if err != nil { + panic(err) + } +} + +// Build build Authelia +func Build(cobraCmd *cobra.Command, args []string) { + Clean(cobraCmd, args) + + fmt.Println("Creating `" + OutputDir + "` directory") + err := os.MkdirAll(OutputDir, os.ModePerm) + + if err != nil { + panic(err) + } + + fmt.Println("Building Authelia Go binary...") + buildAutheliaBinary() + + fmt.Println("Building Authelia frontend...") + buildFrontend() +} diff --git a/cmd/authelia-scripts/cmd_ci.go b/cmd/authelia-scripts/cmd_ci.go new file mode 100644 index 000000000..a5bbbc9ce --- /dev/null +++ b/cmd/authelia-scripts/cmd_ci.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +const dockerPullCommandLine = "docker-compose -f docker-compose.yml " + + "-f example/compose/mongo/docker-compose.yml " + + "-f example/compose/redis/docker-compose.yml " + + "-f example/compose/nginx/portal/docker-compose.yml " + + "-f example/compose/smtp/docker-compose.yml " + + "-f example/compose/httpbin/docker-compose.yml " + + "-f example/compose/ldap/docker-compose.admin.yml " + + "-f example/compose/ldap/docker-compose.yml " + + "pull" + +// RunCI run the CI scripts +func RunCI(cmd *cobra.Command, args []string) { + command := CommandWithStdout("bash", "-c", dockerPullCommandLine) + err := command.Run() + + if err != nil { + panic(err) + } + + fmt.Println("===== Build stage =====") + command = CommandWithStdout("authelia-scripts", "build") + err = command.Run() + + if err != nil { + panic(err) + } + + fmt.Println("===== Unit testing stage =====") + command = CommandWithStdout("authelia-scripts", "unittest") + err = command.Run() + + if err != nil { + panic(err) + } + + fmt.Println("===== Docker image build stage =====") + command = CommandWithStdout("authelia-scripts", "docker", "build") + err = command.Run() + + if err != nil { + panic(err) + } + + fmt.Println("===== End-to-end testing stage =====") + command = CommandWithStdout("authelia-scripts", "suites", "test", "--headless", "--only-forbidden") + err = command.Run() + + if err != nil { + panic(err) + } +} diff --git a/cmd/authelia-scripts/cmd_clean.go b/cmd/authelia-scripts/cmd_clean.go new file mode 100644 index 000000000..612652ad3 --- /dev/null +++ b/cmd/authelia-scripts/cmd_clean.go @@ -0,0 +1,18 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +// Clean artifacts built and installed by authelia-scripts +func Clean(cobraCmd *cobra.Command, args []string) { + fmt.Println("Removing `" + OutputDir + "` directory") + err := os.RemoveAll(OutputDir) + + if err != nil { + panic(err) + } +} diff --git a/cmd/authelia-scripts/cmd_docker.go b/cmd/authelia-scripts/cmd_docker.go new file mode 100644 index 000000000..7e375089a --- /dev/null +++ b/cmd/authelia-scripts/cmd_docker.go @@ -0,0 +1,96 @@ +package main + +import ( + "errors" + "fmt" + "os" + + "github.com/spf13/cobra" +) + +// DockerBuildCmd Command for building docker image of Authelia. +var DockerBuildCmd = &cobra.Command{ + Use: "build", + Short: "Build the docker image of Authelia", + Run: func(cmd *cobra.Command, args []string) { + docker := &Docker{} + err := docker.Build(IntermediateDockerImageName, ".") + if err != nil { + panic(err) + } + + err = docker.Tag(IntermediateDockerImageName, DockerImageName) + + if err != nil { + panic(err) + } + }, +} + +// DockerPushCmd Command for pushing Authelia docker image to Dockerhub +var DockerPushCmd = &cobra.Command{ + Use: "publish", + Short: "Publish Authelia docker image to Dockerhub", + Run: func(cmd *cobra.Command, args []string) { + publishDockerImage() + }, +} + +func login(docker *Docker) { + username := os.Getenv("DOCKER_USERNAME") + password := os.Getenv("DOCKER_PASSWORD") + + if username == "" { + panic(errors.New("DOCKER_USERNAME is empty")) + } + + if password == "" { + panic(errors.New("DOCKER_PASSWORD is empty")) + } + + fmt.Println("Login to dockerhub as " + username) + err := docker.Login(username, password) + + if err != nil { + fmt.Println("Login to dockerhub failed") + panic(err) + } +} + +func deploy(docker *Docker, tag string) { + imageWithTag := DockerImageName + ":" + tag + fmt.Println("===================================================") + fmt.Println("Docker image " + imageWithTag + " will be deployed on Dockerhub.") + fmt.Println("===================================================") + + err := docker.Tag(DockerImageName, imageWithTag) + + if err != nil { + panic(err) + } + + docker.Push(imageWithTag) + + if err != nil { + panic(err) + } +} + +func publishDockerImage() { + docker := &Docker{} + + travisBranch := os.Getenv("TRAVIS_BRANCH") + travisPullRequest := os.Getenv("TRAVIS_PULL_REQUEST") + travisTag := os.Getenv("TRAVIS_TAG") + + if travisBranch == "master" && travisPullRequest == "false" { + login(docker) + deploy(docker, "master") + } else if travisTag != "" { + login(docker) + deploy(docker, travisTag) + deploy(docker, "latest") + } else { + fmt.Println("Docker image will not be built") + } +} diff --git a/cmd/authelia-scripts/cmd_hash_password.go b/cmd/authelia-scripts/cmd_hash_password.go new file mode 100644 index 000000000..b98cf21ad --- /dev/null +++ b/cmd/authelia-scripts/cmd_hash_password.go @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" + + "github.com/clems4ever/authelia/authentication" + "github.com/spf13/cobra" +) + +// HashPassword hash the provided password with crypt sha256 hash function +func HashPassword(cobraCmd *cobra.Command, args []string) { + fmt.Println(authentication.HashPassword(args[0], nil)) +} diff --git a/cmd/authelia-scripts/cmd_serve.go b/cmd/authelia-scripts/cmd_serve.go new file mode 100644 index 000000000..073adf5ed --- /dev/null +++ b/cmd/authelia-scripts/cmd_serve.go @@ -0,0 +1,14 @@ +package main + +import ( + "os" + + "github.com/spf13/cobra" +) + +// ServeCmd serve authelia with the provided configuration +func ServeCmd(cobraCmd *cobra.Command, args []string) { + cmd := CommandWithStdout(OutputDir+"/authelia", "-config", args[0]) + cmd.Env = append(os.Environ(), "PUBLIC_DIR=dist/public_html") + RunCommandUntilCtrlC(cmd) +} diff --git a/cmd/authelia-scripts/cmd_suites.go b/cmd/authelia-scripts/cmd_suites.go new file mode 100644 index 000000000..8d42d1a58 --- /dev/null +++ b/cmd/authelia-scripts/cmd_suites.go @@ -0,0 +1,234 @@ +package main + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "os/exec" + "os/signal" + "strings" + "syscall" + + "github.com/spf13/cobra" +) + +func listDirectories(path string) ([]string, error) { + files, err := ioutil.ReadDir(path) + if err != nil { + return nil, err + } + + dirs := make([]string, 0) + + for _, f := range files { + if f.IsDir() { + dirs = append(dirs, f.Name()) + } + } + + return dirs, nil +} + +func listSuites() ([]string, error) { + return listDirectories("./test/suites/") +} + +func suiteAvailable(suite string, suites []string) (bool, error) { + suites, err := listSuites() + + if err != nil { + return false, err + } + + for _, s := range suites { + if s == suite { + return true, nil + } + } + return false, nil +} + +// SuitesListCmd Command for listing the available suites +var SuitesListCmd = &cobra.Command{ + Use: "list", + Short: "List available suites.", + Run: func(cmd *cobra.Command, args []string) { + suites, err := listSuites() + + if err != nil { + panic(err) + } + + fmt.Println(strings.Join(suites, "\n")) + }, + Args: cobra.ExactArgs(0), +} + +// SuitesCleanCmd Command for cleaning suite environments +var SuitesCleanCmd = &cobra.Command{ + Use: "clean", + Short: "Clean suite environments.", + Run: func(cmd *cobra.Command, args []string) { + command := CommandWithStdout("bash", "-c", + "./node_modules/.bin/ts-node -P test/tsconfig.json -- ./scripts/clean-environment.ts") + err := command.Run() + + if err != nil { + panic(err) + } + }, + Args: cobra.ExactArgs(0), +} + +// SuitesStartCmd Command for starting a suite +var SuitesStartCmd = &cobra.Command{ + Use: "start [suite]", + Short: "Start a suite. Suites can be listed using the list command.", + Run: func(cmd *cobra.Command, args []string) { + suites, err := listSuites() + + if err != nil { + panic(err) + } + + selectedSuite := args[0] + + available, err := suiteAvailable(selectedSuite, suites) + + if err != nil { + panic(err) + } + + if !available { + panic(errors.New("Suite named " + selectedSuite + " does not exist")) + } + + err = ioutil.WriteFile(RunningSuiteFile, []byte(selectedSuite), 0644) + + if err != nil { + panic(err) + } + + signalChannel := make(chan os.Signal) + signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM) + + cmdline := "./node_modules/.bin/ts-node -P test/tsconfig.json -- ./scripts/run-environment.ts " + selectedSuite + command := CommandWithStdout("bash", "-c", cmdline) + command.Env = append(os.Environ(), "ENVIRONMENT=dev") + + err = command.Run() + + if err != nil { + panic(err) + } + + err = os.Remove(RunningSuiteFile) + + if err != nil { + panic(err) + } + }, + Args: cobra.ExactArgs(1), +} + +// SuitesTestCmd Command for testing a suite +var SuitesTestCmd = &cobra.Command{ + Use: "test [suite]", + Short: "Test a suite. Suites can be listed using the list command.", + Run: func(cmd *cobra.Command, args []string) { + runningSuite, err := getRunningSuite() + if err != nil { + panic(err) + } + + if len(args) == 1 { + suite := args[0] + + if runningSuite != "" && suite != runningSuite { + panic(errors.New("Running suite (" + runningSuite + ") is different than suite to be tested (" + suite + "). Shutdown running suite and retry")) + } + + runSuiteTests(suite, runningSuite == "") + } else { + if runningSuite != "" { + panic(errors.New("Cannot run all tests while a suite is currently running. Shutdown running suite and retry")) + } + fmt.Println("No suite provided therefore all suites will be tested") + runAllSuites() + } + }, + Args: cobra.MaximumNArgs(1), +} + +func getRunningSuite() (string, error) { + exist, err := FileExists(RunningSuiteFile) + + if err != nil { + return "", err + } + + if !exist { + return "", nil + } + + b, err := ioutil.ReadFile(RunningSuiteFile) + return string(b), err +} + +func runSuiteTests(suite string, withEnv bool) { + mochaArgs := []string{"--exit", "--colors", "--require", "ts-node/register", "test/suites/" + suite + "/test.ts"} + if onlyForbidden { + mochaArgs = append(mochaArgs, "--forbid-only", "--forbid-pending") + } + mochaCmdLine := "./node_modules/.bin/mocha " + strings.Join(mochaArgs, " ") + + fmt.Println(mochaCmdLine) + + headlessValue := "n" + if headless { + headlessValue = "y" + } + + var cmd *exec.Cmd + + if withEnv { + fmt.Println("No running suite detected, setting up an environment for running the tests") + cmd = CommandWithStdout("bash", "-c", + "./node_modules/.bin/ts-node ./scripts/run-environment.ts "+suite+" '"+mochaCmdLine+"'") + } else { + fmt.Println("Running suite detected. Running tests...") + cmd = CommandWithStdout("bash", "-c", mochaCmdLine) + } + + cmd.Env = append(os.Environ(), + "TS_NODE_PROJECT=test/tsconfig.json", + "HEADLESS="+headlessValue, + "ENVIRONMENT=dev") + + err := cmd.Run() + + if err != nil { + os.Exit(1) + } +} + +func runAllSuites() { + suites, err := listSuites() + + if err != nil { + panic(err) + } + + for _, s := range suites { + runSuiteTests(s, true) + } +} + +var headless bool +var onlyForbidden bool + +func init() { + SuitesTestCmd.Flags().BoolVar(&headless, "headless", false, "Run tests in headless mode") + SuitesTestCmd.Flags().BoolVar(&onlyForbidden, "only-forbidden", false, "Mocha 'only' filters are forbidden") +} diff --git a/cmd/authelia-scripts/cmd_unittest.go b/cmd/authelia-scripts/cmd_unittest.go new file mode 100644 index 000000000..13cd4e854 --- /dev/null +++ b/cmd/authelia-scripts/cmd_unittest.go @@ -0,0 +1,11 @@ +package main + +import "github.com/spf13/cobra" + +// RunUnitTest run the unit tests +func RunUnitTest(cobraCmd *cobra.Command, args []string) { + err := CommandWithStdout("go", "test", "./...").Run() + if err != nil { + panic(err) + } +} diff --git a/cmd/authelia-scripts/constants.go b/cmd/authelia-scripts/constants.go new file mode 100644 index 000000000..185c5b1eb --- /dev/null +++ b/cmd/authelia-scripts/constants.go @@ -0,0 +1,13 @@ +package main + +// OutputDir the output directory where the built version of Authelia is located +var OutputDir = "dist" + +// DockerImageName the official name of authelia docker image +var DockerImageName = "clems4ever/authelia" + +// IntermediateDockerImageName local name of the docker image +var IntermediateDockerImageName = "authelia:dist" + +// RunningSuiteFile name of the file containing the currently running suite +var RunningSuiteFile = ".suite" diff --git a/cmd/authelia-scripts/docker.go b/cmd/authelia-scripts/docker.go new file mode 100644 index 000000000..b78616a96 --- /dev/null +++ b/cmd/authelia-scripts/docker.go @@ -0,0 +1,24 @@ +package main + +// Docker a docker object +type Docker struct{} + +// Build build a docker image +func (d *Docker) Build(tag string, target string) error { + return CommandWithStdout("docker", "build", "-t", tag, target).Run() +} + +// Tag tag a docker image. +func (d *Docker) Tag(image, tag string) error { + return CommandWithStdout("docker", "tag", image, tag).Run() +} + +// Login login to the dockerhub registry. +func (d *Docker) Login(username, password string) error { + return CommandWithStdout("docker", "login", "-u", username, "-p", password).Run() +} + +// Push push a docker image to dockerhub. +func (d *Docker) Push(tag string) error { + return CommandWithStdout("docker", "push", tag).Run() +} diff --git a/cmd/authelia-scripts/exec.go b/cmd/authelia-scripts/exec.go new file mode 100644 index 000000000..718389d91 --- /dev/null +++ b/cmd/authelia-scripts/exec.go @@ -0,0 +1,52 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "os/signal" + "sync" + "syscall" +) + +// CommandWithStdout execute the command and forward stdout and stderr to the OS streams +func CommandWithStdout(name string, args ...string) *exec.Cmd { + cmd := exec.Command(name, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd +} + +// RunCommandUntilCtrlC run a command until ctrl-c is hit +func RunCommandUntilCtrlC(cmd *exec.Cmd) { + mutex := sync.Mutex{} + cond := sync.NewCond(&mutex) + signalChannel := make(chan os.Signal) + signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM) + + mutex.Lock() + + go func() { + mutex.Lock() + f := bufio.NewWriter(os.Stdout) + defer f.Flush() + + fmt.Println("Hit Ctrl+C to shutdown...") + + err := cmd.Run() + + if err != nil { + fmt.Println(err) + cond.Broadcast() + mutex.Unlock() + return + } + + <-signalChannel + cond.Broadcast() + mutex.Unlock() + }() + + cond.Wait() +} diff --git a/cmd/authelia-scripts/files.go b/cmd/authelia-scripts/files.go new file mode 100644 index 000000000..6406572e3 --- /dev/null +++ b/cmd/authelia-scripts/files.go @@ -0,0 +1,15 @@ +package main + +import "os" + +// FileExists returns whether the given file or directory exists +func FileExists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return true, err +} diff --git a/cmd/authelia-scripts/main.go b/cmd/authelia-scripts/main.go new file mode 100755 index 000000000..be50af62e --- /dev/null +++ b/cmd/authelia-scripts/main.go @@ -0,0 +1,121 @@ +//usr/bin/env go run "$0" "$@"; exit + +package main + +import ( + "github.com/spf13/cobra" +) + +// AutheliaCommandDefinition is the definition of one authelia-scripts command. +type AutheliaCommandDefinition struct { + Name string + Short string + Long string + CommandLine string + Args cobra.PositionalArgs + Func func(cmd *cobra.Command, args []string) + SubCommands []*cobra.Command +} + +// CobraCommands list of cobra commands +type CobraCommands = []*cobra.Command + +// Commands is the list of commands of authelia-scripts +var Commands = []AutheliaCommandDefinition{ + AutheliaCommandDefinition{ + Name: "bootstrap", + Short: "Prepare environment for development and testing.", + Long: `Prepare environment for development and testing. This command prepares docker + images and download tools like Kind for Kubernetes testing.`, + Func: Bootstrap, + }, + AutheliaCommandDefinition{ + Name: "build", + Short: "Build Authelia binary and static assets", + Func: Build, + }, + AutheliaCommandDefinition{ + Name: "clean", + Short: "Clean build artifacts", + Func: Clean, + }, + AutheliaCommandDefinition{ + Name: "docker", + Short: "Commands related to building and publishing docker image", + SubCommands: CobraCommands{DockerBuildCmd, DockerPushCmd}, + }, + AutheliaCommandDefinition{ + Name: "hash-password [password]", + Short: "Compute hash of a password for creating a file-based users database", + Func: HashPassword, + Args: cobra.MinimumNArgs(1), + }, + AutheliaCommandDefinition{ + Name: "serve [config]", + Short: "Serve compiled version of Authelia", + Func: ServeCmd, + Args: cobra.MinimumNArgs(1), + }, + AutheliaCommandDefinition{ + Name: "suites", + Short: "Compute hash of a password for creating a file-based users database", + SubCommands: CobraCommands{SuitesCleanCmd, SuitesListCmd, SuitesStartCmd, SuitesTestCmd}, + }, + AutheliaCommandDefinition{ + Name: "ci", + Short: "Run continuous integration script", + Func: RunCI, + }, + AutheliaCommandDefinition{ + Name: "unittest", + Short: "Run unit tests", + Func: RunUnitTest, + }, +} + +func main() { + var rootCmd = &cobra.Command{Use: "authelia-scripts"} + cobraCommands := make([]*cobra.Command, 0) + + for _, autheliaCommand := range Commands { + var fn func(cobraCmd *cobra.Command, args []string) + + if autheliaCommand.CommandLine != "" { + cmdline := autheliaCommand.CommandLine + fn = func(cobraCmd *cobra.Command, args []string) { + cmd := CommandWithStdout(cmdline, args...) + err := cmd.Run() + if err != nil { + panic(err) + } + } + } else if autheliaCommand.Func != nil { + fn = autheliaCommand.Func + } + + command := &cobra.Command{ + Use: autheliaCommand.Name, + Short: autheliaCommand.Short, + } + + if autheliaCommand.Long != "" { + command.Long = autheliaCommand.Long + } + + if fn != nil { + command.Run = fn + } + + if autheliaCommand.Args != nil { + command.Args = autheliaCommand.Args + } + + if autheliaCommand.SubCommands != nil { + command.AddCommand(autheliaCommand.SubCommands...) + } + + cobraCommands = append(cobraCommands, command) + } + rootCmd.AddCommand(cobraCommands...) + rootCmd.Execute() +} diff --git a/configuration/validator/authentication.go b/configuration/validator/authentication.go index c81f328bd..94c255a2f 100644 --- a/configuration/validator/authentication.go +++ b/configuration/validator/authentication.go @@ -2,7 +2,6 @@ package validator import ( "errors" - "fmt" "strings" "github.com/clems4ever/authelia/configuration/schema" @@ -37,7 +36,6 @@ func validateLdapAuthenticationBackend(configuration *schema.LDAPAuthenticationB } else { configuration.URL = validateLdapURL(configuration.URL, validator) } - fmt.Println(configuration.URL) if configuration.User == "" { validator.Push(errors.New("Please provide a user name to connect to the LDAP server")) diff --git a/go.mod b/go.mod index d73da6168..4ea6adec5 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/mattn/go-sqlite3 v1.11.0 github.com/pquerna/otp v1.2.0 github.com/sirupsen/logrus v1.4.2 + github.com/spf13/cobra v0.0.5 github.com/stretchr/testify v1.4.0 github.com/tstranex/u2f v1.0.0 github.com/valyala/fasthttp v1.6.0 diff --git a/go.sum b/go.sum index e8d0f3316..bd9160dc5 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,16 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Workiva/go-datastructures v1.0.50 h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -16,6 +22,7 @@ github.com/fasthttp/router v0.5.2 h1:xdmx8uYc9IFDtlbG2/FhE1Gyowv7/sqMgMonRjoW0Yo github.com/fasthttp/router v0.5.2/go.mod h1:Y5JAeRTSPwSLoUgH4x75UnT1j1IcAgVshMDMMrnNmKQ= github.com/fasthttp/session v1.1.3 h1:2qjxNltI7iv0yh7frsIdhbsGmSoRnTajU8xtpC6Hd80= github.com/fasthttp/session v1.1.3/go.mod h1:DRxVb1PWFtAUTE4U+GgggsVkUaQyacoL8TN+3o4/yLw= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4= github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -25,6 +32,8 @@ github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= @@ -32,21 +41,34 @@ github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/savsgio/dictpool v0.0.0-20191028211042-a886cee3358a h1:HHo8bk/5tOTL+UJ2VBkzGWhurfjyrLMRnvdRBnXYlfs= github.com/savsgio/dictpool v0.0.0-20191028211042-a886cee3358a/go.mod h1:hnGRFeigcU3gTEMTWW8OjfoSYztn2GPcriOY9iIzCrA= github.com/savsgio/gotils v0.0.0-20190925070755-524bc4f47500 h1:9Pi10H7E8E79/x2HSe1FmMGd7BJ1WAqDKzwjpv+ojFg= github.com/savsgio/gotils v0.0.0-20190925070755-524bc4f47500/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -57,6 +79,7 @@ github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ= github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0 h1:uWF8lgKmeaIewWVPwi4GRq2P6+R46IgYZdxWtM+GtEY= @@ -66,14 +89,17 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/package.json b/package.json index 93df104fd..0c318b070 100644 --- a/package.json +++ b/package.json @@ -42,28 +42,21 @@ "@types/request": "^2.0.5", "@types/request-promise": "^4.1.38", "@types/selenium-webdriver": "^3.0.16", - "@types/sinon": "^4.3.0", "@types/speakeasy": "^2.0.2", - "@types/tmp": "0.0.33", "chokidar": "^2.0.4", "chromedriver": "^77.0.0", "commander": "^2.19.0", - "istanbul": "^0.4.5", "ejs": "^2.6.2", "mocha": "^6.1.4", "mockdate": "^2.0.1", "node-fetch": "^2.3.0", - "nodemon": "^1.18.9", "query-string": "^6.0.0", "readable-stream": "^2.3.3", "redis": "^2.8.0", "request": "^2.88.0", "request-promise": "^4.2.2", "selenium-webdriver": "^4.0.0-alpha.4", - "should": "^13.2.1", - "sinon": "^5.0.7", "speakeasy": "^2.0.0", - "tmp": "0.0.33", "tree-kill": "^1.2.1", "ts-node": "^6.0.1", "tslint": "^5.2.0", diff --git a/scripts/authelia-scripts b/scripts/authelia-scripts deleted file mode 100755 index fa20ba4c5..000000000 --- a/scripts/authelia-scripts +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); - -program - .version('0.0.1') - - .command('bootstrap', 'Prepare some containers for development.') - .command('suites', 'Run Authelia in specific environments.') - .command('serve', 'Run Authelia with a customized configuration.') - .command('build', 'Build production version of Authelia from source.') - .command('clean', 'Clean the production version of Authelia.') - .command('unittest', 'Run Authelia integration tests.') - - .command('travis', 'Build and test Authelia on Travis.') - .command('hash-password ', 'Hash a password with SSHA512.') - .command('docker', 'Docker related commands.') - .parse(process.argv); \ No newline at end of file diff --git a/scripts/authelia-scripts-bootstrap b/scripts/authelia-scripts-bootstrap deleted file mode 100755 index 816b8872e..000000000 --- a/scripts/authelia-scripts-bootstrap +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env node - -var { exec } = require('./utils/exec'); -var fs = require('fs'); - -async function buildDockerImages() { - console.log("[BOOTSTRAP] Building required Docker images..."); - - console.log('Build authelia-example-backend docker image.') - await exec('docker build -t authelia-example-backend example/compose/nginx/backend'); - - console.log('Build authelia-duo-api docker image.') - await exec('docker build -t authelia-duo-api example/compose/duo-api'); -} - -async function checkHostsFile() { - async function checkAndFixEntry(entries, domain, ip) { - const foundEntry = entries.filter(l => l[1] == domain); - if (foundEntry.length > 0) { - if (foundEntry[0][0] == ip) { - // The entry exists and is correct. - return; - } - else { - // We need to remove the entry and replace it. - console.log(`Update entry for ${domain}.`); - await exec(`cat /etc/hosts | grep -v "${domain}" | /usr/bin/sudo tee /etc/hosts > /dev/null`); - await exec(`echo "${ip} ${domain}" | /usr/bin/sudo tee -a /etc/hosts > /dev/null`); - } - } - else { - // We need to add the new entry. - console.log(`Add entry for ${domain}.`); - await exec(`echo "${ip} ${domain}" | /usr/bin/sudo tee -a /etc/hosts > /dev/null`); - } - } - - console.log("[BOOTSTRAP] Checking if example.com domain is forwarded to your machine..."); - const actualEntries = fs.readFileSync("/etc/hosts").toString("utf-8") - .split("\n").filter(l => l !== '').map(l => l.split(" ").filter(w => w !== '')); - - await checkAndFixEntry(actualEntries, 'login.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'admin.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'singlefactor.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'dev.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'home.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'mx1.mail.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'mx2.mail.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'public.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'secure.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'mail.example.com', '192.168.240.100'); - await checkAndFixEntry(actualEntries, 'duo.example.com', '192.168.240.100'); - - // For Traefik suite. - await checkAndFixEntry(actualEntries, 'traefik.example.com', '192.168.240.100'); - - // For testing network ACLs. - await checkAndFixEntry(actualEntries, 'proxy-client1.example.com', '192.168.240.201'); - await checkAndFixEntry(actualEntries, 'proxy-client2.example.com', '192.168.240.202'); - await checkAndFixEntry(actualEntries, 'proxy-client3.example.com', '192.168.240.203'); -} - -async function checkKubernetesDependencies() { - console.log("[BOOTSTRAP] Checking Kubernetes tools in /tmp to allow testing a Kube cluster... (no junk installed on host)"); - - if (!fs.existsSync('/tmp/kind')) { - console.log('Install Kind for spawning a Kubernetes cluster.'); - await exec('wget -nv https://github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-linux-amd64 -O /tmp/kind && chmod +x /tmp/kind'); - } - - if (!fs.existsSync('/tmp/kubectl')) { - console.log('Install Kubectl for interacting with Kubernetes.'); - await exec('wget -nv https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl -O /tmp/kubectl && chmod +x /tmp/kubectl'); - } -} - -async function main() { - await checkHostsFile(); - await buildDockerImages(); - await checkKubernetesDependencies(); -} - -main().catch((err) => { - console.error(err); - process.exit(1); -}) diff --git a/scripts/authelia-scripts-build b/scripts/authelia-scripts-build deleted file mode 100755 index 987ab4057..000000000 --- a/scripts/authelia-scripts-build +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -set -x -set -e - -DIST_DIR=dist - -rm -rf $DIST_DIR -mkdir -p $DIST_DIR - -GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -o $DIST_DIR/authelia - -# Build the client -pushd client -npm run build -popd - -mv client/build $DIST_DIR/public_html - diff --git a/scripts/authelia-scripts-clean b/scripts/authelia-scripts-clean deleted file mode 100755 index ce010bffd..000000000 --- a/scripts/authelia-scripts-clean +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -rm -rf dist diff --git a/scripts/authelia-scripts-docker b/scripts/authelia-scripts-docker deleted file mode 100755 index e7d71573b..000000000 --- a/scripts/authelia-scripts-docker +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); - -program - .command('build', 'Build docker image clems4ever/authelia.') - .command('publish', 'Publish image clems4ever/authelia to Dockerhub.') - .parse(process.argv); diff --git a/scripts/authelia-scripts-docker-build b/scripts/authelia-scripts-docker-build deleted file mode 100755 index a351339b9..000000000 --- a/scripts/authelia-scripts-docker-build +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env node - -var { exec } = require('./utils/exec'); -var { IMAGE_NAME, DOCKERHUB_IMAGE_NAME } = require('./utils/docker'); - -async function main() { - await exec(`docker build -t ${IMAGE_NAME}:dist .`); - await exec(`docker tag ${IMAGE_NAME}:dist ${DOCKERHUB_IMAGE_NAME}`); -} - -main().catch((err) => { - console.error(err); - process.exit(1); -}) \ No newline at end of file diff --git a/scripts/authelia-scripts-docker-publish b/scripts/authelia-scripts-docker-publish deleted file mode 100755 index 174636c73..000000000 --- a/scripts/authelia-scripts-docker-publish +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# Parameters: -# TAG - The name of the tag to use for publishing in Dockerhub - -function login_to_dockerhub { - echo "Logging in to Dockerhub as $DOCKER_USERNAME." - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD - if [ "$?" -ne "0" ]; - then - echo "Logging in to Dockerhub failed."; - exit 1 - fi -} - -function deploy_on_dockerhub { - TAG=$1 - IMAGE_NAME=authelia:dist - DOCKERHUB_IMAGE_NAME=clems4ever/authelia - IMAGE_WITH_TAG=$DOCKERHUB_IMAGE_NAME:$TAG - - echo "===========================================================" - echo "Docker image $IMAGE_WITH_TAG will be deployed on Dockerhub." - echo "===========================================================" - docker tag $IMAGE_NAME $IMAGE_WITH_TAG; - docker push $IMAGE_WITH_TAG; - echo "Docker image deployed successfully." -} - - -if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then - echo "Building on master branch" - login_to_dockerhub - deploy_on_dockerhub master -elif [ ! -z "$TRAVIS_TAG" ]; then - login_to_dockerhub - deploy_on_dockerhub $TRAVIS_TAG - deploy_on_dockerhub latest -else - echo "Docker image will not be deployed on Dockerhub." -fi - diff --git a/scripts/authelia-scripts-hash-password b/scripts/authelia-scripts-hash-password deleted file mode 100755 index a8ac7a595..000000000 --- a/scripts/authelia-scripts-hash-password +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); -var RandomString = require("randomstring"); -var Util = require("util"); -var crypt = require("crypt3"); - -function ssha512(password, saltSize, rounds) { - // $6 means SHA512 - const _salt = Util.format("$6$rounds=%d$%s", rounds, - RandomString.generate(saltSize)); - - const hash = crypt(password, _salt); - return Util.format("{CRYPT}%s", hash); -} - -let password; - -program - .option('-s, --salt ', 'The size of the salt to generate.') - .option('-r, --rounds ', 'The number of rounds.') - .arguments('') - .action(function (_password) { - password = _password; - }) - .parse(process.argv); - -if (!password) { - program.help(); -} - -console.log(ssha512(password, program.salt || 16, program.rounds || 500000)); diff --git a/scripts/authelia-scripts-serve b/scripts/authelia-scripts-serve deleted file mode 100755 index 79c609f03..000000000 --- a/scripts/authelia-scripts-serve +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); -var spawn = require('child_process').spawn; - -let config; - -program - .description('Run Authelia server with a custom configuration file. This is an alternative to suites in the case the environment is already set up.') - .arguments('[config_file]', 'Configuration file to run Authelia with.') - .action((configArg) => config = configArg) - .parse(process.argv); - - -if (!config) { - config = 'config.yml'; // set default config file.; -} - -const server = spawn(__dirname + '/../dist/authelia', ['-config', config], { - env: { - ...process.env, - PUBLIC_DIR: __dirname + "/../dist/public_html" - } -}); - -server.stdout.pipe(process.stdout); -server.stderr.pipe(process.stderr); - -server.on('exit', function(statusCode) { - process.exit(statusCode); -}); \ No newline at end of file diff --git a/scripts/authelia-scripts-suites b/scripts/authelia-scripts-suites deleted file mode 100755 index 7d1c333fc..000000000 --- a/scripts/authelia-scripts-suites +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); - -program - .command('start', 'Start a suite.') - .command('list', 'List the available suites') - .command('test', 'Test a suite.') - .command('clean', 'Clean remaining environment artifacts (like docker-compose env).') - .parse(process.argv); diff --git a/scripts/authelia-scripts-suites-clean b/scripts/authelia-scripts-suites-clean deleted file mode 100755 index d6775472b..000000000 --- a/scripts/authelia-scripts-suites-clean +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); -var spawn = require('child_process').spawn; - -program - .description(`Clean environment artifacts from previous suites.`) - .parse(process.argv) - -runEnvProcess = spawn('./node_modules/.bin/ts-node -P test/tsconfig.json -- ./scripts/clean-environment.ts', { - shell: true -}); -runEnvProcess.stdout.pipe(process.stdout); -runEnvProcess.stderr.pipe(process.stderr); - -runEnvProcess.on('exit', function(statusCode) { - process.exit(statusCode); -}); \ No newline at end of file diff --git a/scripts/authelia-scripts-suites-list b/scripts/authelia-scripts-suites-list deleted file mode 100755 index 4891f6382..000000000 --- a/scripts/authelia-scripts-suites-list +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); -var ListSuites = require('./utils/ListSuites'); - -program - .description(`List the available suites.`) - .parse(process.argv) - -console.log(ListSuites().join("\n")); \ No newline at end of file diff --git a/scripts/authelia-scripts-suites-start b/scripts/authelia-scripts-suites-start deleted file mode 100755 index 7ba994da9..000000000 --- a/scripts/authelia-scripts-suites-start +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); -var spawn = require('child_process').spawn; -var fs = require('fs'); -var ListSuites = require('./utils/ListSuites'); - -let suite; - -program - .description(`Start the suite provided as argument. You can list the suites with the 'list' command.`) - .arguments('') - .action((suiteArg) => suite = suiteArg) - .parse(process.argv) - -if (!suite) { - program.help(); -} - -if (ListSuites().indexOf(suite) == -1) { - console.log("[WARNING] This suite does not exist. Use 'list' command to check the existing suites."); - process.exit(1); -} - -const ENVIRONMENT_FILENAME = '.suite'; - -let runEnvProcess; - -// Sometime SIGINT is received twice, we make sure with this variable that we cleanup -// only once. -var alreadyCleaningUp = false; - -// Properly cleanup server and client if ctrl-c is hit -process.on('SIGINT', function() { - if (alreadyCleaningUp) return; - alreadyCleaningUp = true; - console.log('Cleanup procedure is running...'); -}); - -async function main() { - fs.writeFileSync(ENVIRONMENT_FILENAME, suite); - - // Start the environment from ts-node process. - runEnvProcess = spawn('./node_modules/.bin/ts-node -P test/tsconfig.json -- ./scripts/run-environment.ts ' + suite, { - shell: true, - env: { - ...process.env, - ENVIRONMENT: 'dev', - } - }); - runEnvProcess.stdout.pipe(process.stdout); - runEnvProcess.stderr.pipe(process.stderr); - - runEnvProcess.on('exit', function(statusCode) { - fs.unlinkSync(ENVIRONMENT_FILENAME); - process.exit(statusCode); - }); -} - -main() - .catch((err) => { - console.error(err); - process.exit(1) - }); \ No newline at end of file diff --git a/scripts/authelia-scripts-suites-test b/scripts/authelia-scripts-suites-test deleted file mode 100755 index ffcb947eb..000000000 --- a/scripts/authelia-scripts-suites-test +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env node - -var program = require('commander'); -var spawn = require('child_process').spawn; -var fs = require('fs'); -var ListSuites = require('./utils/ListSuites'); - -let suite; - -program - .description('Run the tests for the current suite or the provided one.') - .arguments('[suite]') - .option('--headless', 'Run in headless mode.') - .option('--forbid-only', 'Forbid only and pending filters.') - .action((suiteArg) => suite = suiteArg) - .parse(process.argv); - -async function runTests(suite, withEnv) { - return new Promise((resolve, reject) => { - let mochaArgs = ['--exit', '--colors', '--require', 'ts-node/register', 'test/suites/' + suite + '/test.ts'] - if (program.forbidOnly) { - mochaArgs = ['--forbid-only', '--forbid-pending'].concat(mochaArgs); - } - - const mochaCommand = './node_modules/.bin/mocha ' + mochaArgs.join(' '); - let testProcess; - if (!withEnv) { - testProcess = spawn(mochaCommand, { - shell: true, - env: { - ...process.env, - TS_NODE_PROJECT: 'test/tsconfig.json', - HEADLESS: (program.headless) ? 'y' : 'n', - ENVIRONMENT: 'dev', - } - }); - } else { - testProcess = spawn('./node_modules/.bin/ts-node', - ['-P', 'test/tsconfig.json', '--', './scripts/run-environment.ts', suite, mochaCommand], { - env: { - ...process.env, - TS_NODE_PROJECT: 'test/tsconfig.json', - HEADLESS: (program.headless) ? 'y' : 'n', - ENVIRONMENT: 'dev', - } - }); - } - - testProcess.stdout.pipe(process.stdout); - testProcess.stderr.pipe(process.stderr); - - testProcess.on('exit', function(statusCode) { - if (statusCode == 0) resolve(); - reject(new Error('Tests exited with status ' + statusCode)); - }); - }); -} - -async function runAllTests() { - const suites = ListSuites(); - let failure = false; - for(var s in suites) { - try { - console.log('Running suite %s', suites[s]); - await runTests(suites[s], true); - } catch (e) { - console.error(e); - failure = true; - } - } - if (failure) { - throw new Error('Some tests failed.'); - } -} - -const ENVIRONMENT_FILENAME = '.suite'; // This file is created by the start command. -const suiteFileExists = fs.existsSync(ENVIRONMENT_FILENAME); - -if (suite) { - if (suiteFileExists && suite != fs.readFileSync(ENVIRONMENT_FILENAME)) { - console.error('You cannot test a suite while another one is running. If you want to test the current suite, ' + - 'do not provide the suite argument. Otherwise, stop the current suite and run the command again.'); - process.exit(1); - } - console.log('Suite %s provided. Running test related to this suite against built version of Authelia.', suite); - runTests(suite, !suiteFileExists) - .catch((err) => { - console.error(err); - process.exit(1); - }); -} -else if (suiteFileExists) { - suite = fs.readFileSync(ENVIRONMENT_FILENAME); - console.log('Suite %s detected from dev env. Running test related to this suite.', suite); - runTests(suite, false) - .catch((err) => { - console.error(err); - process.exit(1); - }); -} -else { - console.log('No suite provided therefore all suites will be tested.'); - runAllTests(suite) - .catch((err) => { - console.error(err); - process.exit(1); - }); -} - -// Sometime SIGINT is received twice, we make sure with this variable that we cleanup -// only once. -var alreadyCleaningUp = false; - -// Properly cleanup server and client if ctrl-c is hit -process.on('SIGINT', function() { - if (alreadyCleaningUp) return; - alreadyCleaningUp = true; - console.log('Cleanup procedure is running...'); -}); - diff --git a/scripts/authelia-scripts-travis b/scripts/authelia-scripts-travis deleted file mode 100755 index f194d7e06..000000000 --- a/scripts/authelia-scripts-travis +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -set -e - -source bootstrap.sh - -docker --version -docker-compose --version - -authelia-scripts bootstrap - -docker-compose -f docker-compose.yml \ - -f example/compose/mongo/docker-compose.yml \ - -f example/compose/redis/docker-compose.yml \ - -f example/compose/nginx/portal/docker-compose.yml \ - -f example/compose/smtp/docker-compose.yml \ - -f example/compose/httpbin/docker-compose.yml \ - -f example/compose/ldap/docker-compose.admin.yml \ - -f example/compose/ldap/docker-compose.yml \ - pull - -# Build -echo "===> Build stage" -authelia-scripts build - -# Run unit tests -echo "===> Unit tests stage" -authelia-scripts unittest - -# Build the docker image -echo "===> Docker image build stage" -authelia-scripts docker build - -# Run integration tests -echo "===> e2e stage" -authelia-scripts suites test --headless --forbid-only - -# Test npm deployment before actual deployment -# ./scripts/npm-deployment-test.sh diff --git a/scripts/authelia-scripts-unittest b/scripts/authelia-scripts-unittest deleted file mode 100755 index f9143f72f..000000000 --- a/scripts/authelia-scripts-unittest +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -go test ./... \ No newline at end of file diff --git a/scripts/npm-deployment-test.sh b/scripts/npm-deployment-test.sh deleted file mode 100755 index 1776833c8..000000000 --- a/scripts/npm-deployment-test.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -set -e - -NPM_UNPACK_DIR=/tmp/npm-unpack - -echo "--- Packing npm package into a tarball" -npm pack - -AUTHELIA_PACKAGE=`ls | grep "authelia-\([0-9]\+.\)\{2\}[0-9]\+.tgz"` -echo "--- Authelia package is ${AUTHELIA_PACKAGE}" - -tar -tzvf ${AUTHELIA_PACKAGE} - -echo "--- Copy package into "${NPM_UNPACK_DIR}" to test unpacking" -mkdir -p ${NPM_UNPACK_DIR} -cp ${AUTHELIA_PACKAGE} ${NPM_UNPACK_DIR} - -pushd ${NPM_UNPACK_DIR} - -echo "--- Test unpacking..." -npm install ${AUTHELIA_PACKAGE} - -RET_CODE_INSTALL=$? -# echo ${RET_CODE} - -# The binary must start and display the help menu -./node_modules/.bin/authelia | grep "No config file has been provided." -RET_CODE_RUN=$? - -popd - -if [ "$RET_CODE_INSTALL" != "0" ] || [ "$RET_CODE_RUN" != "0" ] -then - echo "--- Unpacking failed..." - exit 1 -else - echo "+++ Unpacking succeeded" - exit 0 -fi - - - diff --git a/scripts/run-environment.ts b/scripts/run-environment.ts index 744391a2c..df6b04c85 100644 --- a/scripts/run-environment.ts +++ b/scripts/run-environment.ts @@ -39,11 +39,12 @@ async function stop() { console.error('Teardown timed out...'); process.exit(1); }, teardown_timeout); - console.log('>>> Tearing down environment <<<'); - try { + + try { + console.log('>>> Tearing down environment <<<'); await teardown(); clearTimeout(timer); - } catch (err) { + } catch(err) { console.error(err); throw err; } diff --git a/scripts/utils/docker.js b/scripts/utils/docker.js deleted file mode 100644 index e899665b7..000000000 --- a/scripts/utils/docker.js +++ /dev/null @@ -1,6 +0,0 @@ - - -module.exports = { - IMAGE_NAME: 'authelia', - DOCKERHUB_IMAGE_NAME: 'clems4ever/authelia' -} \ No newline at end of file diff --git a/test/helpers/context/AutheliaServerFromDist.ts b/test/helpers/context/AutheliaServerFromDist.ts index 1c1767daf..97c762166 100644 --- a/test/helpers/context/AutheliaServerFromDist.ts +++ b/test/helpers/context/AutheliaServerFromDist.ts @@ -14,8 +14,8 @@ class AutheliaServerFromDist implements AutheliaServerInterface { } async start() { - console.log("Spawn authelia server from dist."); - this.serverProcess = ChildProcess.spawn('./scripts/authelia-scripts serve ' + this.configPath, { + console.log("Spawn authelia server from dist using config " + this.configPath); + this.serverProcess = ChildProcess.spawn('./cmd/authelia-scripts/authelia-scripts serve ' + this.configPath, { shell: true, env: process.env, } as any); diff --git a/test/helpers/scenarii/SingleFactorAuthentication.ts b/test/helpers/scenarii/SingleFactorAuthentication.ts index d1bc8471a..9cbec8958 100644 --- a/test/helpers/scenarii/SingleFactorAuthentication.ts +++ b/test/helpers/scenarii/SingleFactorAuthentication.ts @@ -30,7 +30,7 @@ export default function(timeout: number = 5000) { await VisitPage(this.driver, "https://admin.example.com:8080/secret.html"); // the url should be the one from the portal. - await VerifyUrlContains(this.driver, "https://login.example.com:8080/#/?rd=https://admin.example.com:8080", timeout); + await VerifyUrlContains(this.driver, "https://login.example.com:8080/#/?rd=https://admin.example.com:8080/secret.html", timeout); // And the user should end up on the second factor page. await VerifyIsSecondFactorStage(this.driver, timeout);