mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
[MISC] Implement golint recommendations (#885)
Co-authored-by: Clément Michaud <clement.michaud34@gmail.com>
This commit is contained in:
parent
a6b7a8632b
commit
2e784084c7
|
@ -1,4 +1,7 @@
|
|||
package main
|
||||
|
||||
// BuildTag tag used to bootstrap Authelia binary.
|
||||
var BuildTag = "__BUILD_TAG__"
|
||||
|
||||
// BuildCommit commit used to bootstrap Authelia binary.
|
||||
var BuildCommit = "__BUILD_COMMIT__"
|
||||
|
|
4
go.mod
4
go.mod
|
@ -19,7 +19,7 @@ require (
|
|||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kr/pty v1.1.8 // indirect
|
||||
github.com/lib/pq v1.3.0
|
||||
github.com/mattn/go-sqlite3 v1.13.0
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
github.com/ogier/pflag v0.0.1 // indirect
|
||||
github.com/onsi/ginkgo v1.10.3 // indirect
|
||||
github.com/onsi/gomega v1.7.1 // indirect
|
||||
|
@ -32,7 +32,7 @@ require (
|
|||
github.com/stretchr/testify v1.5.1
|
||||
github.com/tebeka/selenium v0.9.9
|
||||
github.com/tstranex/u2f v1.0.0
|
||||
github.com/valyala/fasthttp v1.10.0
|
||||
github.com/valyala/fasthttp v1.11.0
|
||||
github.com/xdg/stringprep v1.0.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.3.2
|
||||
google.golang.org/appengine v1.6.5 // indirect
|
||||
|
|
3
go.sum
3
go.sum
|
@ -89,6 +89,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
|
||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs=
|
||||
github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
|
@ -212,6 +213,7 @@ github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A
|
|||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c=
|
||||
github.com/mattn/go-sqlite3 v1.13.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
|
@ -447,6 +449,7 @@ golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
package authentication
|
||||
|
||||
// Level is the type representing a level of authentication
|
||||
// Level is the type representing a level of authentication.
|
||||
type Level int
|
||||
|
||||
const (
|
||||
// NotAuthenticated if the user is not authenticated yet
|
||||
// NotAuthenticated if the user is not authenticated yet.
|
||||
NotAuthenticated Level = iota
|
||||
// OneFactor if the user has passed first factor only
|
||||
// OneFactor if the user has passed first factor only.
|
||||
OneFactor Level = iota
|
||||
// TwoFactor if the user has passed two factors
|
||||
// TwoFactor if the user has passed two factors.
|
||||
TwoFactor Level = iota
|
||||
)
|
||||
|
||||
const (
|
||||
// TOTP Method using Time-Based One-Time Password applications like Google Authenticator
|
||||
// TOTP Method using Time-Based One-Time Password applications like Google Authenticator.
|
||||
TOTP = "totp"
|
||||
// U2F Method using U2F devices like Yubikeys
|
||||
// U2F Method using U2F devices like Yubikeys.
|
||||
U2F = "u2f"
|
||||
// Push Method using Duo application to receive push notifications
|
||||
// Push Method using Duo application to receive push notifications.
|
||||
Push = "mobile_push"
|
||||
)
|
||||
|
||||
|
@ -25,13 +25,14 @@ const (
|
|||
var PossibleMethods = []string{TOTP, U2F, Push}
|
||||
|
||||
const (
|
||||
//Argon2id Hash Identifier
|
||||
// HashingAlgorithmArgon2id Argon2id hash identifier.
|
||||
HashingAlgorithmArgon2id = "argon2id"
|
||||
//SHA512 Hash Identifier
|
||||
// HashingAlgorithmSHA512 SHA512 hash identifier.
|
||||
HashingAlgorithmSHA512 = "6"
|
||||
)
|
||||
|
||||
// These are the default values from the upstream crypt module, we use them to for GetInt, and they need to be checked when updating github.com/simia-tech/crypt
|
||||
// These are the default values from the upstream crypt module we use them to for GetInt
|
||||
// and they need to be checked when updating github.com/simia-tech/crypt.
|
||||
const (
|
||||
HashingDefaultArgon2idTime = 1
|
||||
HashingDefaultArgon2idMemory = 32 * 1024
|
||||
|
@ -40,5 +41,5 @@ const (
|
|||
HashingDefaultSHA512Iterations = 5000
|
||||
)
|
||||
|
||||
// HashingPossibleSaltCharacters represents valid hashing runes
|
||||
// HashingPossibleSaltCharacters represents valid hashing runes.
|
||||
var HashingPossibleSaltCharacters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/")
|
||||
|
|
|
@ -17,35 +17,39 @@ type LDAPConnection interface {
|
|||
Modify(modifyRequest *ldap.ModifyRequest) error
|
||||
}
|
||||
|
||||
// LDAPConnectionImpl the production implementation of an ldap connection
|
||||
// LDAPConnectionImpl the production implementation of an ldap connection.
|
||||
type LDAPConnectionImpl struct {
|
||||
conn *ldap.Conn
|
||||
}
|
||||
|
||||
// NewLDAPConnectionImpl create a new ldap connection
|
||||
// NewLDAPConnectionImpl create a new ldap connection.
|
||||
func NewLDAPConnectionImpl(conn *ldap.Conn) *LDAPConnectionImpl {
|
||||
return &LDAPConnectionImpl{conn}
|
||||
}
|
||||
|
||||
// Bind binds ldap connection to a username/password.
|
||||
func (lc *LDAPConnectionImpl) Bind(username, password string) error {
|
||||
return lc.conn.Bind(username, password)
|
||||
}
|
||||
|
||||
// Close closes a ldap connection.
|
||||
func (lc *LDAPConnectionImpl) Close() {
|
||||
lc.conn.Close()
|
||||
}
|
||||
|
||||
// Search searches a ldap server.
|
||||
func (lc *LDAPConnectionImpl) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) {
|
||||
return lc.conn.Search(searchRequest)
|
||||
}
|
||||
|
||||
// Modify modifies an ldap object.
|
||||
func (lc *LDAPConnectionImpl) Modify(modifyRequest *ldap.ModifyRequest) error {
|
||||
return lc.conn.Modify(modifyRequest)
|
||||
}
|
||||
|
||||
// ********************* FACTORY ***********************
|
||||
|
||||
// LDAPConnectionFactory an interface of factory of ldap connections
|
||||
// LDAPConnectionFactory an interface of factory of ldap connections.
|
||||
type LDAPConnectionFactory interface {
|
||||
DialTLS(network, addr string, config *tls.Config) (LDAPConnection, error)
|
||||
Dial(network, addr string) (LDAPConnection, error)
|
||||
|
@ -54,7 +58,7 @@ type LDAPConnectionFactory interface {
|
|||
// LDAPConnectionFactoryImpl the production implementation of an ldap connection factory.
|
||||
type LDAPConnectionFactoryImpl struct{}
|
||||
|
||||
// NewLDAPConnectionFactoryImpl create a concrete ldap connection factory
|
||||
// NewLDAPConnectionFactoryImpl create a concrete ldap connection factory.
|
||||
func NewLDAPConnectionFactoryImpl() *LDAPConnectionFactoryImpl {
|
||||
return &LDAPConnectionFactoryImpl{}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ func NewLDAPUserProvider(configuration schema.LDAPAuthenticationBackendConfigura
|
|||
}
|
||||
}
|
||||
|
||||
// NewLDAPUserProviderWithFactory creates a new instance of LDAPUserProvider with existing factory.
|
||||
func NewLDAPUserProviderWithFactory(configuration schema.LDAPAuthenticationBackendConfiguration,
|
||||
connectionFactory LDAPConnectionFactory) *LDAPUserProvider {
|
||||
return &LDAPUserProvider{
|
||||
|
@ -90,7 +91,7 @@ func (p *LDAPUserProvider) CheckUserPassword(inputUsername string, password stri
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// OWASP recommends to escape some special characters
|
||||
// OWASP recommends to escape some special characters.
|
||||
// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.md
|
||||
const specialLDAPRunes = ",#+<>;\"="
|
||||
|
||||
|
@ -111,7 +112,7 @@ type ldapUserProfile struct {
|
|||
func (p *LDAPUserProvider) resolveUsersFilter(userFilter string, inputUsername string) string {
|
||||
inputUsername = p.ldapEscape(inputUsername)
|
||||
|
||||
// We temporarily keep placeholder {0} for backward compatibility
|
||||
// We temporarily keep placeholder {0} for backward compatibility.
|
||||
userFilter = strings.ReplaceAll(userFilter, "{0}", inputUsername)
|
||||
|
||||
// The {username} placeholder is equivalent to {0}, it's the new way, a named placeholder.
|
||||
|
@ -137,7 +138,7 @@ func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername str
|
|||
p.configuration.MailAttribute,
|
||||
p.configuration.UsernameAttribute}
|
||||
|
||||
// Search for the given username
|
||||
// Search for the given username.
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
|
||||
1, 0, false, userFilter, attributes, nil,
|
||||
|
@ -182,11 +183,11 @@ func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername str
|
|||
func (p *LDAPUserProvider) resolveGroupsFilter(inputUsername string, profile *ldapUserProfile) (string, error) { //nolint:unparam
|
||||
inputUsername = p.ldapEscape(inputUsername)
|
||||
|
||||
// We temporarily keep placeholder {0} for backward compatibility
|
||||
// We temporarily keep placeholder {0} for backward compatibility.
|
||||
groupFilter := strings.ReplaceAll(p.configuration.GroupsFilter, "{0}", inputUsername)
|
||||
groupFilter = strings.ReplaceAll(groupFilter, "{input}", inputUsername)
|
||||
if profile != nil {
|
||||
// We temporarily keep placeholder {1} for backward compatibility
|
||||
// We temporarily keep placeholder {1} for backward compatibility.
|
||||
groupFilter = strings.ReplaceAll(groupFilter, "{1}", ldap.EscapeFilter(profile.Username))
|
||||
groupFilter = strings.ReplaceAll(groupFilter, "{username}", ldap.EscapeFilter(profile.Username))
|
||||
groupFilter = strings.ReplaceAll(groupFilter, "{dn}", ldap.EscapeFilter(profile.DN))
|
||||
|
@ -219,7 +220,7 @@ func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error
|
|||
groupBaseDN = p.configuration.AdditionalGroupsDN + "," + groupBaseDN
|
||||
}
|
||||
|
||||
// Search for the given username
|
||||
// Search for the given username.
|
||||
searchGroupRequest := ldap.NewSearchRequest(
|
||||
groupBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
|
||||
0, 0, false, groupsFilter, []string{p.configuration.GroupNameAttribute}, nil,
|
||||
|
@ -237,7 +238,7 @@ func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error
|
|||
logging.Logger().Warningf("No groups retrieved from LDAP for user %s", inputUsername)
|
||||
break
|
||||
}
|
||||
// append all values of the document. Normally there should be only one per document.
|
||||
// Append all values of the document. Normally there should be only one per document.
|
||||
groups = append(groups, res.Attributes[0].Values...)
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ func selectMatchingRules(rules []schema.ACLRule, subject Subject, object Object)
|
|||
return selectMatchingObjectRules(matchingRules, object)
|
||||
}
|
||||
|
||||
// PolicyToLevel converts a string policy to int authorization level.
|
||||
func PolicyToLevel(policy string) Level {
|
||||
switch policy {
|
||||
case "bypass":
|
||||
|
|
|
@ -171,11 +171,13 @@ func generateSelfSignedCertificate(cmd *cobra.Command, args []string) {
|
|||
log.Printf("wrote %s\n", keyPath)
|
||||
}
|
||||
|
||||
// CertificatesCmd certificate helper command.
|
||||
var CertificatesCmd = &cobra.Command{
|
||||
Use: "certificates",
|
||||
Short: "Commands related to certificate generation",
|
||||
}
|
||||
|
||||
// CertificatesGenerateCmd certificate generation command.
|
||||
var CertificatesGenerateCmd = &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate a self-signed certificate",
|
||||
|
|
|
@ -19,6 +19,7 @@ func init() {
|
|||
HashPasswordCmd.Flags().IntP("salt-length", "l", schema.DefaultPasswordConfiguration.SaltLength, "set the auto-generated salt length")
|
||||
}
|
||||
|
||||
// HashPasswordCmd password hashing command.
|
||||
var HashPasswordCmd = &cobra.Command{
|
||||
Use: "hash-password [password]",
|
||||
Short: "Hash a password to be used in file-based users database. Default algorithm is argon2id.",
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/authelia/authelia/internal/storage"
|
||||
)
|
||||
|
||||
// MigrateCmd migration helper command.
|
||||
var MigrateCmd *cobra.Command
|
||||
|
||||
func init() {
|
||||
|
@ -20,7 +21,7 @@ func init() {
|
|||
MigrateCmd.AddCommand(MigrateLocalCmd, MigrateMongoCmd)
|
||||
}
|
||||
|
||||
// TOTPSecretsV3 one entry of TOTP secrets in v3
|
||||
// TOTPSecretsV3 one entry of TOTP secrets in v3.
|
||||
type TOTPSecretsV3 struct {
|
||||
UserID string `json:"userId"`
|
||||
Secret struct {
|
||||
|
@ -28,7 +29,7 @@ type TOTPSecretsV3 struct {
|
|||
} `json:"secret"`
|
||||
}
|
||||
|
||||
// U2FDeviceHandleV3 one entry of U2F device handle in v3
|
||||
// U2FDeviceHandleV3 one entry of U2F device handle in v3.
|
||||
type U2FDeviceHandleV3 struct {
|
||||
UserID string `json:"userId"`
|
||||
Registration struct {
|
||||
|
@ -37,13 +38,13 @@ type U2FDeviceHandleV3 struct {
|
|||
} `json:"registration"`
|
||||
}
|
||||
|
||||
// PreferencesV3 one entry of preferences in v3
|
||||
// PreferencesV3 one entry of preferences in v3.
|
||||
type PreferencesV3 struct {
|
||||
UserID string `json:"userId"`
|
||||
Method string `json:"method"`
|
||||
}
|
||||
|
||||
// AuthenticationTraceV3 one authentication trace in v3
|
||||
// AuthenticationTraceV3 one authentication trace in v3.
|
||||
type AuthenticationTraceV3 struct {
|
||||
UserID string `json:"userId"`
|
||||
Successful bool `json:"isAuthenticationSuccessful"`
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
var configurationPath string
|
||||
var localDatabasePath string
|
||||
|
||||
// MigrateLocalCmd migration command
|
||||
// MigrateLocalCmd migration command.
|
||||
var MigrateLocalCmd = &cobra.Command{
|
||||
Use: "localdb",
|
||||
Short: "Migrate data from v3 local database into database configured in v4 configuration file",
|
||||
|
@ -32,7 +32,7 @@ func init() {
|
|||
MigrateLocalCmd.MarkPersistentFlagRequired("config")
|
||||
}
|
||||
|
||||
// migrateLocal data from v3 to v4
|
||||
// migrateLocal data from v3 to v4.
|
||||
func migrateLocal(cmd *cobra.Command, args []string) {
|
||||
dbProvider := createDBProvider(configurationPath)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
var mongoURL string
|
||||
var mongoDatabase string
|
||||
|
||||
// MigrateMongoCmd migration command
|
||||
// MigrateMongoCmd migration command.
|
||||
var MigrateMongoCmd = &cobra.Command{
|
||||
Use: "mongo",
|
||||
Short: "Migrate data from v3 mongo database into database configured in v4 configuration file",
|
||||
|
|
|
@ -6,8 +6,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// ACLRule represent one ACL rule
|
||||
// "weak" coerces a single value into string slice
|
||||
// ACLRule represent one ACL rule "weak" coerces a single value into string slice.
|
||||
type ACLRule struct {
|
||||
Domains []string `mapstructure:"domain,weak"`
|
||||
Policy string `mapstructure:"policy"`
|
||||
|
@ -16,25 +15,24 @@ type ACLRule struct {
|
|||
Resources []string `mapstructure:"resources"`
|
||||
}
|
||||
|
||||
// IsPolicyValid check if policy is valid
|
||||
// IsPolicyValid check if policy is valid.
|
||||
func IsPolicyValid(policy string) bool {
|
||||
return policy == "deny" || policy == "one_factor" || policy == "two_factor" || policy == "bypass"
|
||||
}
|
||||
|
||||
// IsSubjectValid check if a subject is valid
|
||||
// IsSubjectValid check if a subject is valid.
|
||||
func IsSubjectValid(subject string) bool {
|
||||
return subject == "" || strings.HasPrefix(subject, "user:") || strings.HasPrefix(subject, "group:")
|
||||
}
|
||||
|
||||
// IsNetworkValid check if a network is valid
|
||||
// IsNetworkValid check if a network is valid.
|
||||
func IsNetworkValid(network string) bool {
|
||||
_, _, err := net.ParseCIDR(network)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Validate validate an ACL Rule
|
||||
// Validate validate an ACL Rule.
|
||||
func (r *ACLRule) Validate(validator *StructValidator) {
|
||||
|
||||
if len(r.Domains) == 0 {
|
||||
validator.Push(fmt.Errorf("Domain must be provided"))
|
||||
}
|
||||
|
@ -62,7 +60,7 @@ type AccessControlConfiguration struct {
|
|||
Rules []ACLRule `mapstructure:"rules"`
|
||||
}
|
||||
|
||||
// Validate validate the access control configuration
|
||||
// Validate validate the access control configuration.
|
||||
func (acc *AccessControlConfiguration) Validate(validator *StructValidator) {
|
||||
if acc.DefaultPolicy == "" {
|
||||
acc.DefaultPolicy = "deny"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package schema
|
||||
|
||||
// LDAPAuthenticationBackendConfiguration represents the configuration related to LDAP server
|
||||
// LDAPAuthenticationBackendConfiguration represents the configuration related to LDAP server.
|
||||
type LDAPAuthenticationBackendConfiguration struct {
|
||||
URL string `mapstructure:"url"`
|
||||
SkipVerify bool `mapstructure:"skip_verify"`
|
||||
|
@ -16,12 +16,13 @@ type LDAPAuthenticationBackendConfiguration struct {
|
|||
Password string `mapstructure:"password"`
|
||||
}
|
||||
|
||||
// FileAuthenticationBackendConfiguration represents the configuration related to file-based backend
|
||||
// FileAuthenticationBackendConfiguration represents the configuration related to file-based backend.
|
||||
type FileAuthenticationBackendConfiguration struct {
|
||||
Path string `mapstructure:"path"`
|
||||
Password *PasswordConfiguration `mapstructure:"password"`
|
||||
}
|
||||
|
||||
// PasswordConfiguration represents the configuration related to password hashing.
|
||||
type PasswordConfiguration struct {
|
||||
Iterations int `mapstructure:"iterations"`
|
||||
KeyLength int `mapstructure:"key_length"`
|
||||
|
@ -31,7 +32,7 @@ type PasswordConfiguration struct {
|
|||
Parallelism int `mapstructure:"parallelism"`
|
||||
}
|
||||
|
||||
// DefaultPasswordConfiguration represents the default configuration related to Argon2id hashing
|
||||
// DefaultPasswordConfiguration represents the default configuration related to Argon2id hashing.
|
||||
var DefaultPasswordConfiguration = PasswordConfiguration{
|
||||
Iterations: 1,
|
||||
KeyLength: 32,
|
||||
|
@ -41,7 +42,7 @@ var DefaultPasswordConfiguration = PasswordConfiguration{
|
|||
Parallelism: 8,
|
||||
}
|
||||
|
||||
// DefaultCIPasswordConfiguration represents the default configuration related to Argon2id hashing for CI
|
||||
// DefaultCIPasswordConfiguration represents the default configuration related to Argon2id hashing for CI.
|
||||
var DefaultCIPasswordConfiguration = PasswordConfiguration{
|
||||
Iterations: 1,
|
||||
KeyLength: 32,
|
||||
|
@ -51,14 +52,14 @@ var DefaultCIPasswordConfiguration = PasswordConfiguration{
|
|||
Parallelism: 8,
|
||||
}
|
||||
|
||||
// DefaultPasswordSHA512Configuration represents the default configuration related to SHA512 hashing
|
||||
// DefaultPasswordSHA512Configuration represents the default configuration related to SHA512 hashing.
|
||||
var DefaultPasswordSHA512Configuration = PasswordConfiguration{
|
||||
Iterations: 50000,
|
||||
SaltLength: 16,
|
||||
Algorithm: "sha512",
|
||||
}
|
||||
|
||||
// AuthenticationBackendConfiguration represents the configuration related to the authentication backend
|
||||
// AuthenticationBackendConfiguration represents the configuration related to the authentication backend.
|
||||
type AuthenticationBackendConfiguration struct {
|
||||
DisableResetPassword bool `mapstructure:"disable_reset_password"`
|
||||
Ldap *LDAPAuthenticationBackendConfiguration `mapstructure:"ldap"`
|
||||
|
|
|
@ -24,6 +24,7 @@ type NotifierConfiguration struct {
|
|||
SMTP *SMTPNotifierConfiguration `mapstructure:"smtp"`
|
||||
}
|
||||
|
||||
// DefaultSMTPNotifierConfiguration represents default configuration parameters for the SMTP notifier.
|
||||
var DefaultSMTPNotifierConfiguration = SMTPNotifierConfiguration{
|
||||
Subject: "[Authelia] {title}",
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ type RegulationConfiguration struct {
|
|||
BanTime string `mapstructure:"ban_time"`
|
||||
}
|
||||
|
||||
// DefaultRegulationConfiguration represents default configuration parameters for the regulator.
|
||||
var DefaultRegulationConfiguration = RegulationConfiguration{
|
||||
MaxRetries: 3,
|
||||
FindTime: "2m",
|
||||
|
|
|
@ -8,6 +8,8 @@ type TOTPConfiguration struct {
|
|||
}
|
||||
|
||||
var defaultOtpSkew = 1
|
||||
|
||||
// DefaultTOTPConfiguration represents default configuration parameters for TOTP generation.
|
||||
var DefaultTOTPConfiguration = TOTPConfiguration{
|
||||
Issuer: "Authelia",
|
||||
Period: 30,
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/authelia/authelia/internal/configuration/schema"
|
||||
)
|
||||
|
||||
// ValidateSession validates and update session configuration.
|
||||
// ValidateNotifier validates and update notifier configuration.
|
||||
func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *schema.StructValidator) {
|
||||
if configuration.SMTP == nil && configuration.FileSystem == nil {
|
||||
validator.Push(fmt.Errorf("Notifier should be either `smtp` or `filesystem`"))
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/authelia/authelia/internal/utils"
|
||||
)
|
||||
|
||||
// ValidateSession validates and update session configuration.
|
||||
// ValidateRegulation validates and update regulator configuration.
|
||||
func ValidateRegulation(configuration *schema.RegulationConfiguration, validator *schema.StructValidator) {
|
||||
if configuration.FindTime == "" {
|
||||
configuration.FindTime = schema.DefaultRegulationConfiguration.FindTime // 2 min
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/authelia/authelia/internal/configuration/schema"
|
||||
)
|
||||
|
||||
// ValidateSQLStorage validates storage configuration.
|
||||
// ValidateStorage validates storage configuration.
|
||||
func ValidateStorage(configuration schema.StorageConfiguration, validator *schema.StructValidator) {
|
||||
if configuration.Local == nil && configuration.MySQL == nil && configuration.PostgreSQL == nil {
|
||||
validator.Push(errors.New("A storage configuration must be provided. It could be 'local', 'mysql' or 'postgres'"))
|
||||
|
|
|
@ -11,6 +11,7 @@ const ResetPasswordAction = "ResetPassword"
|
|||
|
||||
const authPrefix = "Basic "
|
||||
|
||||
// AuthorizationHeader is the basic-auth HTTP header Authelia utilises.
|
||||
const AuthorizationHeader = "Proxy-Authorization"
|
||||
const remoteUserHeader = "Remote-User"
|
||||
const remoteGroupsHeader = "Remote-Groups"
|
||||
|
@ -18,7 +19,7 @@ const remoteGroupsHeader = "Remote-Groups"
|
|||
var protoHostSeparator = []byte("://")
|
||||
|
||||
const (
|
||||
// Forbidden means the user is forbidden the access to a resource
|
||||
// Forbidden means the user is forbidden the access to a resource.
|
||||
Forbidden authorizationMatching = iota
|
||||
// NotAuthorized means the user can access the resource with more permissions.
|
||||
NotAuthorized authorizationMatching = iota
|
||||
|
|
|
@ -2,12 +2,14 @@ package handlers
|
|||
|
||||
import "github.com/authelia/authelia/internal/middlewares"
|
||||
|
||||
// ConfigurationBody configuration parameters exposed to the frontend.
|
||||
type ConfigurationBody struct {
|
||||
GoogleAnalyticsTrackingID string `json:"ga_tracking_id,omitempty"`
|
||||
RememberMe bool `json:"remember_me"` // whether remember me is enabled or not
|
||||
ResetPassword bool `json:"reset_password"`
|
||||
}
|
||||
|
||||
// ConfigurationGet fetches configuration parameters for frontend mutation.
|
||||
func ConfigurationGet(ctx *middlewares.AutheliaCtx) {
|
||||
body := ConfigurationBody{
|
||||
GoogleAnalyticsTrackingID: ctx.Configuration.GoogleAnalyticsTrackingID,
|
||||
|
|
|
@ -79,6 +79,7 @@ func UserInfoGet(ctx *middlewares.AutheliaCtx) {
|
|||
ctx.SetJSONBody(preferences)
|
||||
}
|
||||
|
||||
// MethodBody the selected 2FA method.
|
||||
type MethodBody struct {
|
||||
Method string `json:"method" valid:"required"`
|
||||
}
|
||||
|
|
|
@ -7,15 +7,18 @@ import (
|
|||
"github.com/pquerna/otp/totp"
|
||||
)
|
||||
|
||||
// TOTPVerifier is the interface for verifying TOTPs.
|
||||
type TOTPVerifier interface {
|
||||
Verify(token, secret string) (bool, error)
|
||||
}
|
||||
|
||||
// TOTPVerifierImpl the production implementation for TOTP verification.
|
||||
type TOTPVerifierImpl struct {
|
||||
Period uint
|
||||
Skew uint
|
||||
}
|
||||
|
||||
// Verify verifies TOTPs.
|
||||
func (tv *TOTPVerifierImpl) Verify(token, secret string) (bool, error) {
|
||||
opts := totp.ValidateOpts{
|
||||
Period: tv.Period,
|
||||
|
|
|
@ -11,15 +11,15 @@ type MethodList = []string
|
|||
|
||||
type authorizationMatching int
|
||||
|
||||
// UserInfo is the model of user second factor preferences
|
||||
// UserInfo is the model of user second factor preferences.
|
||||
type UserPreferences struct {
|
||||
// The preferred 2FA method.
|
||||
Method string `json:"method" valid:"required"`
|
||||
|
||||
// True if a security key has been registered
|
||||
// True if a security key has been registered.
|
||||
HasU2F bool `json:"has_u2f" valid:"required"`
|
||||
|
||||
// True if a TOTP device has been registered
|
||||
// True if a TOTP device has been registered.
|
||||
HasTOTP bool `json:"has_totp" valid:"required"`
|
||||
}
|
||||
|
||||
|
@ -68,12 +68,12 @@ type StateResponse struct {
|
|||
DefaultRedirectionURL string `json:"default_redirection_url"`
|
||||
}
|
||||
|
||||
// resetPasswordStep1RequestBody model of the reset password (step1) request body
|
||||
// resetPasswordStep1RequestBody model of the reset password (step1) request body.
|
||||
type resetPasswordStep1RequestBody struct {
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// resetPasswordStep2RequestBody model of the reset password (step2) request body
|
||||
// resetPasswordStep2RequestBody model of the reset password (step2) request body.
|
||||
type resetPasswordStep2RequestBody struct {
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
|
|
@ -6,12 +6,15 @@ import (
|
|||
"github.com/tstranex/u2f"
|
||||
)
|
||||
|
||||
// U2FVerifier is the interface for verifying U2F keys.
|
||||
type U2FVerifier interface {
|
||||
Verify(keyHandle []byte, publicKey []byte, signResponse u2f.SignResponse, challenge u2f.Challenge) error
|
||||
}
|
||||
|
||||
// U2FVerifierImpl the production implementation for U2F key verification.
|
||||
type U2FVerifierImpl struct{}
|
||||
|
||||
// Verify verifies U2F keys.
|
||||
func (uv *U2FVerifierImpl) Verify(keyHandle []byte, publicKey []byte,
|
||||
signResponse u2f.SignResponse, challenge u2f.Challenge) error {
|
||||
var registration u2f.Registration
|
||||
|
|
|
@ -23,14 +23,14 @@ import (
|
|||
"github.com/authelia/authelia/internal/session"
|
||||
)
|
||||
|
||||
// MockAutheliaCtx a mock of AutheliaCtx
|
||||
// MockAutheliaCtx a mock of AutheliaCtx.
|
||||
type MockAutheliaCtx struct {
|
||||
// Logger hook
|
||||
// Logger hook.
|
||||
Hook *test.Hook
|
||||
Ctx *middlewares.AutheliaCtx
|
||||
Ctrl *gomock.Controller
|
||||
|
||||
// Providers
|
||||
// Providers.
|
||||
UserProviderMock *MockUserProvider
|
||||
StorageProviderMock *storage.MockProvider
|
||||
NotifierMock *MockNotifier
|
||||
|
@ -40,27 +40,27 @@ type MockAutheliaCtx struct {
|
|||
Clock TestingClock
|
||||
}
|
||||
|
||||
// TestingClock implementation of clock for tests
|
||||
// TestingClock implementation of clock for tests.
|
||||
type TestingClock struct {
|
||||
now time.Time
|
||||
}
|
||||
|
||||
// Now return the stored clock
|
||||
// Now return the stored clock.
|
||||
func (dc *TestingClock) Now() time.Time {
|
||||
return dc.now
|
||||
}
|
||||
|
||||
// After return a channel receiving the time after duration has elapsed
|
||||
// After return a channel receiving the time after duration has elapsed.
|
||||
func (dc *TestingClock) After(d time.Duration) <-chan time.Time {
|
||||
return time.After(d)
|
||||
}
|
||||
|
||||
// Set set the time of the clock
|
||||
// Set set the time of the clock.
|
||||
func (dc *TestingClock) Set(now time.Time) {
|
||||
dc.now = now
|
||||
}
|
||||
|
||||
// NewMockAutheliaCtx create an instance of AutheliaCtx mock
|
||||
// NewMockAutheliaCtx create an instance of AutheliaCtx mock.
|
||||
func NewMockAutheliaCtx(t *testing.T) *MockAutheliaCtx {
|
||||
mockAuthelia := new(MockAutheliaCtx)
|
||||
mockAuthelia.Clock = TestingClock{}
|
||||
|
@ -107,7 +107,7 @@ func NewMockAutheliaCtx(t *testing.T) *MockAutheliaCtx {
|
|||
providers.Regulator = regulation.NewRegulator(configuration.Regulation, providers.StorageProvider, &mockAuthelia.Clock)
|
||||
|
||||
request := &fasthttp.RequestCtx{}
|
||||
// Set a cookie to identify this client throughout the test
|
||||
// Set a cookie to identify this client throughout the test.
|
||||
// request.Request.Header.SetCookie("authelia_session", "client_cookie")
|
||||
|
||||
autheliaCtx, _ := middlewares.NewAutheliaCtx(request, configuration, providers)
|
||||
|
@ -120,7 +120,7 @@ func NewMockAutheliaCtx(t *testing.T) *MockAutheliaCtx {
|
|||
return mockAuthelia
|
||||
}
|
||||
|
||||
// Close close the mock
|
||||
// Close close the mock.
|
||||
func (m *MockAutheliaCtx) Close() {
|
||||
m.Hook.Reset()
|
||||
m.Ctrl.Finish()
|
||||
|
@ -146,6 +146,7 @@ func (m *MockAutheliaCtx) Assert200OK(t *testing.T, data interface{}) {
|
|||
assert.Equal(t, string(b), string(m.Ctx.Response.Body()))
|
||||
}
|
||||
|
||||
// GetResponseData retrieves a response from the service.
|
||||
func (m *MockAutheliaCtx) GetResponseData(t *testing.T, data interface{}) {
|
||||
okResponse := middlewares.OKResponse{}
|
||||
okResponse.Data = data
|
||||
|
|
|
@ -2,7 +2,7 @@ package models
|
|||
|
||||
import "time"
|
||||
|
||||
// Attempt represent an authentication attempt.
|
||||
// AuthenticationAttempt represent an authentication attempt.
|
||||
type AuthenticationAttempt struct {
|
||||
// The user who tried to authenticate.
|
||||
Username string
|
||||
|
|
|
@ -6,12 +6,21 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// ErrTimeoutReached error thrown when a timeout is reached
|
||||
// ErrTimeoutReached error thrown when a timeout is reached.
|
||||
var ErrTimeoutReached = errors.New("timeout reached")
|
||||
var parseDurationRegexp = regexp.MustCompile(`^(?P<Duration>[1-9]\d*?)(?P<Unit>[smhdwMy])?$`)
|
||||
|
||||
// Hour is an int based representation of the time unit
|
||||
const Hour = time.Minute * 60
|
||||
|
||||
// Day is an int based representation of the time unit
|
||||
const Day = Hour * 24
|
||||
|
||||
// Week is an int based representation of the time unit
|
||||
const Week = Day * 7
|
||||
|
||||
// Year is an int based representation of the time unit
|
||||
const Year = Day * 365
|
||||
|
||||
// Month is an int based representation of the time unit
|
||||
const Month = Year / 12
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// IsRedirectionSafe determines if a redirection URL is secured.
|
||||
func IsRedirectionSafe(url url.URL, protectedDomain string) bool {
|
||||
if url.Scheme != "https" {
|
||||
return false
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Checks if a single string is in an array of strings
|
||||
// IsStringInSlice checks if a single string is in an array of strings.
|
||||
func IsStringInSlice(a string, list []string) (inSlice bool) {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
|
@ -15,8 +15,8 @@ func IsStringInSlice(a string, list []string) (inSlice bool) {
|
|||
return false
|
||||
}
|
||||
|
||||
// Splits a string s into an array with each item being a max of int d
|
||||
// d = denominator, n = numerator, q = quotient, r = remainder
|
||||
// SliceString splits a string s into an array with each item being a max of int d
|
||||
// d = denominator, n = numerator, q = quotient, r = remainder.
|
||||
func SliceString(s string, d int) (array []string) {
|
||||
n := len(s)
|
||||
q := n / d
|
||||
|
@ -30,7 +30,7 @@ func SliceString(s string, d int) (array []string) {
|
|||
return
|
||||
}
|
||||
|
||||
// RandomString generate a random string of n characters
|
||||
// RandomString generate a random string of n characters.
|
||||
func RandomString(n int, characters []rune) (randomString string) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
b := make([]rune, n)
|
||||
|
|
Loading…
Reference in New Issue
Block a user