Declare suites as Go structs and bootstrap e2e test framework in Go.

Some tests are not fully rewritten in Go, a typescript wrapper is called
instead until we remove the remaining TS tests and dependencies.

Also, dockerize every components (mainly Authelia backend, frontend and kind)
so that the project does not interfere with user host anymore (open ports for instance).
The only remaining intrusive change is the one done during bootstrap to add entries in /etc/hosts.
It will soon be avoided using authelia.com domain that I own.
This commit is contained in:
Clement Michaud 2019-11-02 15:32:58 +01:00 committed by Clément Michaud
parent ad8463f2fa
commit a991379a74
214 changed files with 3509 additions and 3815 deletions

4
.gitignore vendored
View File

@ -35,12 +35,10 @@ example/ldap/private.ldif
Configuration.schema.json
users_database.test.yml
.suite
.kube
.idea
.authelia-interrupt
qemu-*-static
qemu-*-static

View File

@ -10,25 +10,34 @@ services:
- ntp
- xvfb
addons:
chrome: stable
apt:
sources:
- google-chrome
packages:
- libgif-dev
- google-chrome-stable
install: # Install ChromeDriver (64bits; replace 64 with 32 for 32bits).
- wget -N https://chromedriver.storage.googleapis.com/78.0.3904.70/chromedriver_linux64.zip -P ~/
- unzip ~/chromedriver_linux64.zip -d ~/
- rm ~/chromedriver_linux64.zip
- sudo mv -f ~/chromedriver /usr/local/share/
- sudo chmod +x /usr/local/share/chromedriver
- sudo ln -s /usr/local/share/chromedriver /usr/bin/chromedriver
before_script:
- export PATH=./cmd/authelia-scripts/:/tmp:$PATH
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
- nvm install v11 && nvm use v11 && npm i
- source bootstrap.sh
jobs:
include:
- stage: test
addons:
chrome: stable
apt:
sources:
- google-chrome
packages:
- libgif-dev
- google-chrome-stable
script:
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
- nvm install v11 && nvm use v11 && npm i
- source bootstrap.sh
- authelia-scripts ci
- authelia-scripts --log-level debug ci
# TODO(c.michaud): publish built artifact on Github.
- &build-images
stage: build images

View File

@ -1,6 +1,6 @@
#!/bin/bash
export PATH=./cmd/authelia-scripts/:/tmp:$PATH
export PATH=./cmd/authelia-scripts/:/tmp:$PATH:./node_modules/.bin
if [ -z "$OLD_PS1" ]; then
OLD_PS1="$PS1"

View File

@ -1,2 +1,3 @@
HOST=authelia-frontend
REACT_APP_CSP_CONTENT="default-src 'unsafe-inline'; script-src * 'unsafe-inline'; img-src * data:; style-src 'unsafe-inline'; connect-src * 'unsafe-inline' extensions:"

View File

@ -47,5 +47,6 @@
"not dead",
"not ie <= 11",
"not op_mini all"
]
],
"proxy": "http://authelia-backend:9091/"
}

View File

