[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" "os/exec"
"strings" "strings"
"github.com/authelia/authelia/internal/utils"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/authelia/authelia/internal/utils"
) )
// HostEntry represents an entry in /etc/hosts // HostEntry represents an entry in /etc/hosts

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -262,14 +262,14 @@ session:
secret: insecure_session_secret secret: insecure_session_secret
# The time in seconds before the cookie expires and session is reset. # 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. # The inactivity time in seconds before the session is reset.
inactivity: 300 # 5 minutes inactivity: 5m
# The remember me duration. # The remember me duration.
# Value of 0 disables remember me. # 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 # 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. # or attack. Currently the default is 1M or 1 month.
remember_me_duration: 1M remember_me_duration: 1M
@ -300,10 +300,12 @@ regulation:
# The time range during which the user can attempt login before being banned. # 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. # 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. # 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. # 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. the file path as shown below.
$ authelia --config config.custom.yml $ 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 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. # 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. # 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 secret: unsecure_session_secret
# The time in seconds before the cookie expires and session is reset. # 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. # The inactivity time in seconds before the session is reset.
inactivity: 300 # 5 minutes inactivity: 5m
# The remember me duration. # The remember me duration.
# Value of 0 disables remember me. # 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 # 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. # or attack. Currently the default is 1M or 1 month.
remember_me_duration: 1M remember_me_duration: 1M
@ -57,28 +57,7 @@ session:
Configuration of this section has an impact on security. You should read notes in Configuration of this section has an impact on security. You should read notes in
[security measures](../security/measures.md#session-security) for more information. [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 The configuration parameters expiration, inactivity, and remember_me_duration use duration notation. See the documentation
usage. for [duration notation format](index.md#duration-notation-format) for more information.
**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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,13 @@ package schema
// RegulationConfiguration represents the configuration related to regulation. // RegulationConfiguration represents the configuration related to regulation.
type RegulationConfiguration struct { type RegulationConfiguration struct {
MaxRetries int `mapstructure:"max_retries"` MaxRetries int `mapstructure:"max_retries"`
FindTime int64 `mapstructure:"find_time"` FindTime string `mapstructure:"find_time"`
BanTime int64 `mapstructure:"ban_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. // SessionConfiguration represents the configuration related to user sessions.
type SessionConfiguration struct { 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"` Name string `mapstructure:"name"`
Secret string `mapstructure:"secret"` Secret string `mapstructure:"secret"`
Expiration int64 `mapstructure:"expiration"` // Expiration in seconds Expiration string `mapstructure:"expiration"`
Inactivity int64 `mapstructure:"inactivity"` // Inactivity in seconds Inactivity string `mapstructure:"inactivity"`
RememberMeDuration string `mapstructure:"remember_me_duration"` RememberMeDuration string `mapstructure:"remember_me_duration"`
Domain string `mapstructure:"domain"` Domain string `mapstructure:"domain"`
Redis *RedisSessionConfiguration `mapstructure:"redis"` Redis *RedisSessionConfiguration `mapstructure:"redis"`
@ -23,6 +22,7 @@ type SessionConfiguration struct {
// DefaultSessionConfiguration is the default session configuration // DefaultSessionConfiguration is the default session configuration
var DefaultSessionConfiguration = SessionConfiguration{ var DefaultSessionConfiguration = SessionConfiguration{
Name: "authelia_session", Name: "authelia_session",
Expiration: 3600, Expiration: "1h",
Inactivity: "5m",
RememberMeDuration: "1M", RememberMeDuration: "1M",
} }

View File

@ -6,3 +6,10 @@ type TOTPConfiguration struct {
Period int `mapstructure:"period"` Period int `mapstructure:"period"`
Skew *int `mapstructure:"skew"` 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 ( import (
"testing" "testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/configuration/schema"
) )
func TestShouldRaiseErrorsWhenNoBackendProvided(t *testing.T) { func TestShouldRaiseErrorsWhenNoBackendProvided(t *testing.T) {

View File

@ -20,16 +20,20 @@ func Validate(configuration *schema.Configuration, validator *schema.StructValid
configuration.Port = defaultPort configuration.Port = defaultPort
} }
if configuration.LogLevel == "" {
configuration.LogLevel = defaultLogLevel
}
if configuration.TLSKey != "" && configuration.TLSCert == "" { if configuration.TLSKey != "" && configuration.TLSCert == "" {
validator.Push(fmt.Errorf("No TLS certificate provided, please check the \"tls_cert\" which has been configured")) validator.Push(fmt.Errorf("No TLS certificate provided, please check the \"tls_cert\" which has been configured"))
} else if configuration.TLSKey == "" && configuration.TLSCert != "" { } else if configuration.TLSKey == "" && configuration.TLSCert != "" {
validator.Push(fmt.Errorf("No TLS key provided, please check the \"tls_key\" which has been configured")) 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 != "" { if configuration.DefaultRedirectionURL != "" {
_, err := url.ParseRequestURI(configuration.DefaultRedirectionURL) _, err := url.ParseRequestURI(configuration.DefaultRedirectionURL)
if err != nil { 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 { if configuration.TOTP == nil {
configuration.TOTP = &schema.TOTPConfiguration{} configuration.TOTP = &schema.TOTPConfiguration{}
} }
ValidateTOTP(configuration.TOTP, validator) 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 { if configuration.Notifier == nil {
validator.Push(fmt.Errorf("A notifier configuration must be provided")) validator.Push(fmt.Errorf("A notifier configuration must be provided"))
} else { } else {
ValidateNotifier(configuration.Notifier, validator) 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 ( import (
"testing" "testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/authelia/authelia/internal/configuration/schema"
) )
func newDefaultConfig() schema.Configuration { func newDefaultConfig() schema.Configuration {
@ -129,3 +130,23 @@ func TestShouldNotRaiseErrorWhenBothTLSCertificateAndKeyAreProvided(t *testing.T
Validate(&config, validator) Validate(&config, validator)
require.Len(t, validator.Errors(), 0) 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 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. // ValidateSession validates and update session configuration.
func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *schema.StructValidator) { func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *schema.StructValidator) {

View File

@ -3,8 +3,9 @@ package validator
import ( import (
"testing" "testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/authelia/authelia/internal/configuration/schema"
) )
type NotifierSuite struct { 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 ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/authelia/authelia/internal/configuration/schema" "github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils" "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")) validator.Push(errors.New("Set secret of the session object"))
} }
// TODO(james-d-elliott): Convert to duration notation if configuration.Expiration == "" {
if configuration.Expiration == 0 {
configuration.Expiration = schema.DefaultSessionConfiguration.Expiration // 1 hour configuration.Expiration = schema.DefaultSessionConfiguration.Expiration // 1 hour
} else if configuration.Expiration < 1 { } else if _, err := utils.ParseDurationString(configuration.Expiration); err != nil {
validator.Push(errors.New("Set expiration of the session above 0")) 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 == "" {
if configuration.Inactivity < 0 { configuration.Inactivity = schema.DefaultSessionConfiguration.Inactivity // 5 min
validator.Push(errors.New("Set inactivity of the session to 0 or above")) } 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 == "" { if configuration.RememberMeDuration == "" {
configuration.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration configuration.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration // 1 month
} else { } else if _, err := utils.ParseDurationString(configuration.RememberMeDuration); err != nil {
if _, err := utils.ParseDurationString(configuration.RememberMeDuration); err != nil { validator.Push(errors.New(fmt.Sprintf("Error occurred parsing session remember_me_duration string: %s", err)))
validator.Push(errors.New(fmt.Sprintf("Error occurred parsing remember_me_duration string: %s", err)))
}
} }
if configuration.Domain == "" { if configuration.Domain == "" {

View File

@ -3,8 +3,9 @@ package validator
import ( import (
"testing" "testing"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/authelia/authelia/internal/configuration/schema"
) )
func newDefaultSessionConfig() schema.SessionConfiguration { func newDefaultSessionConfig() schema.SessionConfiguration {
@ -21,7 +22,27 @@ func TestShouldSetDefaultSessionName(t *testing.T) {
ValidateSession(&config, validator) ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 0) 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) { func TestShouldRaiseErrorWhenRedisIsUsedAndPasswordNotSet(t *testing.T) {
@ -57,14 +78,14 @@ func TestShouldRaiseErrorWhenDomainNotSet(t *testing.T) {
func TestShouldRaiseErrorWhenBadInactivityAndExpirationSet(t *testing.T) { func TestShouldRaiseErrorWhenBadInactivityAndExpirationSet(t *testing.T) {
validator := schema.NewStructValidator() validator := schema.NewStructValidator()
config := newDefaultSessionConfig() config := newDefaultSessionConfig()
config.Inactivity = -1 config.Inactivity = "-1"
config.Expiration = -1 config.Expiration = "-1"
ValidateSession(&config, validator) ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 2) assert.Len(t, validator.Errors(), 2)
assert.EqualError(t, validator.Errors()[0], "Set expiration of the session above 0") 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], "Set inactivity of the session to 0 or above") 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) { func TestShouldRaiseErrorWhenBadRememberMeDurationSet(t *testing.T) {
@ -75,7 +96,7 @@ func TestShouldRaiseErrorWhenBadRememberMeDurationSet(t *testing.T) {
ValidateSession(&config, validator) ValidateSession(&config, validator)
assert.Len(t, validator.Errors(), 1) 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) { func TestShouldSetDefaultRememberMeDuration(t *testing.T) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,14 +7,17 @@ import (
"testing" "testing"
"time" "time"
"github.com/authelia/authelia/internal/authentication" "github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/mocks"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "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 // Test getOriginalURL
@ -469,8 +472,38 @@ func TestShouldDestroySessionWhenInactiveForTooLong(t *testing.T) {
clock := mocks.TestingClock{} clock := mocks.TestingClock{}
clock.Set(time.Now()) 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 := mock.Ctx.GetSession()
userSession.Username = "john" userSession.Username = "john"
@ -495,8 +528,7 @@ func TestShouldKeepSessionWhenUserCheckedRememberMeAndIsInactiveForTooLong(t *te
clock := mocks.TestingClock{} clock := mocks.TestingClock{}
clock.Set(time.Now()) 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 := mock.Ctx.GetSession()
userSession.Username = "john" userSession.Username = "john"
@ -522,8 +554,7 @@ func TestShouldKeepSessionWhenInactivityTimeoutHasNotBeenExceeded(t *testing.T)
clock := mocks.TestingClock{} clock := mocks.TestingClock{}
clock.Set(time.Now()) 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 := mock.Ctx.GetSession()
userSession.Username = "john" userSession.Username = "john"

View File

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

View File

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

View File

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

View File

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

View File

@ -7,11 +7,12 @@ import (
"strings" "strings"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/internal/configuration/schema" "github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/session" "github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/utils" "github.com/authelia/authelia/internal/utils"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
) )
// NewRequestLogger create a new request logger for the given request. // 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/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/golang/mock/gomock"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/valyala/fasthttp" "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) { func TestShouldCallNextWithAutheliaCtx(t *testing.T) {

View File

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

View File

@ -5,13 +5,14 @@ import (
"testing" "testing"
"time" "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" jwt "github.com/dgrijalva/jwt-go"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite" "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 { func newArgs(retriever func(ctx *middlewares.AutheliaCtx) (*session.Identity, error)) middlewares.IdentityVerificationStartArgs {

View File

@ -1,6 +1,10 @@
package middlewares package middlewares
import ( 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/authentication"
"github.com/authelia/authelia/internal/authorization" "github.com/authelia/authelia/internal/authorization"
"github.com/authelia/authelia/internal/configuration/schema" "github.com/authelia/authelia/internal/configuration/schema"
@ -9,9 +13,6 @@ import (
"github.com/authelia/authelia/internal/session" "github.com/authelia/authelia/internal/session"
"github.com/authelia/authelia/internal/storage" "github.com/authelia/authelia/internal/storage"
"github.com/authelia/authelia/internal/utils" "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. // AutheliaCtx contains all server variables related to Authelia.

View File

@ -6,19 +6,21 @@ import (
"testing" "testing"
"time" "time"
"github.com/authelia/authelia/internal/regulation"
"github.com/authelia/authelia/internal/storage"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "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/authorization"
"github.com/authelia/authelia/internal/configuration/schema" "github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/middlewares" "github.com/authelia/authelia/internal/middlewares"
"github.com/authelia/authelia/internal/session" "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 // MockAutheliaCtx a mock of AutheliaCtx

View File

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

View File

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

View File

@ -2,5 +2,5 @@ package notification
// Notifier interface for sending the identity verification link. // Notifier interface for sending the identity verification link.
type Notifier interface { 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") auth := newLoginAuth(username, password, "mail.authelia.com")
proto, _, err := auth.Start(serverInfo) proto, _, err := auth.Start(serverInfo)
assert.Equal(t,"LOGIN", proto) assert.Equal(t, "LOGIN", proto)
require.NoError(t, err) require.NoError(t, err)
toServer, err := auth.Next([]byte("Username:"), true) toServer, err := auth.Next([]byte("Username:"), true)
assert.Equal(t,[]byte(username), toServer) assert.Equal(t, []byte(username), toServer)
require.NoError(t, err) require.NoError(t, err)
toServer, err = auth.Next([]byte("Password:"), true) toServer, err = auth.Next([]byte("Password:"), true)
@ -32,7 +32,7 @@ func TestFullLoginAuth(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
toServer, err = auth.Next([]byte(nil), false) toServer, err = auth.Next([]byte(nil), false)
assert.Equal(t,[]byte(nil), toServer) assert.Equal(t, []byte(nil), toServer)
require.NoError(t, err) require.NoError(t, err)
toServer, err = auth.Next([]byte("test"), true) toServer, err = auth.Next([]byte("test"), true)
@ -60,7 +60,7 @@ func TestTLSNotNeededForLocalhost(t *testing.T) {
auth := newLoginAuth("john", "strongpw123", "localhost") auth := newLoginAuth("john", "strongpw123", "localhost")
proto, _, err := auth.Start(serverInfo) proto, _, err := auth.Start(serverInfo)
assert.Equal(t,"LOGIN", proto) assert.Equal(t, "LOGIN", proto)
require.NoError(t, err) require.NoError(t, err)
} }
@ -73,4 +73,4 @@ func TestTLSNeededForNonLocalhost(t *testing.T) {
auth := newLoginAuth("john", "strongpw123", "mail.authelia.com") auth := newLoginAuth("john", "strongpw123", "mail.authelia.com")
_, _, err := auth.Start(serverInfo) _, _, err := auth.Start(serverInfo)
assert.EqualError(t, err, "connection over plain-text") assert.EqualError(t, err, "connection over plain-text")
} }

View File

@ -9,9 +9,10 @@ import (
"net/smtp" "net/smtp"
"strings" "strings"
log "github.com/sirupsen/logrus"
"github.com/authelia/authelia/internal/configuration/schema" "github.com/authelia/authelia/internal/configuration/schema"
"github.com/authelia/authelia/internal/utils" "github.com/authelia/authelia/internal/utils"
log "github.com/sirupsen/logrus"
) )
// SMTPNotifier a notifier to send emails to SMTP servers. // 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 := &Regulator{storageProvider: provider}
regulator.clock = clock regulator.clock = clock
if configuration != nil { 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")) panic(fmt.Errorf("find_time cannot be greater than ban_time"))
} }
// Set regulator enabled only if MaxRetries is not 0. // Set regulator enabled only if MaxRetries is not 0.
regulator.enabled = configuration.MaxRetries > 0 regulator.enabled = configuration.MaxRetries > 0
regulator.maxRetries = configuration.MaxRetries regulator.maxRetries = configuration.MaxRetries
regulator.findTime = time.Duration(configuration.FindTime) * time.Second regulator.findTime = findTime
regulator.banTime = time.Duration(configuration.BanTime) * time.Second regulator.banTime = banTime
} }
return regulator return regulator
} }

View File

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

View File

@ -5,14 +5,15 @@ import (
"os" "os"
"path" "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/configuration/schema"
"github.com/authelia/authelia/internal/duo" "github.com/authelia/authelia/internal/duo"
"github.com/authelia/authelia/internal/handlers" "github.com/authelia/authelia/internal/handlers"
"github.com/authelia/authelia/internal/logging" "github.com/authelia/authelia/internal/logging"
"github.com/authelia/authelia/internal/middlewares" "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. // StartServer start Authelia server with the given configuration and providers.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,9 +4,10 @@ import (
"database/sql" "database/sql"
"fmt" "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/configuration/schema"
"github.com/authelia/authelia/internal/logging" "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 // MySQLProvider is a MySQL provider

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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