diff --git a/cmd/authelia/constants.go b/cmd/authelia/constants.go index 481305a1..14f2cf13 100644 --- a/cmd/authelia/constants.go +++ b/cmd/authelia/constants.go @@ -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__" diff --git a/go.mod b/go.mod index 8b4db983..83a99943 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index 70e4f238..9e058bdc 100644 --- a/go.sum +++ b/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= diff --git a/internal/authentication/const.go b/internal/authentication/const.go index a63c678c..ccd4b44a 100644 --- a/internal/authentication/const.go +++ b/internal/authentication/const.go @@ -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+/") diff --git a/internal/authentication/ldap_connection_factory.go b/internal/authentication/ldap_connection_factory.go index d141419a..694bcbd5 100644 --- a/internal/authentication/ldap_connection_factory.go +++ b/internal/authentication/ldap_connection_factory.go @@ -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{} } diff --git a/internal/authentication/ldap_user_provider.go b/internal/authentication/ldap_user_provider.go index 97fd6f41..051bacf9 100644 --- a/internal/authentication/ldap_user_provider.go +++ b/internal/authentication/ldap_user_provider.go @@ -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...) } diff --git a/internal/authorization/authorizer.go b/internal/authorization/authorizer.go index 8212f80e..a1ad892f 100644 --- a/internal/authorization/authorizer.go +++ b/internal/authorization/authorizer.go @@ -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": diff --git a/internal/commands/certificates.go b/internal/commands/certificates.go index 5da3c120..67ac099f 100644 --- a/internal/commands/certificates.go +++ b/internal/commands/certificates.go @@ -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", diff --git a/internal/commands/hash.go b/internal/commands/hash.go index 27ff6f09..0488f43e 100644 --- a/internal/commands/hash.go +++ b/internal/commands/hash.go @@ -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.", diff --git a/internal/commands/migration.go b/internal/commands/migration.go index 6e0abe0d..7f610be4 100644 --- a/internal/commands/migration.go +++ b/internal/commands/migration.go @@ -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"` diff --git a/internal/commands/migration_local.go b/internal/commands/migration_local.go index a344eb45..acf6ada1 100644 --- a/internal/commands/migration_local.go +++ b/internal/commands/migration_local.go @@ -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) diff --git a/internal/commands/migration_mongo.go b/internal/commands/migration_mongo.go index 6d5ca3e7..f0384bdf 100644 --- a/internal/commands/migration_mongo.go +++ b/internal/commands/migration_mongo.go @@ -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", diff --git a/internal/configuration/schema/access_control.go b/internal/configuration/schema/access_control.go index a2253794..79981798 100644 --- a/internal/configuration/schema/access_control.go +++ b/internal/configuration/schema/access_control.go @@ -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" diff --git a/internal/configuration/schema/authentication.go b/internal/configuration/schema/authentication.go index b8b93afa..91f8a58f 100644 --- a/internal/configuration/schema/authentication.go +++ b/internal/configuration/schema/authentication.go @@ -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"` diff --git a/internal/configuration/schema/notifier.go b/internal/configuration/schema/notifier.go index 4b79874d..99d20bb2 100644 --- a/internal/configuration/schema/notifier.go +++ b/internal/configuration/schema/notifier.go @@ -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}", } diff --git a/internal/configuration/schema/regulation.go b/internal/configuration/schema/regulation.go index 0c36a46b..e4b3b466 100644 --- a/internal/configuration/schema/regulation.go +++ b/internal/configuration/schema/regulation.go @@ -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", diff --git a/internal/configuration/schema/totp.go b/internal/configuration/schema/totp.go index 3b87464f..843d03c0 100644 --- a/internal/configuration/schema/totp.go +++ b/internal/configuration/schema/totp.go @@ -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, diff --git a/internal/configuration/validator/notifier.go b/internal/configuration/validator/notifier.go index 68783475..f51e3725 100644 --- a/internal/configuration/validator/notifier.go +++ b/internal/configuration/validator/notifier.go @@ -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`")) diff --git a/internal/configuration/validator/regulation.go b/internal/configuration/validator/regulation.go index 8bdff6e8..1dbf2989 100644 --- a/internal/configuration/validator/regulation.go +++ b/internal/configuration/validator/regulation.go @@ -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 diff --git a/internal/configuration/validator/storage.go b/internal/configuration/validator/storage.go index b5e66a2f..25bff51d 100644 --- a/internal/configuration/validator/storage.go +++ b/internal/configuration/validator/storage.go @@ -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'")) diff --git a/internal/handlers/const.go b/internal/handlers/const.go index 53c720a9..e9f593cd 100644 --- a/internal/handlers/const.go +++ b/internal/handlers/const.go @@ -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 diff --git a/internal/handlers/handler_configuration.go b/internal/handlers/handler_configuration.go index d4eb9aff..5b451ea3 100644 --- a/internal/handlers/handler_configuration.go +++ b/internal/handlers/handler_configuration.go @@ -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, diff --git a/internal/handlers/handler_user_info.go b/internal/handlers/handler_user_info.go index d03de6a1..05a27790 100644 --- a/internal/handlers/handler_user_info.go +++ b/internal/handlers/handler_user_info.go @@ -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"` } diff --git a/internal/handlers/totp.go b/internal/handlers/totp.go index f04aa6c3..a8bfacfd 100644 --- a/internal/handlers/totp.go +++ b/internal/handlers/totp.go @@ -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, diff --git a/internal/handlers/types.go b/internal/handlers/types.go index f6c4baf3..1a3cc0d5 100644 --- a/internal/handlers/types.go +++ b/internal/handlers/types.go @@ -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"` } diff --git a/internal/handlers/u2f.go b/internal/handlers/u2f.go index 8ad85c99..034da427 100644 --- a/internal/handlers/u2f.go +++ b/internal/handlers/u2f.go @@ -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 diff --git a/internal/mocks/mock_authelia_ctx.go b/internal/mocks/mock_authelia_ctx.go index 947611c5..b3f69483 100644 --- a/internal/mocks/mock_authelia_ctx.go +++ b/internal/mocks/mock_authelia_ctx.go @@ -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 diff --git a/internal/models/types.go b/internal/models/types.go index 1dfd07b9..7a3e0373 100644 --- a/internal/models/types.go +++ b/internal/models/types.go @@ -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 diff --git a/internal/utils/const.go b/internal/utils/const.go index 05ffb344..381abc76 100644 --- a/internal/utils/const.go +++ b/internal/utils/const.go @@ -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[1-9]\d*?)(?P[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 diff --git a/internal/utils/safe_redirection.go b/internal/utils/safe_redirection.go index 7a4975df..37b3e48c 100644 --- a/internal/utils/safe_redirection.go +++ b/internal/utils/safe_redirection.go @@ -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 diff --git a/internal/utils/strings.go b/internal/utils/strings.go index 32cdd865..e433036d 100644 --- a/internal/utils/strings.go +++ b/internal/utils/strings.go @@ -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)