@ -8,6 +8,7 @@ import (
"os/exec"
"strings"
"github.com/clems4ever/authelia/utils"
"github.com/spf13/cobra"
)
@ -41,7 +42,7 @@ var hostEntries = []HostEntry{
}
func runCommand(cmd string, args ...string) {
command := CommandWithStdout(cmd, args...)
command := utils.CommandWithStdout(cmd, args...)
err := command.Run()
if err != nil {
@ -66,7 +67,7 @@ func checkCommandExist(cmd string) {
}
func installClientNpmPackages() {
command := CommandWithStdout("npm", "ci")
command := utils.CommandWithStdout("npm", "ci")
command.Dir = "client"
err := command.Run()
@ -97,20 +98,10 @@ func shell(cmd string) {
func buildHelperDockerImages() {
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")
}
shell("docker-compose -f docker-compose.yml -f example/compose/kind/docker-compose.yml build")
shell("docker-compose -f docker-compose.yml -f example/compose/authelia/docker-compose.backend.yml build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)")
shell("docker-compose -f docker-compose.yml -f example/compose/authelia/docker-compose.frontend.yml build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)")
}
func prepareHostsFile() {
@ -203,24 +194,31 @@ func Bootstrap(cobraCmd *cobra.Command, args []string) {
bootstrapPrintln("Getting versions of tools")
readVersions()
bootstrapPrintln("Checking if GOPATH is set")
goPathFound := false
for _, v := range os.Environ() {
if strings.HasPrefix(v, "GOPATH=") {
goPathFound = true
break
}
}
if !goPathFound {
log.Fatal("GOPATH is not set")
}
bootstrapPrintln("Installing NPM packages for development...")
installNpmPackages()
bootstrapPrintln("Install NPM packages for frontend...")
installClientNpmPackages()
bootstrapPrintln("Building development Docker images...")
buildHelperDockerImages()
dockerBuildOfficialImage(defaultArch)
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 docker-image' to start Authelia and visit https://home.example.com:8080.")
bootstrapPrintln("Run 'authelia-scripts suites setup Standalone' 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")
}

View File

@ -1,14 +1,15 @@
package main
import (
"fmt"
"os"
"github.com/clems4ever/authelia/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
func buildAutheliaBinary() {
cmd := CommandWithStdout("go", "build", "-o", "../../"+OutputDir+"/authelia")
cmd := utils.CommandWithStdout("go", "build", "-o", "../../"+OutputDir+"/authelia")
cmd.Dir = "cmd/authelia"
cmd.Env = append(os.Environ(),
"GOOS=linux", "GOARCH=amd64", "CGO_ENABLED=1")
@ -21,35 +22,43 @@ func buildAutheliaBinary() {
}
func buildFrontend() {
cmd := CommandWithStdout("npm", "run", "build")
// Install npm dependencies
cmd := utils.CommandWithStdout("npm", "ci")
cmd.Dir = "client"
err := cmd.Run()
if err != nil {
panic(err)
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
err = os.Rename("client/build", OutputDir+"/public_html")
// Then build the frontend
cmd = utils.CommandWithStdout("npm", "run", "build")
cmd.Dir = "client"
if err != nil {
panic(err)
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
if err := os.Rename("client/build", OutputDir+"/public_html"); err != nil {
log.Fatal(err)
}
}
// Build build Authelia
func Build(cobraCmd *cobra.Command, args []string) {
log.Info("Building Authelia...")
Clean(cobraCmd, args)
fmt.Println("Creating `" + OutputDir + "` directory")
log.Debug("Creating `" + OutputDir + "` directory")
err := os.MkdirAll(OutputDir, os.ModePerm)
if err != nil {
panic(err)
}
fmt.Println("Building Authelia Go binary...")
log.Debug("Building Authelia Go binary...")
buildAutheliaBinary()
fmt.Println("Building Authelia frontend...")
log.Debug("Building Authelia frontend...")
buildFrontend()
}

View File

@ -1,8 +1,8 @@
package main
import (
"fmt"
"github.com/clems4ever/authelia/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@ -18,34 +18,18 @@ const dockerPullCommandLine = "docker-compose -f docker-compose.yml " +
// 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)
log.Info("=====> Build stage")
if err := utils.CommandWithStdout("authelia-scripts", "--log-level", "debug", "build").Run(); err != nil {
log.Fatal(err)
}
fmt.Println("===== Build stage =====")
command = CommandWithStdout("authelia-scripts", "build")
err = command.Run()
if err != nil {
panic(err)
log.Info("=====> Unit testing stage")
if err := utils.CommandWithStdout("authelia-scripts", "--log-level", "debug", "unittest").Run(); err != nil {
log.Fatal(err)
}
fmt.Println("===== Unit testing stage =====")
command = CommandWithStdout("authelia-scripts", "unittest")
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)
log.Info("=====> End-to-end testing stage")
if err := utils.CommandWithStdout("authelia-scripts", "--log-level", "debug", "suites", "test", "--headless", "--only-forbidden").Run(); err != nil {
log.Fatal(err)
}
}

View File

@ -1,15 +1,15 @@
package main
import (
"fmt"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// Clean artifacts built and installed by authelia-scripts
func Clean(cobraCmd *cobra.Command, args []string) {
fmt.Println("Removing `" + OutputDir + "` directory")
log.Debug("Removing `" + OutputDir + "` directory")
err := os.RemoveAll(OutputDir)
if err != nil {

View File

@ -3,10 +3,11 @@ package main
import (
"errors"
"fmt"
"log"
"os"
"strings"
"github.com/clems4ever/authelia/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@ -40,25 +41,25 @@ func dockerBuildOfficialImage(arch string) error {
}
if arch == "arm32v7" {
err := CommandWithStdout("docker", "run", "--rm", "--privileged", "multiarch/qemu-user-static", "--reset", "-p", "yes").Run()
err := utils.CommandWithStdout("docker", "run", "--rm", "--privileged", "multiarch/qemu-user-static", "--reset", "-p", "yes").Run()
if err != nil {
panic(err)
}
err = CommandWithStdout("bash", "-c", "wget https://github.com/multiarch/qemu-user-static/releases/download/v4.1.0-1/qemu-arm-static -O ./qemu-arm-static && chmod +x ./qemu-arm-static").Run()
err = utils.CommandWithStdout("bash", "-c", "wget https://github.com/multiarch/qemu-user-static/releases/download/v4.1.0-1/qemu-arm-static -O ./qemu-arm-static && chmod +x ./qemu-arm-static").Run()
if err != nil {
panic(err)
}
} else if arch == "arm64v8" {
err := CommandWithStdout("docker", "run", "--rm", "--privileged", "multiarch/qemu-user-static", "--reset", "-p", "yes").Run()
err := utils.CommandWithStdout("docker", "run", "--rm", "--privileged", "multiarch/qemu-user-static", "--reset", "-p", "yes").Run()
if err != nil {
panic(err)
}
err = CommandWithStdout("bash", "-c", "wget https://github.com/multiarch/qemu-user-static/releases/download/v4.1.0-1/qemu-aarch64-static -O ./qemu-aarch64-static && chmod +x ./qemu-aarch64-static").Run()
err = utils.CommandWithStdout("bash", "-c", "wget https://github.com/multiarch/qemu-user-static/releases/download/v4.1.0-1/qemu-aarch64-static -O ./qemu-aarch64-static && chmod +x ./qemu-aarch64-static").Run()
if err != nil {
panic(err)
@ -73,6 +74,7 @@ var DockerBuildCmd = &cobra.Command{
Use: "build",
Short: "Build the docker image of Authelia",
Run: func(cmd *cobra.Command, args []string) {
log.Infof("Building Docker image %s...", DockerImageName)
checkArchIsSupported(arch)
err := dockerBuildOfficialImage(arch)
@ -94,6 +96,7 @@ var DockerPushCmd = &cobra.Command{
Use: "push-image",
Short: "Publish Authelia docker image to Dockerhub",
Run: func(cmd *cobra.Command, args []string) {
log.Infof("Pushing Docker image %s to dockerhub...", DockerImageName)
checkArchIsSupported(arch)
publishDockerImage(arch)
},
@ -104,6 +107,7 @@ var DockerManifestCmd = &cobra.Command{
Use: "push-manifest",
Short: "Publish Authelia docker manifest to Dockerhub",
Run: func(cmd *cobra.Command, args []string) {
log.Infof("Pushing Docker manifest of %s to dockerhub...", DockerImageName)
publishDockerManifest()
},
}
@ -113,76 +117,59 @@ func login(docker *Docker) {
password := os.Getenv("DOCKER_PASSWORD")
if username == "" {
panic(errors.New("DOCKER_USERNAME is empty"))
log.Fatal(errors.New("DOCKER_USERNAME is empty"))
}
if password == "" {
panic(errors.New("DOCKER_PASSWORD is empty"))
log.Fatal(errors.New("DOCKER_PASSWORD is empty"))
}
fmt.Println("Login to dockerhub as " + username)
log.Debug("Login to dockerhub as " + username)
err := docker.Login(username, password)
if err != nil {
fmt.Println("Login to dockerhub failed")
panic(err)
log.Fatal("Login to dockerhub failed", err)
}
}
func deploy(docker *Docker, tag string) {
imageWithTag := DockerImageName + ":" + tag
fmt.Println("===================================================")
fmt.Println("Docker image " + imageWithTag + " will be deployed on Dockerhub.")
fmt.Println("===================================================")
log.Debug("Docker image " + imageWithTag + " will be deployed on Dockerhub.")
err := docker.Tag(DockerImageName, imageWithTag)
if err != nil {
panic(err)
if err := docker.Tag(DockerImageName, imageWithTag); err != nil {
log.Fatal(err)
}
err = docker.Push(imageWithTag)
if err != nil {
panic(err)
if err := docker.Push(imageWithTag); err != nil {
log.Fatal(err)
}
}
func deployManifest(docker *Docker, tag string, amd64tag string, arm32v7tag string, arm64v8tag string) {
dockerImagePrefix := DockerImageName + ":"
fmt.Println("===================================================")
fmt.Println("Docker manifest " + dockerImagePrefix + tag + " will be deployed on Dockerhub.")
fmt.Println("===================================================")
log.Debug("Docker manifest " + dockerImagePrefix + tag + " will be deployed on Dockerhub.")
err := docker.Manifest(dockerImagePrefix+tag, dockerImagePrefix+amd64tag, dockerImagePrefix+arm32v7tag, dockerImagePrefix+arm64v8tag)
if err != nil {
panic(err)
log.Fatal(err)
}
tags := []string{amd64tag, arm32v7tag, arm64v8tag}
for _, t := range tags {
fmt.Println("===================================================")
fmt.Println("Docker removing tag for " + dockerImagePrefix + t + " on Dockerhub.")
fmt.Println("===================================================")
log.Debug("Docker removing tag for " + dockerImagePrefix + t + " on Dockerhub.")
err = docker.CleanTag(t)
if err != nil {
if err := docker.CleanTag(t); err != nil {
panic(err)
}
}
fmt.Println("===================================================")
fmt.Println("Docker pushing README.md to Dockerhub.")
fmt.Println("===================================================")
log.Debug("Docker pushing README.md to Dockerhub.")
err = docker.PublishReadme()
if err != nil {
panic(err)
if err := docker.PublishReadme(); err != nil {
log.Fatal(err)
}
}
@ -201,7 +188,7 @@ func publishDockerImage(arch string) {
deploy(docker, travisTag+"-"+arch)
deploy(docker, "latest-"+arch)
} else {
fmt.Println("Docker image will not be published")
log.Info("Docker image will not be published")
}
}

View File

@ -3,12 +3,15 @@ package main
import (
"os"
"github.com/clems4ever/authelia/utils"
log "github.com/sirupsen/logrus"
"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])
log.Infof("Running Authelia with config %s...", args[0])
cmd := utils.CommandWithStdout(OutputDir+"/authelia", "-config", args[0])
cmd.Env = append(os.Environ(), "PUBLIC_DIR=dist/public_html")
RunCommandUntilCtrlC(cmd)
utils.RunCommandUntilCtrlC(cmd)
}

View File

@ -5,48 +5,33 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"os/signal"
"sort"
"strings"
"syscall"
"time"
"github.com/clems4ever/authelia/suites"
"github.com/clems4ever/authelia/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
func listDirectories(path string) ([]string, error) {
files, err := ioutil.ReadDir(path)
if err != nil {
return nil, err
}
// ErrNotAvailableSuite error raised when suite is not available.
var ErrNotAvailableSuite = errors.New("unavailable suite")
dirs := make([]string, 0)
// ErrNoRunningSuite error raised when no suite is running
var ErrNoRunningSuite = errors.New("no running suite")
for _, f := range files {
if f.IsDir() {
dirs = append(dirs, f.Name())
}
}
// runningSuiteFile name of the file containing the currently running suite
var runningSuiteFile = ".suite"
return dirs, nil
}
var headless bool
var onlyForbidden bool
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
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")
}
// SuitesListCmd Command for listing the available suites
@ -54,117 +39,166 @@ 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"))
fmt.Println(strings.Join(listSuites(), "\n"))
},
Args: cobra.ExactArgs(0),
}
// SuitesCleanCmd Command for cleaning suite environments
var SuitesCleanCmd = &cobra.Command{
Use: "clean",
Short: "Clean suite environments.",
// SuitesSetupCmd Command for setuping a suite environment
var SuitesSetupCmd = &cobra.Command{
Use: "setup [suite]",
Short: "Setup a Go suite environment. Suites can be listed using the list command.",
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()
providedSuite := args[0]
runningSuite, err := getRunningSuite()
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)
log.Fatal(err)
}
selectedSuite := args[0]
available, err := suiteAvailable(selectedSuite, suites)
if err != nil {
panic(err)
if runningSuite != "" && runningSuite != providedSuite {
log.Fatal("A suite is already running")
}
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)
if err := setupSuite(providedSuite); err != nil {
log.Fatal(err)
}
},
Args: cobra.ExactArgs(1),
}
// SuitesTeardownCmd Command for tearing down a suite environment
var SuitesTeardownCmd = &cobra.Command{
Use: "teardown [suite]",
Short: "Teardown a Go suite environment. Suites can be listed using the list command.",
Run: func(cmd *cobra.Command, args []string) {
var suiteName string
if len(args) == 1 {
suiteName = args[0]
} else {
runningSuite, err := getRunningSuite()
if err != nil {
panic(err)
}
if runningSuite == "" {
panic(ErrNoRunningSuite)
}
suiteName = runningSuite
}
if err := teardownSuite(suiteName); err != nil {
panic(err)
}
},
Args: cobra.MaximumNArgs(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)
Run: testSuite,
Args: cobra.MaximumNArgs(1),
}
func listSuites() []string {
suiteNames := make([]string, 0)
for _, k := range suites.GlobalRegistry.Suites() {
suiteNames = append(suiteNames, k)
}
sort.Strings(suiteNames)
return suiteNames
}
func checkSuiteAvailable(suite string) error {
suites := listSuites()
for _, s := range suites {
if s == suite {
return nil
}
}
return ErrNotAvailableSuite
}
func runSuiteSetupTeardown(command string, suite string) error {
selectedSuite := suite
err := checkSuiteAvailable(selectedSuite)
if err != nil {
if err == ErrNotAvailableSuite {
log.Fatal(errors.New("Suite named " + selectedSuite + " does not exist"))
}
log.Fatal(err)
}
s := suites.GlobalRegistry.Get(selectedSuite)
cmd := utils.CommandWithStdout("bash", "-c", "go run cmd/authelia-suites/*.go "+command+" "+selectedSuite)
cmd.Env = os.Environ()
return utils.RunCommandWithTimeout(cmd, s.SetUpTimeout)
}
func setupSuite(suiteName string) error {
log.Infof("Setup environment for suite %s...", suiteName)
signalChannel := make(chan os.Signal)
signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM)
interrupted := false
go func() {
<-signalChannel
interrupted = true
}()
if errSetup := runSuiteSetupTeardown("setup", suiteName); errSetup != nil || interrupted {
teardownSuite(suiteName)
return errSetup
}
return nil
}
func teardownSuite(suiteName string) error {
log.Infof("Tear down environment for suite %s...", suiteName)
return runSuiteSetupTeardown("teardown", suiteName)
}
func testSuite(cmd *cobra.Command, args []string) {
runningSuite, err := getRunningSuite()
if err != nil {
log.Fatal(err)
}
if len(args) == 1 {
suite := args[0]
if runningSuite != "" && suite != runningSuite {
log.Fatal(errors.New("Running suite (" + runningSuite + ") is different than suite to be tested (" + suite + "). Shutdown running suite and retry"))
}
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"))
if err := runSuiteTests(suite, runningSuite == ""); err != nil {
log.Fatal(err)
}
} else {
if runningSuite != "" {
fmt.Println("Running suite (" + runningSuite + ") detected. Run tests of that suite")
if err := runSuiteTests(runningSuite, false); err != nil {
log.Fatal(err)
}
runSuiteTests(suite, runningSuite == "")
} else {
if runningSuite != "" {
fmt.Println("Running suite (" + runningSuite + ") detected. Run tests of that suite")
runSuiteTests(runningSuite, false)
} else {
fmt.Println("No suite provided therefore all suites will be tested")
runAllSuites()
fmt.Println("No suite provided therefore all suites will be tested")
if err := runAllSuites(); err != nil {
log.Fatal(err)
}
}
},
Args: cobra.MaximumNArgs(1),
}
}
func getRunningSuite() (string, error) {
exist, err := FileExists(RunningSuiteFile)
exist, err := utils.FileExists(runningSuiteFile)
if err != nil {
return "", err
@ -174,61 +208,51 @@ func getRunningSuite() (string, error) {
return "", nil
}
b, err := ioutil.ReadFile(RunningSuiteFile)
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")
func runSuiteTests(suiteName string, withEnv bool) error {
if withEnv {
if err := setupSuite(suiteName); err != nil {
return err
}
}
mochaCmdLine := "./node_modules/.bin/mocha " + strings.Join(mochaArgs, " ")
fmt.Println(mochaCmdLine)
suite := suites.GlobalRegistry.Get(suiteName)
headlessValue := "n"
// Default value is 1 minute
timeout := "60s"
if suite.TestTimeout > 0 {
timeout = fmt.Sprintf("%ds", int64(suite.TestTimeout/time.Second))
}
testCmdLine := fmt.Sprintf("go test ./suites -timeout %s -run '^(Test%sSuite)$'", timeout, suiteName)
log.Infof("Running tests of suite %s...", suiteName)
log.Debugf("Running tests with command: %s", testCmdLine)
cmd := utils.CommandWithStdout("bash", "-c", testCmdLine)
cmd.Env = os.Environ()
if headless {
headlessValue = "y"
cmd.Env = append(cmd.Env, "HEADLESS=y")
}
var cmd *exec.Cmd
testErr := cmd.Run()
if withEnv {
cmd = CommandWithStdout("bash", "-c",
"./node_modules/.bin/ts-node ./scripts/run-environment.ts "+suite+" '"+mochaCmdLine+"'")
} else {
cmd = CommandWithStdout("bash", "-c", mochaCmdLine)
teardownSuite(suiteName)
}
cmd.Env = append(os.Environ(),
"TS_NODE_PROJECT=test/tsconfig.json",
"HEADLESS="+headlessValue,
"ENVIRONMENT=dev")
err := cmd.Run()
if err != nil {
panic(err)
}
return testErr
}
func runAllSuites() {
suites, err := listSuites()
if err != nil {
panic(err)
}
for _, s := range suites {
runSuiteTests(s, true)
func runAllSuites() error {
log.Info("Start running all suites")
for _, s := range listSuites() {
if err := runSuiteTests(s, true); err != nil {
return err
}
}
}
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")
log.Info("All suites passed successfully")
return nil
}

View File

@ -1,11 +1,15 @@
package main
import "github.com/spf13/cobra"
import (
"github.com/clems4ever/authelia/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// RunUnitTest run the unit tests
func RunUnitTest(cobraCmd *cobra.Command, args []string) {
err := CommandWithStdout("go", "test", "./...").Run()
err := utils.Shell("go test $(go list ./... | grep -v suites)").Run()
if err != nil {
panic(err)
log.Fatal(err)
}
}

View File

@ -8,6 +8,3 @@ 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"

View File

@ -1,57 +1,61 @@
package main
import (
"github.com/clems4ever/authelia/utils"
)
// Docker a docker object
type Docker struct{}
// Build build a docker image
func (d *Docker) Build(tag, dockerfile, target string) error {
return CommandWithStdout("docker", "build", "-t", tag, "-f", dockerfile, target).Run()
return utils.CommandWithStdout("docker", "build", "-t", tag, "-f", dockerfile, target).Run()
}
// Tag tag a docker image.
func (d *Docker) Tag(image, tag string) error {
return CommandWithStdout("docker", "tag", image, tag).Run()
return utils.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()
return utils.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()
return utils.CommandWithStdout("docker", "push", tag).Run()
}
// Manifest push a docker manifest to dockerhub.
func (d *Docker) Manifest(tag, amd64tag, arm32v7tag, arm64v8tag string) error {
err := CommandWithStdout("docker", "manifest", "create", tag, amd64tag, arm32v7tag, arm64v8tag).Run()
err := utils.CommandWithStdout("docker", "manifest", "create", tag, amd64tag, arm32v7tag, arm64v8tag).Run()
if err != nil {
panic(err)
}
err = CommandWithStdout("docker", "manifest", "annotate", tag, arm32v7tag, "--os", "linux", "--arch", "arm").Run()
err = utils.CommandWithStdout("docker", "manifest", "annotate", tag, arm32v7tag, "--os", "linux", "--arch", "arm").Run()
if err != nil {
panic(err)
}
err = CommandWithStdout("docker", "manifest", "annotate", tag, arm64v8tag, "--os", "linux", "--arch", "arm64", "--variant", "v8").Run()
err = utils.CommandWithStdout("docker", "manifest", "annotate", tag, arm64v8tag, "--os", "linux", "--arch", "arm64", "--variant", "v8").Run()
if err != nil {
panic(err)
}
return CommandWithStdout("docker", "manifest", "push", "--purge", tag).Run()
return utils.CommandWithStdout("docker", "manifest", "push", "--purge", tag).Run()
}
// CleanTag remove a tag from dockerhub.
func (d *Docker) CleanTag(tag string) error {
return CommandWithStdout("bash", "-c", "curl -s -o /dev/null -u $DOCKER_USERNAME:$DOCKER_PASSWORD -X DELETE https://cloud.docker.com/v2/repositories/"+DockerImageName+"/tags/"+tag+"/").Run()
return utils.CommandWithStdout("bash", "-c", "curl -s -o /dev/null -u $DOCKER_USERNAME:$DOCKER_PASSWORD -X DELETE https://cloud.docker.com/v2/repositories/"+DockerImageName+"/tags/"+tag+"/").Run()
}
// PublishReadme push README.md to dockerhub.
func (d *Docker) PublishReadme() error {
return CommandWithStdout("bash", "-c", `jq -n --arg msg "$(<README.md)" '{"registry":"registry-1.docker.io","full_description": $msg }' | curl -s -o /dev/null -u $DOCKER_USERNAME:$DOCKER_PASSWORD -X "PATCH" -H "Content-Type: application/json" -d @- https://cloud.docker.com/v2/repositories/clems4ever/authelia/`).Run()
return utils.CommandWithStdout("bash", "-c", `jq -n --arg msg "$(<README.md)" '{"registry":"registry-1.docker.io","full_description": $msg }' | curl -s -o /dev/null -u $DOCKER_USERNAME:$DOCKER_PASSWORD -X "PATCH" -H "Content-Type: application/json" -d @- https://cloud.docker.com/v2/repositories/clems4ever/authelia/`).Run()
}

View File

@ -1,52 +0,0 @@
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()
}

View File

@ -3,11 +3,13 @@
package main
import (
"log"
"github.com/clems4ever/authelia/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var logLevel string
// AutheliaCommandDefinition is the definition of one authelia-scripts command.
type AutheliaCommandDefinition struct {
Name string
@ -59,9 +61,14 @@ var Commands = []AutheliaCommandDefinition{
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},
Name: "suites",
Short: "Compute hash of a password for creating a file-based users database",
SubCommands: CobraCommands{
SuitesTestCmd,
SuitesListCmd,
SuitesSetupCmd,
SuitesTeardownCmd,
},
},
AutheliaCommandDefinition{
Name: "ci",
@ -75,6 +82,15 @@ var Commands = []AutheliaCommandDefinition{
},
}
func levelStringToLevel(level string) log.Level {
if level == "debug" {
return log.DebugLevel
} else if level == "warning" {
return log.WarnLevel
}
return log.InfoLevel
}
func main() {
var rootCmd = &cobra.Command{Use: "authelia-scripts"}
cobraCommands := make([]*cobra.Command, 0)
@ -85,7 +101,7 @@ func main() {
if autheliaCommand.CommandLine != "" {
cmdline := autheliaCommand.CommandLine
fn = func(cobraCmd *cobra.Command, args []string) {
cmd := CommandWithStdout(cmdline, args...)
cmd := utils.CommandWithStdout(cmdline, args...)
err := cmd.Run()
if err != nil {
panic(err)
@ -118,10 +134,18 @@ func main() {
cobraCommands = append(cobraCommands, command)
}
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Set the log level for the command")
rootCmd.AddCommand(cobraCommands...)
cobra.OnInitialize(initConfig)
err := rootCmd.Execute()
if err != nil {
log.Fatal(err)
}
}
func initConfig() {
log.SetLevel(levelStringToLevel(logLevel))
}

125
cmd/authelia-suites/main.go Normal file
View File

@ -0,0 +1,125 @@
package main
import (
"io/ioutil"
"os"
"path/filepath"
"github.com/clems4ever/authelia/suites"
"github.com/clems4ever/authelia/utils"
"github.com/otiai10/copy"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var tmpDirectory = "/tmp/authelia/suites/"
// runningSuiteFile name of the file containing the currently running suite
var runningSuiteFile = ".suite"
func init() {
log.SetLevel(log.DebugLevel)
}
func main() {
rootCmd := &cobra.Command{
Use: "authelia-suites",
}
startCmd := &cobra.Command{
Use: "setup [suite]",
Short: "Setup the suite environment",
Run: setupSuite,
}
stopCmd := &cobra.Command{
Use: "teardown [suite]",
Short: "Teardown the suite environment",
Run: teardownSuite,
}
rootCmd.AddCommand(startCmd)
rootCmd.AddCommand(stopCmd)
rootCmd.Execute()
}
func createRunningSuiteFile(suite string) error {
return ioutil.WriteFile(runningSuiteFile, []byte(suite), 0644)
}
func removeRunningSuiteFile() error {
return os.Remove(runningSuiteFile)
}
func setupSuite(cmd *cobra.Command, args []string) {
suiteName := args[0]
s := suites.GlobalRegistry.Get(suiteName)
cwd, err := filepath.Abs("./")
if err != nil {
log.Fatal(err)
}
suiteResourcePath := cwd + "/suites/" + suiteName
exist, err := utils.FileExists(suiteResourcePath)
if err != nil {
log.Fatal(err)
}
suiteTmpDirectory := tmpDirectory + suiteName
if exist {
err := copy.Copy(suiteResourcePath, suiteTmpDirectory)
if err != nil {
log.Fatal(err)
}
} else {
err := os.MkdirAll(suiteTmpDirectory, 0755)
if err != nil {
log.Fatal(err)
}
}
// Create the .suite file
if err := createRunningSuiteFile(suiteName); err != nil {
log.Fatal(err)
}
err = s.SetUp(suiteTmpDirectory)
if err != nil {
log.Error("Failure during environment deployment.")
teardownSuite(nil, args)
log.Fatal(err)
}
log.Info("Environment is ready!")
}
func teardownSuite(cmd *cobra.Command, args []string) {
if os.Getenv("SKIP_TEARDOWN") != "" {
return
}
s := suites.GlobalRegistry.Get(args[0])
if err := removeRunningSuiteFile(); err != nil {
log.Print(err)
}
suiteTmpDirectory := tmpDirectory + args[0]
s.TearDown(suiteTmpDirectory)
err := os.RemoveAll(suiteTmpDirectory)
if err != nil {
log.Fatal(err)
}
log.Info("Environment has been cleaned!")
}

View File

@ -1,8 +1,7 @@
version: '2'
version: '3'
networks:
authelianet:
driver: bridge
ipam:
config:
- subnet: 192.168.240.0/24
gateway: 192.168.240.1

View File

@ -0,0 +1,8 @@
FROM golang:1.13-stretch
ARG USER_ID
ARG GROUP_ID
RUN groupadd -g ${GROUP_ID} dev && \
useradd -m -u $USER_ID -g $GROUP_ID dev
USER dev

View File

@ -0,0 +1,9 @@
FROM node:11-stretch-slim
ARG USER_ID
ARG GROUP_ID
RUN cat /etc/passwd && userdel -rf node && \
groupadd -g ${GROUP_ID} dev && \
useradd -m -u $USER_ID -g $GROUP_ID dev
USER dev

View File

@ -0,0 +1,20 @@
version: '3'
services:
authelia-backend:
build:
context: example/compose/authelia
dockerfile: Dockerfile.backend
command: /resources/entrypoint.sh
working_dir: /app
volumes:
- "./example/compose/authelia/resources/:/resources"
- ".:/app"
- "${GOPATH}:/go"
- "/tmp/authelia:/tmp/authelia"
environment:
- SUITE_PATH=${SUITE_PATH}
- ENVIRONMENT=dev
ports:
- 9091:9091
networks:
- authelianet

View File

@ -0,0 +1,8 @@
version: '3'
services:
authelia-frontend:
image: nginx:alpine
volumes:
- ./example/compose/authelia/resources/nginx.conf:/etc/nginx/nginx.conf
networks:
- authelianet

View File

@ -0,0 +1,14 @@
version: '3'
services:
authelia-frontend:
build:
context: example/compose/authelia
dockerfile: Dockerfile.frontend
command: npm run start
working_dir: /app
volumes:
- "./client:/app"
ports:
- 3000:3000
networks:
- authelianet

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
authelia:
image: authelia:dist

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -x
go get github.com/cespare/reflex
reflex -c /resources/reflex.conf

View File

@ -0,0 +1,17 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
location / {
proxy_set_header Host $http_host;
proxy_pass http://authelia-backend;
}
}
}

View File

@ -0,0 +1 @@
-r '(\.go$|go\.mod|\.sh|\.yml)' -s /resources/run.sh

View File

@ -0,0 +1,8 @@
#!/bin/bash
# Build the binary
go build -o /tmp/authelia/authelia-tmp cmd/authelia/main.go
# Run the temporary binary
cd $SUITE_PATH
/tmp/authelia/authelia-tmp -config ${SUITE_PATH}/configuration.yml

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
duo-api:
image: authelia-duo-api

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
httpbin:
image: citizenstig/httpbin

View File

@ -0,0 +1,17 @@
FROM alpine:3.10.3
WORKDIR /kind
RUN apk add --no-cache bash curl docker && \
curl -Lo kind https://github.com/clems4ever/kind/releases/download/docker-network/kind && chmod +x kind && \
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl && chmod +x kubectl
ADD entrypoint.sh entrypoint.sh
ADD patch-kubeconfig.sh patch-kubeconfig.sh
ENV HOME=/kind/config
ENV KUBECONFIG=/kind/config/.kube/kind-config-kind
VOLUME /kind/config
ENTRYPOINT ["./entrypoint.sh"]

View File

@ -0,0 +1,4 @@
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
networking:
dockerNetwork: authelia_authelianet

View File

@ -0,0 +1,38 @@
version: '3'
services:
authelia-kind-proxy:
build:
context: ./example/compose/kind
volumes:
- kind-volume:/kind/config
- /var/run/docker.sock:/var/run/docker.sock
- ./example/kube:/authelia
- ./example/compose/kind/config.yml:/etc/kind/config.yml
command: kubectl port-forward --address 0.0.0.0 -n authelia service/nginx-ingress-controller-service 8080:443
networks:
authelianet:
aliases:
- public.example.com
- secure.example.com
- login.example.com
- admin.example.com
- dev.example.com
- mail.example.com
# Set the IP to be able to query on port 443
ipv4_address: 192.168.240.100
kube-dashboard:
build:
context: ./example/compose/kind
volumes:
- kind-volume:/kind/config
- ./example/compose/kind/entrypoint-dashboard.sh:/entrypoint-dashboard.sh
command: "/entrypoint-dashboard.sh"
networks:
authelianet:
aliases:
- kubernetes.example.com
ipv4_address: 192.168.240.110
volumes:
kind-volume:

View File

@ -0,0 +1,4 @@
#!/bin/bash
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
kubectl port-forward --address 0.0.0.0 -n kubernetes-dashboard service/kubernetes-dashboard 443:443

View File

@ -0,0 +1,5 @@
#!/bin/sh
export PATH=/kind:$PATH
exec "$@"

View File

@ -0,0 +1,7 @@
#!/bin/sh
# This script patches the kubeconfig generated by Kind in order to access the cluster container via this container
echo "Patching Kubeconfig to target Kube container without link"
CONTROL_PLANE_IP=`docker inspect -f '{{(index .NetworkSettings.Networks "authelia_authelianet").IPAddress}}' kind-control-plane`
sed -i "s/127.0.0.1:.*/$CONTROL_PLANE_IP:6443/" `kind get kubeconfig-path --name="kind"`

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
openldap-admin:
image: osixia/phpldapadmin:0.6.11

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
openldap:
image: clems4ever/openldap

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
mongo:
image: mongo:3.4

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
nginx-backend:
image: authelia-example-backend

View File

@ -1,18 +0,0 @@
version: '2'
services:
kubernetes:
image: nginx:alpine
volumes:
- ./example/compose/nginx/kubernetes/nginx.conf:/etc/nginx/nginx.conf
- ./example/compose/nginx/kubernetes/ssl:/etc/ssl
networks:
authelianet:
aliases:
- public.example.com
- secure.example.com
- login.example.com
- admin.example.com
- dev.example.com
- mail.example.com
# Set the IP to be able to query on port 443
ipv4_address: 192.168.240.100

View File

@ -1,30 +0,0 @@
#
# You can find a documented example of configuration in ./docs/proxies/nginx.md.
#
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 8080 ssl;
resolver 127.0.0.11 ipv6=off;
ssl_certificate /etc/ssl/server.cert;
ssl_certificate_key /etc/ssl/server.key;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN";
location / {
proxy_set_header Host $http_host;
proxy_pass https://192.168.240.1:8080;
}
}
}

View File

@ -1,19 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDEzCCAfugAwIBAgIUJZXxXExVQPJhc8TnlD+uAAYHlvwwDQYJKoZIhvcNAQEL
BQAwGDEWMBQGA1UEAwwNKi5leGFtcGxlLmNvbTAgFw0xOTA5MjYyMDAwMTBaGA8y
MTE5MDkwMjIwMDAxMFowGDEWMBQGA1UEAwwNKi5leGFtcGxlLmNvbTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3DFTAdrxG6iOj5UjSeB5lMjMQQyeYm
OxUvswwwBzmQYPUt0inAJ9QmXJ8i9Fbye8HHYUeqE5zsEfeHir81MiWfhi9oUzJt
u3bmxGLDXYaApejd18hBKITX6MYogmK2lWrl/F9zPYxc2xM/fqWnGg2xwdrMmida
hZjDUfh0rtoz8zqOzJaiiDoFMwNO+NTGmDbeOwBFYOF1OTkS3aJWwJCLZmINUG8h
Z3YPR+SL8CpGGl0xhJYAwXD1AtMlYwAteTILqrqvo2XkGsvuj0mx0w/D0DDpC48g
oSNsRIVTW3Ql3uu+kXDFtkf4I63Ctt85rZk1kX3QtYmS0pRzvmyY/b0CAwEAAaNT
MFEwHQYDVR0OBBYEFMTozK79Kp813+8TstjXRFw1MTE5MB8GA1UdIwQYMBaAFMTo
zK79Kp813+8TstjXRFw1MTE5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBALf1bJf3qF3m54+q98E6lSE+34yi/rVdzB9reAW1QzvvqdJRtsfjt39R
SznsbmrvCfK4SLyOj9Uhd8Z6bASPPNsUux1XAGN4AqaGmlYI8b7j3LhKCdRBZQ0I
zWgPhocyWwp5VkFe68zR06NHme/2B6eBRFsdd/69DIOv9YnEGUHk3A/9v1zvolt9
krW57Oz63zWGYXmtPPTD8of/Ya6NKqwonVx1MUQ5QzqH3WySYhRsIYqwUEXm9jt5
GEM3Nx0phEltaOLXa71nqS/Rhg/5Kod0cFaNoSKb6N93I8bqKKTK0m5wMJ5Fisrm
Pw5+AIar7RT5gHU2DD2/OTb9bXXww8I=
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvcMVMB2vEbqI6PlSNJ4HmUyMxBDJ5iY7FS+zDDAHOZBg9S3S
KcAn1CZcnyL0VvJ7wcdhR6oTnOwR94eKvzUyJZ+GL2hTMm27dubEYsNdhoCl6N3X
yEEohNfoxiiCYraVauX8X3M9jFzbEz9+pacaDbHB2syaJ1qFmMNR+HSu2jPzOo7M
lqKIOgUzA0741MaYNt47AEVg4XU5ORLdolbAkItmYg1QbyFndg9H5IvwKkYaXTGE
lgDBcPUC0yVjAC15Mguquq+jZeQay+6PSbHTD8PQMOkLjyChI2xEhVNbdCXe676R
cMW2R/gjrcK23zmtmTWRfdC1iZLSlHO+bJj9vQIDAQABAoIBAEZvkP/JJOCJwqPn
V3IcbmmilmV4bdi1vByDFgyiDyx4wOSA24+PubjvfFW9XcCgRPuKjDtTj/AhWBHv
B7stfa2lZuNV7/u562mZArA+IAr62Zp0LdIxDV8x3T8gbjVB3HhPYbv0RJZDKTYd
zV6jhfIrVu9mHpoY6ZnodhapCPYIyk/d49KBIHZuAc25CUjMXgTeaVtf0c996036
UxW6ef33wAOJAvW0RCvbXAJfmBeEq2qQlkjTIlpYx71fhZWexHifi8Ouv3Zonc+1
/P2Adq5uzYVBT92f9RKHg9QxxNzVrLjSMaxyvUtWQCAQfW0tFIRdqBGsHYsQrFtI
F4yzv8ECgYEA7ntpyN9HD9Z9lYQzPCR73sFCLM+ID99aVij0wHuxK97bkSyyvkLd
7MyTaym3lg1UEqWNWBCLvFULZx7F0Ah6qCzD4ymm3Bj/ADpWWPgljBI0AFml+HHs
hcATmXUrj5QbLyhiP2gmJjajp1o/rgATx6ED66seSynD6JOH8wUhhZUCgYEAy7OA
06PF8GfseNsTqlDjNF0K7lOqd21S0prdwrsJLiVzUlfMM25MLE0XLDUutCnRheeh
IlcuDoBsVTxz6rkvFGD74N+pgXlN4CicsBq5ofK060PbqCQhSII3fmHobrZ9Cr75
HmBjAxHx998SKaAAGbBbcYGUAp521i1pH5CEPYkCgYEAkUd1Zf0+2RMdZhwm6hh/
rW+l1I6IoMK70YkZsLipccRNld7Y9LbfYwYtODcts6di9AkOVfueZJiaXbONZfIE
Zrb+jkAteh9wGL9xIrnohbABJcV3Kiaco84jInUSmGDtPokncOENfHIEuEpuSJ2b
bx1TuhmAVuGWivR0+ULC7RECgYEAgS0cDRpWc9Xzh9Cl7+PLsXEvdWNpPsL9OsEq
0Ep7z9+/+f/jZtoTRCS/BTHUpDvAuwHglT5j3p5iFMt5VuiIiovWLwynGYwrbnNS
qfrIrYKUaH1n1oDS+oBZYLQGCe9/7EifAjxtjYzbvSyg//SPG7tSwfBCREbpZXj2
qSWkNsECgYA/mCDzCTlrrWPuiepo6kTmN+4TnFA+hJI6NccDVQ+jvbqEdoJ4SW4L
zqfZSZRFJMNpSgIqkQNRPJqMP0jQ5KRtJrjMWBnYxktwKz9fDg2R2MxdFgMF2LH2
HEMMhFHlv8NDjVOXh1KwRoltNGVWYsSrD9wKU9GhRCEfmNCGrvBcEg==
-----END RSA PRIVATE KEY-----

View File

@ -1,2 +0,0 @@
nginx.conf

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
nginx-portal:
image: nginx:alpine
@ -13,5 +13,6 @@ services:
- public.example.com
- secure.example.com
- login.example.com
- duo.example.com
# Set the IP to be able to query on port 443
ipv4_address: 192.168.240.100

View File

@ -1,8 +1,6 @@
#
# You can find a documented example of configuration in ./docs/proxies/nginx.md.
#
worker_processes 1;
events {
@ -10,57 +8,13 @@ events {
}
http {
<% if (production) { %>
server {
listen 8080 ssl;
server_name login.example.com;
resolver 127.0.0.11 ipv6=off;
set $backend_endpoint <%= authelia_backend %>;
ssl_certificate /etc/ssl/server.cert;
ssl_certificate_key /etc/ssl/server.key;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN";
# Serves the portal application.
location / {
proxy_pass $backend_endpoint;
}
location /static {
proxy_pass $backend_endpoint;
}
# Serve the backend API for the portal.
location /api {
proxy_set_header X-Real-IP $remote_addr;
# Required by Authelia because "trust proxy" option is used.
# See https://expressjs.com/en/guide/behind-proxies.html
proxy_set_header X-Forwarded-Proto $scheme;
# Required by Authelia to build correct links for identity validation.
proxy_set_header X-Forwarded-Host $http_host;
# Needed for network ACLs to work. It appends the IP of the client to the list of IPs
# and allows Authelia to use it to match the network-based ACLs.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_intercept_errors on;
proxy_pass $backend_endpoint;
}
}
<% } else { %>
server {
listen 8080 ssl;
server_name login.example.com;
resolver 127.0.0.11 ipv6=off;
set $frontend_endpoint http://192.168.240.1:3000;
set $backend_endpoint <%= authelia_backend %>;
set $frontend_endpoint http://authelia-frontend:3000;
set $backend_endpoint http://authelia-backend:9091;
ssl_certificate /etc/ssl/server.cert;
ssl_certificate_key /etc/ssl/server.key;
@ -94,11 +48,11 @@ http {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host "127.0.0.1";
proxy_pass $frontend_endpoint;
}
}
<% } %>
# Serves the home page.
server {
@ -131,7 +85,7 @@ http {
mx1.mail.example.com mx2.mail.example.com;
resolver 127.0.0.11 ipv6=off;
set $upstream_verify <%= authelia_backend %>/api/verify;
set $upstream_verify http://authelia-backend:9091/api/verify;
set $upstream_endpoint http://nginx-backend;
set $upstream_headers http://httpbin:8000/headers;

View File

@ -1,40 +0,0 @@
#!/usr/bin/env node
const ejs = require('ejs');
const fs = require('fs');
const program = require('commander');
let backend;
program
.version('0.1.0')
.option('-p, --production', 'Render template for production.')
.arguments('[backend]')
.action((backendArg) => backend = backendArg)
.parse(process.argv)
const options = {
production: false,
}
if (!backend) {
backend = 'http://192.168.240.1:9091'
}
if (program.production) {
options['production'] = true;
}
options['authelia_backend'] = backend;
const templatePath = __dirname + '/nginx.conf.ejs';
const outputPath = __dirname + '/nginx.conf';
html = ejs.renderFile(templatePath, options, (err, conf) => {
try {
var fd = fs.openSync(outputPath, 'w');
fs.writeFileSync(fd, conf);
} catch (e) {
fs.writeFileSync(outputPath, conf);
}
});

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
redis:
image: redis:4.0-alpine

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
smtp:
image: schickling/mailcatcher

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
# Simulates client 1.
client-1:

View File

@ -1 +0,0 @@
traefik.toml

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
traefik:
image: traefik:v1.7.9-alpine
@ -11,4 +11,4 @@ services:
networks:
authelianet:
# Set the IP to be able to query on port 443
ipv4_address: 192.168.240.100
ipv4_address: 192.168.240.100

View File

@ -1,40 +0,0 @@
#!/usr/bin/env node
const ejs = require('ejs');
const fs = require('fs');
const program = require('commander');
let backend;
program
.version('0.1.0')
.option('-p, --production', 'Render template for production.')
.arguments('[backend]')
.action((backendArg) => backend = backendArg)
.parse(process.argv)
const options = {
production: false,
}
if (!backend) {
backend = 'http://192.168.240.1:9091'
}
if (program.production) {
options['production'] = true;
}
options['authelia_backend'] = backend;
const templatePath = __dirname + '/traefik.toml.ejs';
const outputPath = __dirname + '/traefik.toml';
html = ejs.renderFile(templatePath, options, (err, conf) => {
try {
var fd = fs.openSync(outputPath, 'w');
fs.writeFileSync(fd, conf);
} catch (e) {
fs.writeFileSync(outputPath, conf);
}
});

View File

@ -17,10 +17,6 @@ logLevel = "DEBUG"
[file]
# TODO(c.michaud): remove this template by providing a proxy doing
# the routing depending on the mode (production or dev)
<% if (!production) { %>
[frontends]
[frontends.authelia_api]
backend = "authelia_api_backend"
@ -35,27 +31,11 @@ logLevel = "DEBUG"
[backends]
[backends.authelia_api_backend]
[backends.authelia_api_backend.servers.server]
url = "http://192.168.240.1:9091"
url = "http://authelia-backend:9091"
[backends.authelia_front_backend]
[backends.authelia_front_backend.servers.server]
url = "http://192.168.240.1:3000"
<% } else { %>
[frontends]
[frontends.authelia]
backend = "authelia_backend"
[frontends.authelia.routes.route0]
rule = "Host:login.example.com"
[backends]
[backends.authelia_backend]
[backends.authelia_backend.servers.server]
url = "http://192.168.240.1:9091"
<% } %>
url = "http://authelia-frontend:3000"
[api]
# This is exposed via a subdomain and a proxy

View File

@ -1,17 +1,20 @@
---
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app
namespace: authelia
labels:
k8s-app: test-app
app: test-app
spec:
replicas: 1
selector:
matchLabels:
app: test-app
template:
metadata:
labels:
k8s-app: test-app
app: test-app
spec:
containers:
- name: test-app
@ -28,10 +31,10 @@ metadata:
name: test-app-service
namespace: authelia
labels:
k8s-app: test-app
app: test-app
spec:
selector:
k8s-app: test-app
app: test-app
ports:
- port: 80
name: http

View File

@ -1,5 +1,5 @@
---
apiVersion: apps/v1beta2
apiVersion: apps/v1
kind: Deployment
metadata:
name: authelia

View File

@ -1,17 +0,0 @@
-----BEGIN CERTIFICATE-----
MIICvjCCAaYCCQCJYt0VhOelKjANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDDBZs
b2dpbi5rdWJlLmV4YW1wbGUuY29tMB4XDTE4MDMwNDE1MTQzMVoXDTE5MDMwNDE1
MTQzMVowITEfMB0GA1UEAwwWbG9naW4ua3ViZS5leGFtcGxlLmNvbTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIlUUppqDLXQCey+OqC4YIhsZFhus0S
0OcNKBhMcUpKdaqtMf8n8mUtGCByUTf+LMBOyv/WrdcGH5pwlylyERPfDsUFF+5W
LjhHGjMZVKWHOadb25HpO9IZUyyC+5PepfrHlxS5EhTQXymA7yjaXSizfH0uF9Le
mF/RoqArtDfq/2/golcX5YkRt6FwbGrypHG0MuREyMN7H+XmKyC4Cwc1ECbROrWv
C5491Fvw4fW0zWa6M1z56kzA+X7ZleiemiY0vm7hzlm8qztd449pJzweb/Gl2r7n
LdFK+H2jbkn07Z//rwlm8Wlwtb3GLOTgisNv5jALpCDdgiSmUc+G+f0CAwEAATAN
BgkqhkiG9w0BAQsFAAOCAQEAUm+gRqlUIGK3UKA+z1Si2EpFeOpSkfBbMjwWQAea
yEY+XtUxQSWmbTx6Cp1miVwSp4ldd0nYVCpesv94FoI3ahktZGafcfviYgyCNPXl
QBREQ3NU9TBLHOmCygL8JlzKLtKABKTiGsDahPmBaMogCbvswFqccZ1EtLRcrI48
FFGS7K4ku561AK+WqFS8yxFKcudJSfmLeEZ0uNazEbh8kIgA5dXtapv6lBhPQ6nN
MPZO321PWGysvj3RXDagYQOPBLX7NhnoFDCoeJKbPQ9lTLOAI0aQnpNoFZnoiWc3
NNLboVSTPQ3jyumAAm7tXS/KWI5Samfp8Cgu7uqhPLdHYg==
-----END CERTIFICATE-----

View File

@ -1,15 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICZjCCAU4CAQAwITEfMB0GA1UEAwwWbG9naW4ua3ViZS5leGFtcGxlLmNvbTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIlUUppqDLXQCey+OqC4YIh
sZFhus0S0OcNKBhMcUpKdaqtMf8n8mUtGCByUTf+LMBOyv/WrdcGH5pwlylyERPf
DsUFF+5WLjhHGjMZVKWHOadb25HpO9IZUyyC+5PepfrHlxS5EhTQXymA7yjaXSiz
fH0uF9LemF/RoqArtDfq/2/golcX5YkRt6FwbGrypHG0MuREyMN7H+XmKyC4Cwc1
ECbROrWvC5491Fvw4fW0zWa6M1z56kzA+X7ZleiemiY0vm7hzlm8qztd449pJzwe
b/Gl2r7nLdFK+H2jbkn07Z//rwlm8Wlwtb3GLOTgisNv5jALpCDdgiSmUc+G+f0C
AwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCHO3wzf1jCOcTmo5NBnCendtEb/IAl
aTBCW3b2+QDRQBGgpQb+JeDjHjIzp5FgzzJVF0XTA8H8jmR56lPTXNlWESzUh1oV
on8QcbPi97nuhIEJNfk7K6gAiK11fULBoNUgI7PsRvAneo2PsCEHGtNsdoU4Ii7A
CuUtKeeZCdbxVM2HradSJ9vvxRmOuIfsQJbUaH0F/Z3A0l0UQbp1AUOWFcJ6XDkX
SgDkMCkXJV53SlwGZm8q6Hj8zwP7Tlk6Nkzcn3ZMDB76o92QSVoi1V07NrvRUvcc
2/eekJBWfpzy1LkaovYGBow4ose8V5nMyH9feXlReCVk2aHYTYbEmQRj
-----END CERTIFICATE REQUEST-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwiVRSmmoMtdAJ7L46oLhgiGxkWG6zRLQ5w0oGExxSkp1qq0x
/yfyZS0YIHJRN/4swE7K/9at1wYfmnCXKXIRE98OxQUX7lYuOEcaMxlUpYc5p1vb
kek70hlTLIL7k96l+seXFLkSFNBfKYDvKNpdKLN8fS4X0t6YX9GioCu0N+r/b+Ci
VxfliRG3oXBsavKkcbQy5ETIw3sf5eYrILgLBzUQJtE6ta8Lnj3UW/Dh9bTNZroz
XPnqTMD5ftmV6J6aJjS+buHOWbyrO13jj2knPB5v8aXavuct0Ur4faNuSfTtn/+v
CWbxaXC1vcYs5OCKw2/mMAukIN2CJKZRz4b5/QIDAQABAoIBAQCkTwLqcFs6k/Om
5ZBGoPgLs0pdmRGIR7lnIjphvihPUI8fIK9km8FIoY5+v2E/ey0SoFyrg1vi1Drg
8RLtr60GXUxZsALd4jABzyM8Rd7erIA9xL8iUPsgx/Adhsk2D0P35v1VO4Ay/1ra
fFVsBMq9DJJ6Ow1MmLjqtzfkSLigbRRSPwaS081oW570cg9ABc1Cpp9sdLjG2Il0
Eyet0qe0fiJAOlnE+tMRls9AoGYLG61msb1OhkpKfaNdw6IolkSGQZDqqsf1cSE3
I7ypsE0LLtDeCU/jsUMjDHBwerqTANUHO5Y4PZ3hSJN55p/IGEiUeAMYs+dqtFx8
xc/KfV2BAoGBAP+2nR73QjWdqJ0A4IdRq811eZM+NTWbobKRSay+T3Ve8QcRqc41
YXJYqRhX23me3p9CxHDMVoXYtWS1nlXnsOxk60idffEIf5tbjzEYi1dIdLoCfbVW
dZS1ZsZh4GZ3If8e78R+9IBQ6+SFvsVocRXpkf6VHp6jB3mXH0XCyNXdAoGBAMJd
CORqmdrmCbfZnn7G3cZ7kTS05inMkj/svtDb+tkcy2x+pfL9y+SfeAf+o5AGl6pN
CsiiGJTVj/Wtic572zdT198UFyWjDrgYUMNzvL9430hnZkySF/E8f1XHD8Sb4P65
CVGJeVKuEHTXcas9F3VYln/87WGDVrtVowO408KhAoGACFiSej9BtvRFW5J6wY/l
1pfd9vNR00UYGvbo+61edIs7vKpT63oMiynfov7DGA4aYAJS3QeeT1IKYZYX69/b
A2wrzbvuL17Co3RykPynF5syzBtmtPN0dP0StKjfJRkAUA5XbwdhvYpmmJfQ6SqG
fluYO0HstOrHRK2tBJ7d5TUCgYBt9mDPihgdpkQdRfvL0gsq/kH6xdXqFBkyHWkf
lTVonEfizAxrW3d9k1M/gqtbEr+/0/Kj7EFoAyN9ZX8v2Rb/SGo7hYxK+OOc9/TJ
f7NryKDav9U6wPTWwNlx2DttiptSwbEp9lMzmdMpp7JhpSCefU44fwp2Pu5U8nBV
7L2xwQKBgHln1Y4EZ9SQDA0jFiSUNoCkkUJFox8752FsPolCna3GmBAYJn8+Oumj
VbLPJvJxHmXMn+JN+rxxFve/DxV1TJqsan5F7i5xp0Ck4rm+TU0ZxvHW75yNG8ER
bNGkvo1dme3fh8YETH6sqePTtbJ04hMfNhn1/iu89s6+ft4cqnpk
-----END RSA PRIVATE KEY-----

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
start_authelia() {
kubectl create configmap authelia-config --namespace=authelia --from-file=authelia/configs/config.yml

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
start_apps() {
# Create TLS certificate and key for HTTPS termination

View File

@ -1,19 +1,21 @@
---
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: authelia
labels:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
spec:
replicas: 1
revisionHistoryLimit: 0
selector:
matchLabels:
app: nginx-ingress-controller
template:
metadata:
labels:
k8s-app: nginx-ingress-controller
name: nginx-ingress-controller
app: nginx-ingress-controller
annotations:
prometheus.io/port: '10254'
prometheus.io/scrape: 'true'

View File

@ -4,7 +4,7 @@ metadata:
name: nginx-ingress-controller-serviceaccount
namespace: authelia
labels:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
---
apiVersion: rbac.authorization.k8s.io/v1beta1
@ -12,7 +12,7 @@ kind: ClusterRole
metadata:
name: nginx-ingress-controller-clusterrole
labels:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
rules:
- apiGroups:
- ""
@ -68,7 +68,7 @@ metadata:
name: nginx-ingress-controller-role
namespace: authelia
labels:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
rules:
- apiGroups:
- ""
@ -112,7 +112,7 @@ metadata:
name: nginx-ingress-controller-role-nisa-binding
namespace: authelia
labels:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
@ -128,7 +128,7 @@ kind: ClusterRoleBinding
metadata:
name: nginx-ingress-controller-clusterrole-nisa-binding
labels:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole

View File

@ -5,10 +5,10 @@ metadata:
name: nginx-ingress-controller-service
namespace: authelia
labels:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
spec:
selector:
k8s-app: nginx-ingress-controller
app: nginx-ingress-controller
type: NodePort
ports:
- port: 80

View File

@ -1,5 +1,5 @@
---
apiVersion: apps/v1beta2
apiVersion: apps/v1
kind: Deployment
metadata:
name: ldap

View File

@ -1,5 +1,5 @@
---
apiVersion: apps/v1beta2
apiVersion: apps/v1
kind: Deployment
metadata:
name: mailcatcher

View File

@ -1,5 +1,5 @@
---
apiVersion: apps/v1beta2
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo

View File

@ -1,5 +1,5 @@
---
apiVersion: apps/v1beta2
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis

View File

@ -1,5 +1,5 @@
---
apiVersion: apps/v1beta2
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app1

7
go.mod
View File

@ -5,6 +5,7 @@ go 1.13
require (
github.com/Workiva/go-datastructures v1.0.50
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/cespare/reflex v0.2.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74
github.com/fasthttp/router v0.5.2
@ -12,12 +13,18 @@ require (
github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/mock v1.3.1
github.com/golang/snappy v0.0.1 // indirect
github.com/google/martian v2.1.0+incompatible
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kr/pty v1.1.8 // indirect
github.com/mattn/go-sqlite3 v1.11.0
github.com/ogier/pflag v0.0.1 // indirect
github.com/otiai10/copy v1.0.2
github.com/pquerna/otp v1.2.0
github.com/simia-tech/crypt v0.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/tebeka/selenium v0.9.9
github.com/tstranex/u2f v1.0.0
github.com/valyala/fasthttp v1.6.0
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect

132
go.sum
View File

@ -1,16 +1,33 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.41.0/go.mod h1:OauMR7DV8fzvZIl2qg6rkaIhD/vmgk4iwEw/h6ercmg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e h1:4ZrkT/RzpnROylmoQL57iVUL57wGKTR5O6KpVnbm2tA=
github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k=
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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
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/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
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/cespare/reflex v0.2.0 h1:6d9WpWJseKjJvZEevKP7Pk42nPx2+BUTqmhNk8wZPwM=
github.com/cespare/reflex v0.2.0/go.mod h1:ooqOLJ4algvHP/oYvKWfWJ9tFUzCLDk5qkIJduMYrgI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
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/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
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=
@ -22,31 +39,69 @@ 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 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
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=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
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/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-github/v27 v27.0.4/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
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=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
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/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
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 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/ogier/pflag v0.0.1 h1:RW6JSWSu/RkSatfcLtogGfFgpim5p7ARQ10ECk5O750=
github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc=
github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
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=
@ -63,13 +118,17 @@ github.com/simia-tech/crypt v0.2.0 h1:cU8qdqUYNuEFKSMq15yaB2aI1aC5vrn6dFOonT6Kg6
github.com/simia-tech/crypt v0.2.0/go.mod h1:DMwvjPTzsiHrjqHVW5HvIbF4vUUzMCYDKVLsPWmLdTo=
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 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
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 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
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 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
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=
@ -78,6 +137,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tebeka/selenium v0.9.9 h1:cNziB+etNgyH/7KlNI7RMC1ua5aH1+5wUlFQyzeMh+w=
github.com/tebeka/selenium v0.9.9/go.mod h1:5Fr8+pUvU6B1OiPfkdCKdXZyr5znvVkxuPd0NOdZCQc=
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=
@ -95,22 +156,89 @@ github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0
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=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
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/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116161606-93218def8b18/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -119,3 +247,7 @@ gopkg.in/ldap.v3 v3.1.0/go.mod h1:dQjCc0R0kfyFjIlWNMH1DORwUASZyDxo2Ry1B51dXaQ=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@ -43,6 +43,10 @@ func (n *SMTPNotifier) unauthenticatedSend(recipient string, msg string) error {
// Connect to the remote SMTP server.
c, err := smtp.Dial(n.address)
if err != nil {
return err
}
// Set the sender and recipient first
if err := c.Mail(n.sender); err != nil {
return err

2198
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,32 +32,23 @@
},
"dependencies": {},
"devDependencies": {
"@types/chokidar": "^1.7.5",
"@types/commander": "^2.12.2",
"@types/mocha": "^5.2.6",
"@types/mockdate": "^2.0.0",
"@types/node-fetch": "^2.1.4",
"@types/query-string": "^5.1.0",
"@types/redis": "^2.8.14",
"@types/request": "^2.0.5",
"@types/request-promise": "^4.1.38",
"@types/selenium-webdriver": "^3.0.16",
"@types/speakeasy": "^2.0.2",
"chokidar": "^2.0.4",
"chromedriver": "^77.0.0",
"commander": "^2.19.0",
"ejs": "^2.6.2",
"mocha": "^6.1.4",
"mockdate": "^2.0.1",
"node-fetch": "^2.3.0",
"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",
"speakeasy": "^2.0.0",
"tree-kill": "^1.2.1",
"ts-node": "^6.0.1",
"tslint": "^5.2.0",
"typescript": "^2.9.2"

View File

@ -4,16 +4,13 @@ import (
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/clems4ever/authelia/models"
"github.com/stretchr/testify/assert"
"github.com/clems4ever/authelia/configuration/schema"
"github.com/clems4ever/authelia/mocks"
"github.com/clems4ever/authelia/models"
"github.com/clems4ever/authelia/regulation"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
type RegulatorSuite struct {

View File

@ -1,8 +0,0 @@
var ListSuites = require('./utils/ListSuites');
const suites = ListSuites();
suites.forEach(async (suite: string) => {
var { teardown } = require(`../test/suites/${suite}/environment`);;
teardown().catch((err: Error) => console.error(err));
});

View File

@ -1,80 +0,0 @@
import { exec } from './utils/exec';
const userSuite = process.argv[2];
const command = process.argv[3]; // The command to run once the env is up.
var { setup, setup_timeout, teardown, teardown_timeout } = require(`../test/suites/${userSuite}/environment`);
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
let teardownInProgress = false;
async function block() {
while (true) {
await sleep(10000);
}
}
async function blockOrRun(cmd: string | null) {
if (cmd) {
await exec(cmd);
} else {
await block();
}
}
process.on('SIGINT', function() {
if (teardownInProgress) return;
teardownInProgress = true;
stop()
.then(() => process.exit(0))
.catch(() => process.exit(1));
});
async function stop() {
const timer = setTimeout(() => {
console.error('Teardown timed out...');
process.exit(1);
}, teardown_timeout);
try {
console.log('>>> Tearing down environment <<<');
await teardown();
clearTimeout(timer);
} catch(err) {
console.error(err);
throw err;
}
}
async function start() {
const timer = setTimeout(async () => {
console.error('Setup timed out...');
try {
await teardown();
} catch(err) {
process.exit(1)
}
}, setup_timeout);
console.log('>>> Setting up environment <<<');
try {
await setup();
await sleep(200);
clearTimeout(timer);
await blockOrRun(command);
if (!teardownInProgress) {
await stop();
process.exit(0);
}
}
catch (err) {
console.error(err);
await stop();
process.exit(1);
}
}
start();

View File

@ -0,0 +1,10 @@
var { setup } = require(`../test/suites/${process.argv[2]}/environment`);
(async function() {
try {
await setup();
} catch(err) {
console.error(err);
process.exit(1);
}
})()

View File

@ -0,0 +1,10 @@
var { teardown } = require(`../test/suites/${process.argv[2]}/environment`);
(async function() {
try {
await teardown();
} catch(err) {
console.error(err);
process.exit(1);
}
})()

View File

@ -12,7 +12,7 @@ jwt_secret: very_important_secret
authentication_backend:
file:
path: ./test/suites/basic/users_database.test.yml
path: users.yml
session:
secret: unsecure_session_secret
@ -91,7 +91,7 @@ regulation:
notifier:
# Use a SMTP server for sending notifications
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -10,7 +10,7 @@ jwt_secret: unsecure_secret
authentication_backend:
file:
path: ./test/suites/basic/users_database.test.yml
path: users.yml
session:
secret: unsecure_session_secret
@ -38,7 +38,7 @@ access_control:
notifier:
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -10,7 +10,7 @@ jwt_secret: very_important_secret
authentication_backend:
file:
path: ./test/suites/basic/users_database.test.yml
path: users.yml
session:
secret: unsecure_session_secret
@ -95,7 +95,7 @@ regulation:
notifier:
# Use a SMTP server for sending notifications
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -44,7 +44,7 @@ authentication_backend:
# production.
ldap:
# The url of the ldap server
url: ldap://127.0.0.1
url: ldap://openldap
# The base dn for every entries
base_dn: dc=example,dc=com
@ -87,7 +87,6 @@ authentication_backend:
## file:
## path: ./users_database.yml
# Access Control
#
# Access control is a list of rules defining the authorizations applied for one
@ -139,43 +138,42 @@ access_control:
# Rules applied to 'admin' group
- domain: mx2.mail.example.com
subject: 'group:admin'
subject: "group:admin"
policy: deny
# Rules applied to user 'john'
- domain: '*.example.com'
subject: 'user:john'
- domain: "*.example.com"
subject: "user:john"
policy: two_factor
- domain: '*.example.com'
subject: 'group:admin'
- domain: "*.example.com"
subject: "group:admin"
policy: two_factor
# Rules applied to 'dev' group
- domain: dev.example.com
resources:
- '^/groups/dev/.*$'
subject: 'group:dev'
- "^/groups/dev/.*$"
subject: "group:dev"
policy: two_factor
# Rules applied to user 'harry'
- domain: dev.example.com
resources:
- '^/users/harry/.*$'
subject: 'user:harry'
- "^/users/harry/.*$"
subject: "user:harry"
policy: two_factor
# Rules applied to user 'bob'
- domain: '*.mail.example.com'
subject: 'user:bob'
- domain: "*.mail.example.com"
subject: "user:bob"
policy: two_factor
- domain: 'dev.example.com'
- domain: "dev.example.com"
resources:
- '^/users/bob/.*$'
subject: 'user:bob'
- "^/users/bob/.*$"
subject: "user:bob"
policy: two_factor
# Configuration of session cookies
#
# The session cookies identify the user once logged in.
@ -199,7 +197,7 @@ session:
# The redis connection details
redis:
host: 127.0.0.1
host: redis
port: 6379
password: authelia
@ -230,7 +228,7 @@ storage:
# Settings to connect to mongo server
mongo:
url: mongodb://127.0.0.1
url: mongodb://mongo
database: authelia
auth:
username: authelia
@ -244,6 +242,6 @@ storage:
notifier:
# Use a SMTP server for sending notifications
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -13,7 +13,7 @@ jwt_secret: very_important_secret
authentication_backend:
ldap:
# The url of the ldap server
url: 127.0.0.1:389
url: ldap://openldap
# The base dn for every entries
base_dn: dc=example,dc=com
@ -66,22 +66,21 @@ totp:
access_control:
default_policy: deny
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
- 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
# Configuration of the authentication regulation mechanism.
regulation:
regulation:
# Set it to 0 to disable max_retries.
max_retries: 3
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
find_time: 300
# The length of time before a banned user can login again.
@ -90,7 +89,6 @@ regulation:
notifier:
# Use a SMTP server for sending notifications
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -12,7 +12,7 @@ jwt_secret: very_important_secret
authentication_backend:
file:
path: ./test/suites/mongo/users_database.test.yml
path: users.yml
session:
secret: unsecure_session_secret
@ -23,7 +23,7 @@ session:
# Configuration of the storage backend used to store data and secrets. i.e. totp data
storage:
mongo:
url: mongodb://127.0.0.1
url: mongodb://mongo
database: authelia
auth:
username: authelia
@ -39,22 +39,21 @@ totp:
access_control:
default_policy: deny
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
- 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
# Configuration of the authentication regulation mechanism.
regulation:
regulation:
# Set it to 0 to disable max_retries.
max_retries: 3
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
find_time: 8
# The length of time before a banned user can login again.
@ -63,7 +62,6 @@ regulation:
notifier:
# Use a SMTP server for sending notifications
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -10,7 +10,7 @@ jwt_secret: unsecure_password
authentication_backend:
file:
path: ./test/suites/basic/users_database.test.yml
path: users.yml
session:
secret: unsecure_session_secret
@ -25,7 +25,7 @@ storage:
# Access Control
#
# Access control is a set of rules you can use to restrict user access to certain
# Access control is a set of rules you can use to restrict user access to certain
# resources.
access_control:
default_policy: deny
@ -44,12 +44,11 @@ access_control:
- domain: secure.example.com
policy: two_factor
# Configuration of the authentication regulation mechanism.
regulation:
regulation:
# Set it to 0 to disable max_retries.
max_retries: 3
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
find_time: 300
# The length of time before a banned user can login again.
ban_time: 900
@ -57,7 +56,6 @@ regulation:
notifier:
# Use a SMTP server for sending notifications
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -12,7 +12,7 @@ default_redirection_url: https://home.example.com:8080/
authentication_backend:
file:
path: ./test/suites/short-timeouts/users_database.test.yml
path: users.yml
session:
secret: unsecure_session_secret
@ -34,7 +34,7 @@ totp:
# Access Control
#
# Access control is a set of rules you can use to restrict user access to certain
# Access control is a set of rules you can use to restrict user access to certain
# resources.
access_control:
# Default policy can either be `bypass`, `one_factor`, `two_factor` or `deny`.
@ -44,39 +44,38 @@ access_control:
- domain: singlefactor.example.com
policy: one_factor
- domain: '*.example.com'
- domain: "*.example.com"
subject: "group:admins"
policy: two_factor
- domain: dev.example.com
resources:
- '^/users/john/.*$'
- "^/users/john/.*$"
subject: "user:john"
policy: two_factor
- domain: dev.example.com
resources:
- '^/users/harry/.*$'
- "^/users/harry/.*$"
subject: "user:harry"
policy: two_factor
- domain: '*.mail.example.com'
- domain: "*.mail.example.com"
subject: "user:bob"
policy: two_factor
- domain: dev.example.com
resources:
- '^/users/bob/.*$'
- "^/users/bob/.*$"
subject: "user:bob"
policy: two_factor
# Configuration of the authentication regulation mechanism.
regulation:
regulation:
# Set it to 0 to disable max_retries.
max_retries: 3
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
find_time: 3
# The length of time before a banned user can login again.
@ -94,16 +93,15 @@ notifier:
# filename: /tmp/authelia/notification.txt
# Use your email account to send the notifications. You can use an app password.
# List of valid services can be found here: https://nodemailer.com/smtp/well-known/
# List of valid services can be found here: https://nodemailer.com/smtp/well-known/
## email:
## username: user@example.com
## password: yourpassword
## sender: admin@example.com
## service: gmail
# Use a SMTP server for sending notifications
smtp:
host: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

View File

@ -0,0 +1,83 @@
###############################################################
# Authelia minimal configuration #
###############################################################
port: 9091
logs_level: debug
default_redirection_url: https://home.example.com:8080/
jwt_secret: very_important_secret
authentication_backend:
file:
path: users.yml
session:
secret: unsecure_session_secret
domain: example.com
expiration: 3600 # 1 hour
inactivity: 300 # 5 minutes
storage:
local:
path: db.sqlite3
totp:
issuer: example.com
access_control:
default_policy: deny
rules:
- domain: singlefactor.example.com
policy: one_factor
- domain: public.example.com
policy: bypass
- domain: secure.example.com
policy: two_factor
- domain: '*.example.com'
subject: "group:admins"
policy: two_factor
- domain: dev.example.com
resources:
- '^/users/john/.*$'
subject: "user:john"
policy: two_factor
- domain: dev.example.com
resources:
- '^/users/harry/.*$'
subject: "user:harry"
policy: two_factor
- domain: '*.mail.example.com'
subject: "user:bob"
policy: two_factor
- domain: dev.example.com
resources:
- '^/users/bob/.*$'
subject: "user:bob"
policy: two_factor
regulation:
# Set it to 0 to disable max_retries.
max_retries: 3
# The user is banned if the authenticaction failed `max_retries` times in a `find_time` seconds window.
find_time: 300
# The length of time before a banned user can login again.
ban_time: 900
notifier:
smtp:
host: smtp
port: 1025
sender: admin@example.com

View File

@ -0,0 +1,28 @@
###############################################################
# Users Database #
###############################################################
# This file can be used if you do not have an LDAP set up.
users:
john:
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
email: john.doe@authelia.com
groups:
- admins
- dev
harry:
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
email: harry.potter@authelia.com
groups: []
bob:
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
email: bob.dylan@authelia.com
groups:
- dev
james:
password: "{CRYPT}$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
email: james.dean@authelia.com

View File

@ -10,7 +10,7 @@ jwt_secret: unsecure_secret
authentication_backend:
file:
path: ./test/suites/basic/users_database.test.yml
path: users.yml
session:
secret: unsecure_session_secret
@ -25,18 +25,17 @@ storage:
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
- 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: 127.0.0.1
host: smtp
port: 1025
sender: admin@example.com

26
suites/action_http.go Normal file
View File

@ -0,0 +1,26 @@
package suites
import (
"crypto/tls"
"io/ioutil"
"net/http"
"github.com/stretchr/testify/assert"
)
func doHTTPGetQuery(s *SeleniumSuite, url string) []byte {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
req, err := http.NewRequest("GET", url, nil)
assert.NoError(s.T(), err)
req.Header.Add("Accept", "application/json")
resp, err := client.Do(req)
assert.NoError(s.T(), err)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
return body
}

Some files were not shown because too many files have changed in this diff Show More