[MISC] Update durations to notation format and housekeeping (#824)

* added regulation validator
* made regulations find_time and ban_time values duration notation strings
* added DefaultRegulationConfiguration for the validator
* made session expiration and inactivity values duration notation strings
* TOTP period does not need to be converted because adjustment should be discouraged
* moved TOTP defaults to DefaultTOTPConfiguration and removed the consts
* arranged the root config validator in configuration file order
* adjusted tests for the changes
* moved duration notation docs to root of configuration
* added references to duration notation where applicable
* project wide gofmt and goimports:
* run gofmt
* run goimports -local github.com/authelia/authelia -w on all files
* Make jwt_secret error uniform and add tests
* now at 100% coverage for internal/configuration/validator/configuration.go
pull/828/head
James Elliott 2020-04-05 22:37:21 +10:00 committed by GitHub
parent 9800421b88
commit 8aade7f40e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
93 changed files with 514 additions and 262 deletions

View File

@ -8,8 +8,9 @@ import (
"os/exec"
"strings"
"github.com/authelia/authelia/internal/utils"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/utils"
)
// HostEntry represents an entry in /etc/hosts

View File

@ -3,9 +3,10 @@ package main
import (
"os"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/utils"
)
func buildAutheliaBinary() {

View File

@ -1,9 +1,10 @@
package main
import (
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/utils"
)
const dockerPullCommandLine = "docker-compose -p authelia -f internal/suites/docker-compose.yml " +

View File

@ -7,9 +7,10 @@ import (
"regexp"
"strings"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/utils"
)
var arch string

View File

@ -3,9 +3,10 @@ package main
import (
"os"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/utils"
)
// ServeCmd serve authelia with the provided configuration

View File

@ -11,10 +11,11 @@ import (
"syscall"
"time"
"github.com/authelia/authelia/internal/suites"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/suites"
"github.com/authelia/authelia/internal/utils"
)
// ErrNotAvailableSuite error raised when suite is not available.

View File

@ -1,10 +1,12 @@
package main
import (
"github.com/authelia/authelia/internal/utils"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"os"
"github.com/authelia/authelia/internal/utils"
)
// RunUnitTest run the unit tests

View File

@ -3,10 +3,11 @@
package main
import (
"github.com/authelia/authelia/internal/commands"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/commands"
"github.com/authelia/authelia/internal/utils"
)
var logLevel string

View File

@ -5,11 +5,12 @@ import (
"os"
"path/filepath"
"github.com/authelia/authelia/internal/suites"
"github.com/authelia/authelia/internal/utils"
"github.com/otiai10/copy"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/suites"
"github.com/authelia/authelia/internal/utils"
)
var tmpDirectory = "/tmp/authelia/suites/"

View File

@ -6,6 +6,9 @@ import (
"log"
"os"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/commands"
@ -18,8 +21,6 @@ import (
"github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/storage"
"github.com/authelia/authelia/internal/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var configPathFlag string
@ -50,7 +51,6 @@ func startServer() {
case "debug":
logging.Logger().Info("Logging severity set to debug")
logging.SetLevel(logrus.DebugLevel)
break
case "trace":
logging.Logger().Info("Logging severity set to trace")
logging.SetLevel(logrus.TraceLevel)

View File

@ -262,14 +262,14 @@ session:
secret: insecure_session_secret
# The time in seconds before the cookie expires and session is reset.
expiration: 3600 # 1 hour
expiration: 1h
# The inactivity time in seconds before the session is reset.
inactivity: 300 # 5 minutes
inactivity: 5m
# The remember me duration.
# Value of 0 disables remember me.
# Value is in seconds, or duration notation. See: https://docs.authelia.com/configuration/session.html#duration-notation
# Value is in seconds, or duration notation. See: https://docs.authelia.com/configuration/index.html#duration-notation-format
# Longer periods are considered less secure because a stolen cookie will last longer giving attackers more time to spy
# or attack. Currently the default is 1M or 1 month.
remember_me_duration: 1M
@ -300,10 +300,12 @@ regulation:
# The time range during which the user can attempt login before being banned.
# The user is banned if the authentication failed 'max_retries' times in a 'find_time' seconds window.
find_time: 120
# Find Time accepts duration notation. See: https://docs.authelia.com/configuration/index.html#duration-notation-format
find_time: 2m
# The length of time before a banned user can login again.
ban_time: 300
# Ban Time accepts duration notation. See: https://docs.authelia.com/configuration/index.html#duration-notation-format
ban_time: 5m
# Configuration of the storage backend used to store data and secrets.
#

View File

@ -14,3 +14,27 @@ When running **Authelia**, you can specify your configuration by passing
the file path as shown below.
$ authelia --config config.custom.yml
## Duration Notation Format
We have implemented a string based notation for configuration options that take a duration. This section describes its
usage. You can use this implementation in: session for expiration, inactivity, and remember_me_duration; and regulation
for ban_time, and find_time. This notation also supports just providing the number of seconds instead.
The notation is comprised of a number which must be positive and not have leading zeros, followed by a letter
denoting the unit of time measurement. The table below describes the units of time and the associated letter.
|Unit |Associated Letter|
|:-----:|:---------------:|
|Years |y |
|Months |M |
|Weeks |w |
|Days |d |
|Hours |h |
|Minutes|m |
|Seconds|s |
Examples:
* 1 hour and 30 minutes: 90m
* 1 day: 1d
* 10 hours: 10h

View File

@ -20,8 +20,15 @@ regulation:
# The time range during which the user can attempt login before being banned.
# The user is banned if the authentication failed `max_retries` times in a `find_time` seconds window.
find_time: 120
# Find Time accepts duration notation. See: https://docs.authelia.com/configuration/index.html#duration-notation-format
find_time: 2m
# The length of time before a banned user can sign in again.
ban_time: 300
# Find Time accepts duration notation. See: https://docs.authelia.com/configuration/index.html#duration-notation-format
ban_time: 5m
```
### Duration Notation
The configuration parameters find_time, and ban_time use duration notation. See the documentation
for [duration notation format](index.md#duration-notation-format) for more information.

View File

@ -27,14 +27,14 @@ session:
secret: unsecure_session_secret
# The time in seconds before the cookie expires and session is reset.
expiration: 3600 # 1 hour
expiration: 1h
# The inactivity time in seconds before the session is reset.
inactivity: 300 # 5 minutes
inactivity: 5m
# The remember me duration.
# Value of 0 disables remember me.
# Value is in seconds, or duration notation. See: https://docs.authelia.com/configuration/session.html#duration-notation
# Value is in seconds, or duration notation. See: https://docs.authelia.com/configuration/index.html#duration-notation-format
# Longer periods are considered less secure because a stolen cookie will last longer giving attackers more time to spy
# or attack. Currently the default is 1M or 1 month.
remember_me_duration: 1M
@ -57,28 +57,7 @@ session:
Configuration of this section has an impact on security. You should read notes in
[security measures](../security/measures.md#session-security) for more information.
# Duration Notation
### Duration Notation
We have implemented a string based notation for configuration options that take a duration. This section describes its
usage.
**NOTE:** At the time of this writing, only remember_me_duration uses this value type. But we plan to change expiration
and inactivity.
The notation is comprised of a number which must be positive and not have leading zeros, followed by a letter
denoting the unit of time measurement. The table below describes the units of time and the associated letter.
|Unit |Associated Letter|
|:-----:|:---------------:|
|Years |y |
|Months |M |
|Weeks |w |
|Days |d |
|Hours |h |
|Minutes|m |
|Seconds|s |
Examples:
* 1 hour and 30 minutes: 90m
* 1 day: 1d
* 10 hours: 10h
The configuration parameters expiration, inactivity, and remember_me_duration use duration notation. See the documentation
for [duration notation format](index.md#duration-notation-format) for more information.

View File

@ -8,8 +8,9 @@ import (
"sync"
"github.com/asaskevich/govalidator"
"github.com/authelia/authelia/internal/configuration/schema"
"gopkg.in/yaml.v2"
"github.com/authelia/authelia/internal/configuration/schema"
)
// FileUserProvider is a provider reading details from a file.

View File

@ -7,8 +7,9 @@ import (
"strings"
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert"
"github.com/authelia/authelia/internal/configuration/schema"
)
func WithDatabase(content []byte, f func(path string)) {

View File

@ -6,9 +6,10 @@ package authentication
import (
tls "crypto/tls"
reflect "reflect"
ldap_v3 "github.com/go-ldap/ldap/v3"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockLDAPConnection is a mock of LDAPConnection interface

View File

@ -6,9 +6,10 @@ import (
"net/url"
"strings"
"github.com/go-ldap/ldap/v3"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/logging"
"github.com/go-ldap/ldap/v3"
)
// LDAPUserProvider is a provider using a LDAP or AD as a user database.

View File

@ -3,11 +3,12 @@ package authentication
import (
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/go-ldap/ldap/v3"
gomock "github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/authelia/authelia/internal/configuration/schema"
)
func TestShouldCreateRawConnectionWhenSchemeIsLDAP(t *testing.T) {

View File

@ -6,8 +6,9 @@ import (
"strconv"
"strings"
"github.com/authelia/authelia/internal/utils"
"github.com/simia-tech/crypt"
"github.com/authelia/authelia/internal/utils"
)
// PasswordHash represents all characteristics of a password hash.

View File

@ -4,11 +4,12 @@ import (
"fmt"
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
"github.com/simia-tech/crypt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
)
func TestShouldHashSHA512Password(t *testing.T) {

View File

@ -3,9 +3,10 @@ package commands
import (
"fmt"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/spf13/cobra"
)
func init() {

View File

@ -4,9 +4,10 @@ import (
"encoding/base64"
"strings"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/configuration"
"github.com/authelia/authelia/internal/storage"
"github.com/spf13/cobra"
)
var MigrateCmd *cobra.Command

View File

@ -8,9 +8,10 @@ import (
"path"
"time"
"github.com/spf13/cobra"
"github.com/authelia/authelia/internal/models"
"github.com/authelia/authelia/internal/storage"
"github.com/spf13/cobra"
)
var configurationPath string

View File

@ -5,12 +5,13 @@ import (
"log"
"time"
"github.com/authelia/authelia/internal/models"
"github.com/authelia/authelia/internal/storage"
"github.com/spf13/cobra"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/authelia/authelia/internal/models"
"github.com/authelia/authelia/internal/storage"
)
var mongoURL string

View File

@ -4,9 +4,10 @@ import (
"fmt"
"strings"
"github.com/spf13/viper"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/configuration/validator"
"github.com/spf13/viper"
)
func check(e error) {

View File

@ -2,7 +2,13 @@ package schema
// RegulationConfiguration represents the configuration related to regulation.
type RegulationConfiguration struct {
MaxRetries int `mapstructure:"max_retries"`
FindTime int64 `mapstructure:"find_time"`
BanTime int64 `mapstructure:"ban_time"`
MaxRetries int `mapstructure:"max_retries"`
FindTime string `mapstructure:"find_time"`
BanTime string `mapstructure:"ban_time"`
}
var DefaultRegulationConfiguration = RegulationConfiguration{
MaxRetries: 3,
FindTime: "2m",
BanTime: "5m",
}

View File

@ -10,11 +10,10 @@ type RedisSessionConfiguration struct {
// SessionConfiguration represents the configuration related to user sessions.
type SessionConfiguration struct {
// TODO(james-d-elliott): Convert to duration notation (Both Expiration and Activity need to be strings, and default needs to be changed)
Name string `mapstructure:"name"`
Secret string `mapstructure:"secret"`
Expiration int64 `mapstructure:"expiration"` // Expiration in seconds
Inactivity int64 `mapstructure:"inactivity"` // Inactivity in seconds
Expiration string `mapstructure:"expiration"`
Inactivity string `mapstructure:"inactivity"`
RememberMeDuration string `mapstructure:"remember_me_duration"`
Domain string `mapstructure:"domain"`
Redis *RedisSessionConfiguration `mapstructure:"redis"`
@ -23,6 +22,7 @@ type SessionConfiguration struct {
// DefaultSessionConfiguration is the default session configuration
var DefaultSessionConfiguration = SessionConfiguration{
Name: "authelia_session",
Expiration: 3600,
Expiration: "1h",
Inactivity: "5m",
RememberMeDuration: "1M",
}

View File

@ -6,3 +6,10 @@ type TOTPConfiguration struct {
Period int `mapstructure:"period"`
Skew *int `mapstructure:"skew"`
}
var defaultOtpSkew = 1
var DefaultTOTPConfiguration = TOTPConfiguration{
Issuer: "Authelia",
Period: 30,
Skew: &defaultOtpSkew,
}

View File

@ -3,10 +3,11 @@ package validator
import (
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/configuration/schema"
)
func TestShouldRaiseErrorsWhenNoBackendProvided(t *testing.T) {

View File

@ -20,16 +20,20 @@ func Validate(configuration *schema.Configuration, validator *schema.StructValid
configuration.Port = defaultPort
}
if configuration.LogLevel == "" {
configuration.LogLevel = defaultLogLevel
}
if configuration.TLSKey != "" && configuration.TLSCert == "" {
validator.Push(fmt.Errorf("No TLS certificate provided, please check the \"tls_cert\" which has been configured"))
} else if configuration.TLSKey == "" && configuration.TLSCert != "" {
validator.Push(fmt.Errorf("No TLS key provided, please check the \"tls_key\" which has been configured"))
}
if configuration.LogLevel == "" {
configuration.LogLevel = defaultLogLevel
}
if configuration.JWTSecret == "" {
validator.Push(fmt.Errorf("Provide a JWT secret using \"jwt_secret\" key"))
}
if configuration.DefaultRedirectionURL != "" {
_, err := url.ParseRequestURI(configuration.DefaultRedirectionURL)
if err != nil {
@ -37,27 +41,29 @@ func Validate(configuration *schema.Configuration, validator *schema.StructValid
}
}
if configuration.JWTSecret == "" {
validator.Push(fmt.Errorf("Provide a JWT secret using `jwt_secret` key"))
}
ValidateAuthenticationBackend(&configuration.AuthenticationBackend, validator)
ValidateSession(&configuration.Session, validator)
if configuration.TOTP == nil {
configuration.TOTP = &schema.TOTPConfiguration{}
}
ValidateTOTP(configuration.TOTP, validator)
ValidateAuthenticationBackend(&configuration.AuthenticationBackend, validator)
if configuration.AccessControl.DefaultPolicy == "" {
configuration.AccessControl.DefaultPolicy = "deny"
}
ValidateSession(&configuration.Session, validator)
if configuration.Regulation == nil {
configuration.Regulation = &schema.RegulationConfiguration{}
}
ValidateRegulation(configuration.Regulation, validator)
ValidateStorage(configuration.Storage, validator)
if configuration.Notifier == nil {
validator.Push(fmt.Errorf("A notifier configuration must be provided"))
} else {
ValidateNotifier(configuration.Notifier, validator)
}
if configuration.AccessControl.DefaultPolicy == "" {
configuration.AccessControl.DefaultPolicy = "deny"
}
ValidateStorage(configuration.Storage, validator)
}

View File

@ -3,9 +3,10 @@ package validator
import (
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/authelia/authelia/internal/configuration/schema"
)
func newDefaultConfig() schema.Configuration {
@ -129,3 +130,23 @@ func TestShouldNotRaiseErrorWhenBothTLSCertificateAndKeyAreProvided(t *testing.T
Validate(&config, validator)
require.Len(t, validator.Errors(), 0)
}
func TestShouldRaiseErrorWithUndefinedJWTSecretKey(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultConfig()
config.JWTSecret = ""
Validate(&config, validator)
require.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "Provide a JWT secret using \"jwt_secret\" key")
}
func TestShouldRaiseErrorWithBadDefaultRedirectionURL(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultConfig()
config.DefaultRedirectionURL = "abc"
Validate(&config, validator)
require.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "Unable to parse default redirection url")
}

View File

@ -1,8 +1,10 @@
package validator
import "github.com/authelia/authelia/internal/configuration/schema"
import (
"fmt"
import "fmt"
"github.com/authelia/authelia/internal/configuration/schema"
)
// ValidateSession validates and update session configuration.
func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *schema.StructValidator) {

View File

@ -3,8 +3,9 @@ package validator
import (
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/configuration/schema"
)
type NotifierSuite struct {

View File

@ -0,0 +1,30 @@
package validator
import (
"errors"
"fmt"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
)
// ValidateSession validates and update session configuration.
func ValidateRegulation(configuration *schema.RegulationConfiguration, validator *schema.StructValidator) {
if configuration.FindTime == "" {
configuration.FindTime = schema.DefaultRegulationConfiguration.FindTime // 2 min
}
if configuration.BanTime == "" {
configuration.BanTime = schema.DefaultRegulationConfiguration.BanTime // 5 min
}
findTime, err := utils.ParseDurationString(configuration.FindTime)
if err != nil {
validator.Push(errors.New(fmt.Sprintf("Error occurred parsing regulation find_time string: %s", err)))
}
banTime, err := utils.ParseDurationString(configuration.BanTime)
if err != nil {
validator.Push(errors.New(fmt.Sprintf("Error occurred parsing regulation ban_time string: %s", err)))
}
if findTime > banTime {
validator.Push(errors.New(fmt.Sprintf("find_time cannot be greater than ban_time")))
}
}

View File

@ -0,0 +1,45 @@
package validator
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/authelia/authelia/internal/configuration/schema"
)
func newDefaultRegulationConfig() schema.RegulationConfiguration {
config := schema.RegulationConfiguration{}
return config
}
func TestShouldSetDefaultRegulationBanTime(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultRegulationConfig()
ValidateRegulation(&config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Equal(t, schema.DefaultRegulationConfiguration.BanTime, config.BanTime)
}
func TestShouldSetDefaultRegulationFindTime(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultRegulationConfig()
ValidateRegulation(&config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Equal(t, schema.DefaultRegulationConfiguration.FindTime, config.FindTime)
}
func TestShouldRaiseErrorWhenFindTimeLessThanBanTime(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultRegulationConfig()
config.FindTime = "1m"
config.BanTime = "10s"
ValidateRegulation(&config, validator)
assert.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "find_time cannot be greater than ban_time")
}

View File

@ -3,6 +3,7 @@ package validator
import (
"errors"
"fmt"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
)
@ -17,24 +18,22 @@ func ValidateSession(configuration *schema.SessionConfiguration, validator *sche
validator.Push(errors.New("Set secret of the session object"))
}
// TODO(james-d-elliott): Convert to duration notation
if configuration.Expiration == 0 {
if configuration.Expiration == "" {
configuration.Expiration = schema.DefaultSessionConfiguration.Expiration // 1 hour
} else if configuration.Expiration < 1 {
validator.Push(errors.New("Set expiration of the session above 0"))
} else if _, err := utils.ParseDurationString(configuration.Expiration); err != nil {
validator.Push(errors.New(fmt.Sprintf("Error occurred parsing session expiration string: %s", err)))
}
// TODO(james-d-elliott): Convert to duration notation
if configuration.Inactivity < 0 {
validator.Push(errors.New("Set inactivity of the session to 0 or above"))
if configuration.Inactivity == "" {
configuration.Inactivity = schema.DefaultSessionConfiguration.Inactivity // 5 min
} else if _, err := utils.ParseDurationString(configuration.Inactivity); err != nil {
validator.Push(errors.New(fmt.Sprintf("Error occurred parsing session inactivity string: %s", err)))
}
if configuration.RememberMeDuration == "" {
configuration.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration
} else {
if _, err := utils.ParseDurationString(configuration.RememberMeDuration); err != nil {
validator.Push(errors.New(fmt.Sprintf("Error occurred parsing remember_me_duration string: %s", err)))
}
configuration.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration // 1 month
} else if _, err := utils.ParseDurationString(configuration.RememberMeDuration); err != nil {
validator.Push(errors.New(fmt.Sprintf("Error occurred parsing session remember_me_duration string: %s", err)))
}
if configuration.Domain == "" {

View File

@ -3,8 +3,9 @@ package validator
import (
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert"
"github.com/authelia/authelia/internal/configuration/schema"
)
func newDefaultSessionConfig() schema.SessionConfiguration {
@ -21,7 +22,27 @@ func TestShouldSetDefaultSessionName(t *testing.T) {
ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Equal(t, "authelia_session", config.Name)
assert.Equal(t, schema.DefaultSessionConfiguration.Name, config.Name)
}
func TestShouldSetDefaultSessionInactivity(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultSessionConfig()
ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Equal(t, schema.DefaultSessionConfiguration.Inactivity, config.Inactivity)
}
func TestShouldSetDefaultSessionExpiration(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultSessionConfig()
ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Equal(t, schema.DefaultSessionConfiguration.Expiration, config.Expiration)
}
func TestShouldRaiseErrorWhenRedisIsUsedAndPasswordNotSet(t *testing.T) {
@ -57,14 +78,14 @@ func TestShouldRaiseErrorWhenDomainNotSet(t *testing.T) {
func TestShouldRaiseErrorWhenBadInactivityAndExpirationSet(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultSessionConfig()
config.Inactivity = -1
config.Expiration = -1
config.Inactivity = "-1"
config.Expiration = "-1"
ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 2)
assert.EqualError(t, validator.Errors()[0], "Set expiration of the session above 0")
assert.EqualError(t, validator.Errors()[1], "Set inactivity of the session to 0 or above")
assert.EqualError(t, validator.Errors()[0], "Error occurred parsing session expiration string: could not convert the input string of -1 into a duration")
assert.EqualError(t, validator.Errors()[1], "Error occurred parsing session inactivity string: could not convert the input string of -1 into a duration")
}
func TestShouldRaiseErrorWhenBadRememberMeDurationSet(t *testing.T) {
@ -75,7 +96,7 @@ func TestShouldRaiseErrorWhenBadRememberMeDurationSet(t *testing.T) {
ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "Error occurred parsing remember_me_duration string: could not convert the input string of 1 year into a duration")
assert.EqualError(t, validator.Errors()[0], "Error occurred parsing session remember_me_duration string: could not convert the input string of 1 year into a duration")
}
func TestShouldSetDefaultRememberMeDuration(t *testing.T) {

View File

@ -3,8 +3,9 @@ package validator
import (
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/configuration/schema"
)
type StorageSuite struct {

View File

@ -2,27 +2,23 @@ package validator
import (
"fmt"
"github.com/authelia/authelia/internal/configuration/schema"
)
const defaultTOTPIssuer = "Authelia"
const DefaultTOTPPeriod = 30
const DefaultTOTPSkew = 1
// ValidateTOTP validates and update TOTP configuration.
func ValidateTOTP(configuration *schema.TOTPConfiguration, validator *schema.StructValidator) {
if configuration.Issuer == "" {
configuration.Issuer = defaultTOTPIssuer
configuration.Issuer = schema.DefaultTOTPConfiguration.Issuer
}
if configuration.Period == 0 {
configuration.Period = DefaultTOTPPeriod
configuration.Period = schema.DefaultTOTPConfiguration.Period
} else if configuration.Period < 0 {
validator.Push(fmt.Errorf("TOTP Period must be 1 or more"))
}
if configuration.Skew == nil {
var skew = DefaultTOTPSkew
configuration.Skew = &skew
configuration.Skew = schema.DefaultTOTPConfiguration.Skew
} else if *configuration.Skew < 0 {
validator.Push(fmt.Errorf("TOTP Skew must be 0 or more"))
}

View File

@ -3,9 +3,10 @@ package validator
import (
"testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/authelia/authelia/internal/configuration/schema"
)
func TestShouldSetDefaultTOTPValues(t *testing.T) {
@ -16,8 +17,8 @@ func TestShouldSetDefaultTOTPValues(t *testing.T) {
require.Len(t, validator.Errors(), 0)
assert.Equal(t, "Authelia", config.Issuer)
assert.Equal(t, DefaultTOTPSkew, *config.Skew)
assert.Equal(t, DefaultTOTPPeriod, config.Period)
assert.Equal(t, *schema.DefaultTOTPConfiguration.Skew, *config.Skew)
assert.Equal(t, schema.DefaultTOTPConfiguration.Period, config.Period)
}
func TestShouldRaiseErrorWhenInvalidTOTPMinimumValues(t *testing.T) {

View File

@ -4,7 +4,7 @@ import (
"encoding/json"
"net/url"
"github.com/duosecurity/duo_api_golang"
duoapi "github.com/duosecurity/duo_api_golang"
"github.com/authelia/authelia/internal/middlewares"
)

View File

@ -3,9 +3,10 @@ package duo
import (
"net/url"
duoapi "github.com/duosecurity/duo_api_golang"
"github.com/authelia/authelia/internal/middlewares"
)
import "github.com/duosecurity/duo_api_golang"
// API interface wrapping duo api library for testing purpose
type API interface {

View File

@ -1,11 +1,13 @@
package handlers
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
"github.com/stretchr/testify/suite"
"testing"
)
type ConfigurationSuite struct {

View File

@ -3,12 +3,11 @@ package handlers
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/configuration/validator"
"github.com/authelia/authelia/internal/mocks"
"github.com/stretchr/testify/suite"
)
type SecondFactorAvailableMethodsFixture struct {
@ -31,13 +30,13 @@ func (s *SecondFactorAvailableMethodsFixture) TearDownTest() {
func (s *SecondFactorAvailableMethodsFixture) TestShouldServeDefaultMethods() {
s.mock.Ctx.Configuration = schema.Configuration{
TOTP: &schema.TOTPConfiguration{
Period: validator.DefaultTOTPPeriod,
Period: schema.DefaultTOTPConfiguration.Period,
},
}
expectedBody := ExtendedConfigurationBody{
AvailableMethods: []string{"totp", "u2f"},
SecondFactorEnabled: false,
TOTPPeriod: validator.DefaultTOTPPeriod,
TOTPPeriod: schema.DefaultTOTPConfiguration.Period,
}
ExtendedConfigurationGet(s.mock.Ctx)
s.mock.Assert200OK(s.T(), expectedBody)
@ -47,13 +46,13 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldServeDefaultMethodsAndMo
s.mock.Ctx.Configuration = schema.Configuration{
DuoAPI: &schema.DuoAPIConfiguration{},
TOTP: &schema.TOTPConfiguration{
Period: validator.DefaultTOTPPeriod,
Period: schema.DefaultTOTPConfiguration.Period,
},
}
expectedBody := ExtendedConfigurationBody{
AvailableMethods: []string{"totp", "u2f", "mobile_push"},
SecondFactorEnabled: false,
TOTPPeriod: validator.DefaultTOTPPeriod,
TOTPPeriod: schema.DefaultTOTPConfiguration.Period,
}
ExtendedConfigurationGet(s.mock.Ctx)
s.mock.Assert200OK(s.T(), expectedBody)
@ -62,7 +61,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldServeDefaultMethodsAndMo
func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsDisabledWhenNoRuleIsSetToTwoFactor() {
s.mock.Ctx.Configuration = schema.Configuration{
TOTP: &schema.TOTPConfiguration{
Period: validator.DefaultTOTPPeriod,
Period: schema.DefaultTOTPConfiguration.Period,
},
}
s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{
@ -86,14 +85,14 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsDisab
s.mock.Assert200OK(s.T(), ExtendedConfigurationBody{
AvailableMethods: []string{"totp", "u2f"},
SecondFactorEnabled: false,
TOTPPeriod: validator.DefaultTOTPPeriod,
TOTPPeriod: schema.DefaultTOTPConfiguration.Period,
})
}
func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabledWhenDefaultPolicySetToTwoFactor() {
s.mock.Ctx.Configuration = schema.Configuration{
TOTP: &schema.TOTPConfiguration{
Period: validator.DefaultTOTPPeriod,
Period: schema.DefaultTOTPConfiguration.Period,
},
}
s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{
@ -117,14 +116,14 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabl
s.mock.Assert200OK(s.T(), ExtendedConfigurationBody{
AvailableMethods: []string{"totp", "u2f"},
SecondFactorEnabled: true,
TOTPPeriod: validator.DefaultTOTPPeriod,
TOTPPeriod: schema.DefaultTOTPConfiguration.Period,
})
}
func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabledWhenSomePolicySetToTwoFactor() {
s.mock.Ctx.Configuration = schema.Configuration{
TOTP: &schema.TOTPConfiguration{
Period: validator.DefaultTOTPPeriod,
Period: schema.DefaultTOTPConfiguration.Period,
},
}
s.mock.Ctx.Providers.Authorizer = authorization.NewAuthorizer(schema.AccessControlConfiguration{
@ -148,7 +147,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldCheckSecondFactorIsEnabl
s.mock.Assert200OK(s.T(), ExtendedConfigurationBody{
AvailableMethods: []string{"totp", "u2f"},
SecondFactorEnabled: true,
TOTPPeriod: validator.DefaultTOTPPeriod,
TOTPPeriod: schema.DefaultTOTPConfiguration.Period,
})
}

View File

@ -9,11 +9,12 @@ import (
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/models"
"github.com/authelia/authelia/internal/authentication"
"github.com/golang/mock/gomock"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/authentication"
)
type FirstFactorSuite struct {

View File

@ -3,9 +3,10 @@ package handlers
import (
"fmt"
"github.com/pquerna/otp/totp"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/session"
"github.com/pquerna/otp/totp"
)
// identityRetrieverFromSession retriever computing the identity from the cookie session.

View File

@ -3,8 +3,9 @@ package handlers
import (
"fmt"
"github.com/authelia/authelia/internal/middlewares"
"github.com/tstranex/u2f"
"github.com/authelia/authelia/internal/middlewares"
)
var u2fConfig = &u2f.Config{

View File

@ -5,12 +5,13 @@ import (
"testing"
"time"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/mocks"
"github.com/dgrijalva/jwt-go"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/mocks"
)
type HandlerRegisterU2FStep1Suite struct {

View File

@ -4,8 +4,9 @@ import (
"crypto/elliptic"
"fmt"
"github.com/authelia/authelia/internal/middlewares"
"github.com/tstranex/u2f"
"github.com/authelia/authelia/internal/middlewares"
)
// SecondFactorU2FRegister handler validating the client has successfully validated the challenge

View File

@ -7,11 +7,12 @@ import (
"regexp"
"testing"
"github.com/authelia/authelia/internal/duo"
"github.com/authelia/authelia/internal/mocks"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/duo"
"github.com/authelia/authelia/internal/mocks"
)
type SecondFactorDuoPostSuite struct {

View File

@ -5,11 +5,12 @@ import (
"regexp"
"testing"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite"
"github.com/tstranex/u2f"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
)
type HandlerSignTOTPSuite struct {

View File

@ -4,10 +4,11 @@ import (
"crypto/elliptic"
"fmt"
"github.com/tstranex/u2f"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/storage"
"github.com/tstranex/u2f"
)
// SecondFactorU2FSignGet handler for initiating a signing request.

View File

@ -3,9 +3,10 @@ package handlers
import (
"testing"
"github.com/authelia/authelia/internal/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/mocks"
)
type HandlerSignU2FStep1Suite struct {

View File

@ -5,11 +5,12 @@ import (
"regexp"
"testing"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite"
"github.com/tstranex/u2f"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
)
type HandlerSignU2FStep2Suite struct {

View File

@ -6,9 +6,10 @@ import (
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/authentication"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/authentication"
)
type StateGetSuite struct {

View File

@ -5,11 +5,12 @@ import (
"strings"
"sync"
"github.com/sirupsen/logrus"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/storage"
"github.com/authelia/authelia/internal/utils"
"github.com/sirupsen/logrus"
)
func loadInfo(username string, storageProvider storage.Provider, preferences *UserPreferences, logger *logrus.Entry) []error {

View File

@ -8,10 +8,11 @@ import (
"strings"
"time"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/middlewares"
"github.com/valyala/fasthttp"
)
func isURLUnderProtectedDomain(url *url.URL, domain string) bool {
@ -155,8 +156,7 @@ func setForwardedHeaders(headers *fasthttp.ResponseHeader, username string, grou
// hasUserBeenInactiveLongEnough check whether the user has been inactive for too long.
func hasUserBeenInactiveLongEnough(ctx *middlewares.AutheliaCtx) (bool, error) {
// TODO(james-d-elliott): Convert to duration notation
maxInactivityPeriod := ctx.Configuration.Session.Inactivity
maxInactivityPeriod := int64(ctx.Providers.SessionProvider.Inactivity.Seconds())
if maxInactivityPeriod == 0 {
return false, nil
}

View File

@ -7,14 +7,17 @@ import (
"testing"
"time"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/mocks"
)
// Test getOriginalURL
@ -469,8 +472,38 @@ func TestShouldDestroySessionWhenInactiveForTooLong(t *testing.T) {
clock := mocks.TestingClock{}
clock.Set(time.Now())
// TODO(james-d-elliott): Convert to duration notation
mock.Ctx.Configuration.Session.Inactivity = 10
mock.Ctx.Configuration.Session.Inactivity = "10"
// Reload the session provider since the configuration is indirect
mock.Ctx.Providers.SessionProvider = session.NewProvider(mock.Ctx.Configuration.Session)
assert.Equal(t, time.Second*10, mock.Ctx.Providers.SessionProvider.Inactivity)
userSession := mock.Ctx.GetSession()
userSession.Username = "john"
userSession.AuthenticationLevel = authentication.TwoFactor
userSession.LastActivity = clock.Now().Add(-1 * time.Hour).Unix()
mock.Ctx.SaveSession(userSession)
mock.Ctx.Request.Header.Set("X-Original-URL", "https://two-factor.example.com")
VerifyGet(mock.Ctx)
// The session has been destroyed
newUserSession := mock.Ctx.GetSession()
assert.Equal(t, "", newUserSession.Username)
assert.Equal(t, authentication.NotAuthenticated, newUserSession.AuthenticationLevel)
}
func TestShouldDestroySessionWhenInactiveForTooLongUsingDurationNotation(t *testing.T) {
mock := mocks.NewMockAutheliaCtx(t)
defer mock.Close()
clock := mocks.TestingClock{}
clock.Set(time.Now())
mock.Ctx.Configuration.Session.Inactivity = "10s"
// Reload the session provider since the configuration is indirect
mock.Ctx.Providers.SessionProvider = session.NewProvider(mock.Ctx.Configuration.Session)
assert.Equal(t, time.Second*10, mock.Ctx.Providers.SessionProvider.Inactivity)
userSession := mock.Ctx.GetSession()
userSession.Username = "john"
@ -495,8 +528,7 @@ func TestShouldKeepSessionWhenUserCheckedRememberMeAndIsInactiveForTooLong(t *te
clock := mocks.TestingClock{}
clock.Set(time.Now())
// TODO(james-d-elliott): Convert to duration notation
mock.Ctx.Configuration.Session.Inactivity = 10
mock.Ctx.Configuration.Session.Inactivity = "10"
userSession := mock.Ctx.GetSession()
userSession.Username = "john"
@ -522,8 +554,7 @@ func TestShouldKeepSessionWhenInactivityTimeoutHasNotBeenExceeded(t *testing.T)
clock := mocks.TestingClock{}
clock.Set(time.Now())
// TODO(james-d-elliott): Convert to duration notation
mock.Ctx.Configuration.Session.Inactivity = 10
mock.Ctx.Configuration.Session.Inactivity = "10"
userSession := mock.Ctx.GetSession()
userSession.Username = "john"

View File

@ -1,9 +1,10 @@
package handlers
import (
"time"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
"time"
)
type TOTPVerifier interface {

View File

@ -5,8 +5,9 @@
package handlers
import (
gomock "github.com/golang/mock/gomock"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
)
// MockTOTPVerifier is a mock of TOTPVerifier interface

View File

@ -1,8 +1,9 @@
package handlers
import (
"github.com/authelia/authelia/internal/authentication"
"github.com/tstranex/u2f"
"github.com/authelia/authelia/internal/authentication"
)
// MethodList is the list of available methods.

View File

@ -5,9 +5,10 @@
package handlers
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
u2f "github.com/tstranex/u2f"
reflect "reflect"
)
// MockU2FVerifier is a mock of U2FVerifier interface

View File

@ -7,11 +7,12 @@ import (
"strings"
"github.com/asaskevich/govalidator"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/utils"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
)
// NewRequestLogger create a new request logger for the given request.

View File

@ -5,12 +5,13 @@ import (
"github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/mocks"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/mocks"
)
func TestShouldCallNextWithAutheliaCtx(t *testing.T) {

View File

@ -6,8 +6,9 @@ import (
"fmt"
"time"
"github.com/authelia/authelia/internal/templates"
jwt "github.com/dgrijalva/jwt-go"
"github.com/authelia/authelia/internal/templates"
)
// IdentityVerificationStart the handler for initiating the identity validation process.

View File

@ -5,13 +5,14 @@ import (
"testing"
"time"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
jwt "github.com/dgrijalva/jwt-go"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/session"
)
func newArgs(retriever func(ctx *middlewares.AutheliaCtx) (*session.Identity, error)) middlewares.IdentityVerificationStartArgs {

View File

@ -1,6 +1,10 @@
package middlewares
import (
jwt "github.com/dgrijalva/jwt-go"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/configuration/schema"
@ -9,9 +13,6 @@ import (
"github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/storage"
"github.com/authelia/authelia/internal/utils"
jwt "github.com/dgrijalva/jwt-go"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
)
// AutheliaCtx contains all server variables related to Authelia.

View File

@ -6,19 +6,21 @@ import (
"testing"
"time"
"github.com/authelia/authelia/internal/regulation"
"github.com/authelia/authelia/internal/storage"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/authelia/authelia/internal/regulation"
"github.com/authelia/authelia/internal/storage"
"github.com/golang/mock/gomock"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/session"
"github.com/golang/mock/gomock"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/valyala/fasthttp"
)
// MockAutheliaCtx a mock of AutheliaCtx

View File

@ -8,9 +8,10 @@ import (
url "net/url"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
duo "github.com/authelia/authelia/internal/duo"
"github.com/authelia/authelia/internal/middlewares"
gomock "github.com/golang/mock/gomock"
)
// MockAPI is a mock of API interface

View File

@ -7,8 +7,9 @@ package mocks
import (
reflect "reflect"
authentication "github.com/authelia/authelia/internal/authentication"
gomock "github.com/golang/mock/gomock"
authentication "github.com/authelia/authelia/internal/authentication"
)
// MockUserProvider is a mock of UserProvider interface

View File

@ -2,5 +2,5 @@ package notification
// Notifier interface for sending the identity verification link.
type Notifier interface {
Send(recipient, subject, body string) error
Send(recipient, subject, body string) error
}

View File

@ -20,11 +20,11 @@ func TestFullLoginAuth(t *testing.T) {
auth := newLoginAuth(username, password, "mail.authelia.com")
proto, _, err := auth.Start(serverInfo)
assert.Equal(t,"LOGIN", proto)
assert.Equal(t, "LOGIN", proto)
require.NoError(t, err)
toServer, err := auth.Next([]byte("Username:"), true)
assert.Equal(t,[]byte(username), toServer)
assert.Equal(t, []byte(username), toServer)
require.NoError(t, err)
toServer, err = auth.Next([]byte("Password:"), true)
@ -32,7 +32,7 @@ func TestFullLoginAuth(t *testing.T) {
require.NoError(t, err)
toServer, err = auth.Next([]byte(nil), false)
assert.Equal(t,[]byte(nil), toServer)
assert.Equal(t, []byte(nil), toServer)
require.NoError(t, err)
toServer, err = auth.Next([]byte("test"), true)
@ -60,7 +60,7 @@ func TestTLSNotNeededForLocalhost(t *testing.T) {
auth := newLoginAuth("john", "strongpw123", "localhost")
proto, _, err := auth.Start(serverInfo)
assert.Equal(t,"LOGIN", proto)
assert.Equal(t, "LOGIN", proto)
require.NoError(t, err)
}

View File

@ -9,9 +9,10 @@ import (
"net/smtp"
"strings"
log "github.com/sirupsen/logrus"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
)
// SMTPNotifier a notifier to send emails to SMTP servers.

View File

@ -15,14 +15,24 @@ func NewRegulator(configuration *schema.RegulationConfiguration, provider storag
regulator := &Regulator{storageProvider: provider}
regulator.clock = clock
if configuration != nil {
if configuration.FindTime > configuration.BanTime {
findTime, err := utils.ParseDurationString(configuration.FindTime)
if err != nil {
panic(err)
}
banTime, err := utils.ParseDurationString(configuration.BanTime)
if err != nil {
panic(err)
}
if findTime > banTime {
panic(fmt.Errorf("find_time cannot be greater than ban_time"))
}
// Set regulator enabled only if MaxRetries is not 0.
regulator.enabled = configuration.MaxRetries > 0
regulator.maxRetries = configuration.MaxRetries
regulator.findTime = time.Duration(configuration.FindTime) * time.Second
regulator.banTime = time.Duration(configuration.BanTime) * time.Second
regulator.findTime = findTime
regulator.banTime = banTime
}
return regulator
}

View File

@ -4,14 +4,15 @@ import (
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/mocks"
"github.com/authelia/authelia/internal/models"
"github.com/authelia/authelia/internal/regulation"
"github.com/authelia/authelia/internal/storage"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
type RegulatorSuite struct {
@ -29,8 +30,8 @@ func (s *RegulatorSuite) SetupTest() {
s.configuration = schema.RegulationConfiguration{
MaxRetries: 3,
BanTime: 180,
FindTime: 30,
BanTime: "180",
FindTime: "30",
}
s.clock.Set(time.Now())
}
@ -282,8 +283,8 @@ func (s *RegulatorSuite) TestShouldHaveRegulatorDisabled() {
// Check Disabled Functionality
configuration := schema.RegulationConfiguration{
MaxRetries: 0,
FindTime: 180,
BanTime: 180,
FindTime: "180",
BanTime: "180",
}
regulator := regulation.NewRegulator(&configuration, s.storageMock, &s.clock)
@ -293,8 +294,8 @@ func (s *RegulatorSuite) TestShouldHaveRegulatorDisabled() {
// Check Enabled Functionality
configuration = schema.RegulationConfiguration{
MaxRetries: 1,
FindTime: 180,
BanTime: 180,
FindTime: "180",
BanTime: "180",
}
regulator = regulation.NewRegulator(&configuration, s.storageMock, &s.clock)

View File

@ -5,14 +5,15 @@ import (
"os"
"path"
duoapi "github.com/duosecurity/duo_api_golang"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/duo"
"github.com/authelia/authelia/internal/handlers"
"github.com/authelia/authelia/internal/logging"
"github.com/authelia/authelia/internal/middlewares"
duoapi "github.com/duosecurity/duo_api_golang"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
// StartServer start Authelia server with the given configuration and providers.

View File

@ -4,8 +4,9 @@ import (
"crypto/sha256"
"fmt"
"github.com/authelia/authelia/internal/utils"
"github.com/fasthttp/session"
"github.com/authelia/authelia/internal/utils"
)
// EncryptingSerializer a serializer encrypting the data with AES-GCM with 256-bit keys.

View File

@ -5,10 +5,11 @@
package mock_session
import (
session "github.com/fasthttp/session"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
time "time"
session "github.com/fasthttp/session"
gomock "github.com/golang/mock/gomock"
)
// MockStorer is a mock of Storer interface

View File

@ -2,18 +2,20 @@ package session
import (
"encoding/json"
"github.com/authelia/authelia/internal/utils"
"time"
"github.com/authelia/authelia/internal/configuration/schema"
fasthttpsession "github.com/fasthttp/session"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
)
// Provider a session provider.
type Provider struct {
sessionHolder *fasthttpsession.Session
RememberMe time.Duration
Inactivity time.Duration
}
// NewProvider instantiate a session provider given a configuration.
@ -22,11 +24,19 @@ func NewProvider(configuration schema.SessionConfiguration) *Provider {
provider := new(Provider)
provider.sessionHolder = fasthttpsession.New(providerConfig.config)
duration, err := utils.ParseDurationString(configuration.RememberMeDuration)
if err != nil {
panic(err)
}
provider.RememberMe = duration
duration, err = utils.ParseDurationString(configuration.Inactivity)
if err != nil {
panic(err)
}
provider.Inactivity = duration
err = provider.sessionHolder.SetProvider(providerConfig.providerName, providerConfig.providerConfig)
if err != nil {
panic(err)

View File

@ -1,14 +1,13 @@
package session
import (
"time"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/fasthttp/session"
"github.com/fasthttp/session/memory"
"github.com/fasthttp/session/redis"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
)
// NewProviderConfig creates a configuration for creating the session provider
@ -24,13 +23,8 @@ func NewProviderConfig(configuration schema.SessionConfiguration) ProviderConfig
// Only serve the header over HTTPS.
config.Secure = true
// TODO(james-d-elliott): Convert to duration notation
if configuration.Expiration > 0 {
config.Expires = time.Duration(configuration.Expiration) * time.Second
} else {
// If Expiration is 0 then cookie expiration is disabled.
config.Expires = 0
}
// Ignore the error as it will be handled by validator
config.Expires, _ = utils.ParseDurationString(configuration.Expiration)
// TODO(c.michaud): Make this configurable by giving the list of IPs that are trustable.
config.IsSecureFunc = func(*fasthttp.RequestCtx) bool {

View File

@ -5,13 +5,14 @@ import (
"testing"
"time"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
"github.com/fasthttp/session"
"github.com/fasthttp/session/memory"
"github.com/fasthttp/session/redis"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils"
)
func TestShouldCreateInMemorySessionProvider(t *testing.T) {
@ -19,8 +20,7 @@ func TestShouldCreateInMemorySessionProvider(t *testing.T) {
configuration := schema.SessionConfiguration{}
configuration.Domain = "example.com"
configuration.Name = "my_session"
// TODO(james-d-elliott): Convert to duration notation
configuration.Expiration = 40
configuration.Expiration = "40"
providerConfig := NewProviderConfig(configuration)
assert.Equal(t, "my_session", providerConfig.config.CookieName)
@ -38,8 +38,7 @@ func TestShouldCreateRedisSessionProvider(t *testing.T) {
configuration := schema.SessionConfiguration{}
configuration.Domain = "example.com"
configuration.Name = "my_session"
// TODO(james-d-elliott): Convert to duration notation
configuration.Expiration = 40
configuration.Expiration = "40"
configuration.Redis = &schema.RedisSessionConfiguration{
Host: "redis.example.com",
Port: 6379,
@ -68,8 +67,7 @@ func TestShouldSetDbNumber(t *testing.T) {
configuration := schema.SessionConfiguration{}
configuration.Domain = "example.com"
configuration.Name = "my_session"
// TODO(james-d-elliott): Convert to duration notation
configuration.Expiration = 40
configuration.Expiration = "40"
configuration.Redis = &schema.RedisSessionConfiguration{
Host: "redis.example.com",
Port: 6379,

View File

@ -3,13 +3,11 @@ package session
import (
"testing"
"github.com/authelia/authelia/internal/authentication"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/configuration/schema"
)
@ -18,8 +16,7 @@ func TestShouldInitializerSession(t *testing.T) {
configuration := schema.SessionConfiguration{}
configuration.Domain = "example.com"
configuration.Name = "my_session"
// TODO(james-d-elliott): Convert to duration notation
configuration.Expiration = 40
configuration.Expiration = "40"
provider := NewProvider(configuration)
session, err := provider.GetSession(ctx)
@ -33,8 +30,7 @@ func TestShouldUpdateSession(t *testing.T) {
configuration := schema.SessionConfiguration{}
configuration.Domain = "example.com"
configuration.Name = "my_session"
// TODO(james-d-elliott): Convert to duration notation
configuration.Expiration = 40
configuration.Expiration = "40"
provider := NewProvider(configuration)
session, _ := provider.GetSession(ctx)
@ -59,8 +55,7 @@ func TestShouldDestroySessionAndWipeSessionData(t *testing.T) {
configuration := schema.SessionConfiguration{}
configuration.Domain = "example.com"
configuration.Name = "my_session"
// TODO(james-d-elliott): Convert to duration notation
configuration.Expiration = 40
configuration.Expiration = "40"
provider := NewProvider(configuration)
session, err := provider.GetSession(ctx)

View File

@ -1,9 +1,10 @@
package session
import (
"github.com/authelia/authelia/internal/authentication"
"github.com/fasthttp/session"
"github.com/tstranex/u2f"
"github.com/authelia/authelia/internal/authentication"
)
// ProviderConfig is the configuration used to create the session provider.

View File

@ -4,9 +4,10 @@ import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql" // Load the MySQL Driver used in the connection string.
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/logging"
_ "github.com/go-sql-driver/mysql" // Load the MySQL Driver used in the connection string.
)
// MySQLProvider is a MySQL provider

View File

@ -5,9 +5,10 @@ import (
"fmt"
"strings"
_ "github.com/lib/pq" // Load the PostgreSQL Driver used in the connection string.
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/logging"
_ "github.com/lib/pq" // Load the PostgreSQL Driver used in the connection string.
)
// PostgreSQLProvider is a Postrgres provider

View File

@ -5,10 +5,12 @@
package storage
import (
models "github.com/authelia/authelia/internal/models"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
time "time"
gomock "github.com/golang/mock/gomock"
models "github.com/authelia/authelia/internal/models"
)
// MockProvider is a mock of Provider interface

View File

@ -4,8 +4,9 @@ import (
"database/sql"
"fmt"
"github.com/authelia/authelia/internal/logging"
_ "github.com/mattn/go-sqlite3" // Load the SQLite Driver used in the connection string.
"github.com/authelia/authelia/internal/logging"
)
// SQLiteProvider is a sqlite3 provider

View File

@ -6,8 +6,9 @@ import (
"os/exec"
"strings"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/authelia/authelia/internal/utils"
)
// DockerEnvironment represent a docker environment

View File

@ -5,8 +5,9 @@ import (
"strings"
"time"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/authelia/authelia/internal/utils"
)
func waitUntilServiceLogDetected(

View File

@ -5,8 +5,9 @@ import (
"os"
"time"
"github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
"github.com/authelia/authelia/internal/utils"
)
var kubernetesSuiteName = "Kubernetes"

View File

@ -10,9 +10,10 @@ import (
"testing"
"time"
"github.com/authelia/authelia/internal/storage"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/storage"
)
type StandaloneWebDriverSuite struct {

View File

@ -1,9 +1,10 @@
package utils
import (
"github.com/stretchr/testify/assert"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestShouldParseDurationString(t *testing.T) {