fix(storage): set sane default connection timeout (#2256)

This sets a sane default connection timeout for SQL connections.
This commit is contained in:
James Elliott 2021-08-06 15:35:14 +10:00 committed by GitHub
parent 4f515328d6
commit 9ebad9bec2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 82 additions and 8 deletions

View File

@ -498,6 +498,7 @@ storage:
username: authelia username: authelia
## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html
password: mypassword password: mypassword
timeout: 5s
## ##
## PostgreSQL (Storage Provider) ## PostgreSQL (Storage Provider)
@ -509,6 +510,7 @@ storage:
# username: authelia # username: authelia
# ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html # ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html
# password: mypassword # password: mypassword
# timeout: 5s
# sslmode: disable # sslmode: disable
## ##

View File

@ -84,3 +84,15 @@ required: yes
The password paired with the username used to connect to the database. Can also be defined using a The password paired with the username used to connect to the database. Can also be defined using a
[secret](../secrets.md) which is also the recommended way when running as a container. [secret](../secrets.md) which is also the recommended way when running as a container.
### timeout
<div markdown="1">
type: duration
{: .label .label-config .label-purple }
default: 5s
{: .label .label-config .label-blue }
required: no
{: .label .label-config .label-green }
</div>
The SQL connection timeout.

View File

@ -20,6 +20,7 @@ storage:
database: authelia database: authelia
username: authelia username: authelia
password: mypassword password: mypassword
timeout: 5s
``` ```
## Options ## Options
@ -84,3 +85,15 @@ required: yes
The password paired with the username used to connect to the database. Can also be defined using a The password paired with the username used to connect to the database. Can also be defined using a
[secret](../secrets.md) which is also the recommended way when running as a container. [secret](../secrets.md) which is also the recommended way when running as a container.
### timeout
<div markdown="1">
type: duration
{: .label .label-config .label-purple }
default: 5s
{: .label .label-config .label-blue }
required: no
{: .label .label-config .label-green }
</div>
The SQL connection timeout.

View File

@ -80,6 +80,18 @@ required: yes
The password paired with the username used to connect to the database. Can also be defined using a The password paired with the username used to connect to the database. Can also be defined using a
[secret](../secrets.md) which is also the recommended way when running as a container. [secret](../secrets.md) which is also the recommended way when running as a container.
### timeout
<div markdown="1">
type: duration
{: .label .label-config .label-purple }
default: 5s
{: .label .label-config .label-blue }
required: no
{: .label .label-config .label-green }
</div>
The SQL connection timeout.
### sslmode ### sslmode
<div markdown="1"> <div markdown="1">
type: string type: string

View File

@ -498,6 +498,7 @@ storage:
username: authelia username: authelia
## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html
password: mypassword password: mypassword
timeout: 5s
## ##
## PostgreSQL (Storage Provider) ## PostgreSQL (Storage Provider)
@ -509,6 +510,7 @@ storage:
# username: authelia # username: authelia
# ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html # ## Password can also be set using a secret: https://www.authelia.com/docs/configuration/secrets.html
# password: mypassword # password: mypassword
# timeout: 5s
# sslmode: disable # sslmode: disable
## ##

View File

@ -1,5 +1,7 @@
package schema package schema
import "time"
// LocalStorageConfiguration represents the configuration when using local storage. // LocalStorageConfiguration represents the configuration when using local storage.
type LocalStorageConfiguration struct { type LocalStorageConfiguration struct {
Path string `koanf:"path"` Path string `koanf:"path"`
@ -7,11 +9,12 @@ type LocalStorageConfiguration struct {
// SQLStorageConfiguration represents the configuration of the SQL database. // SQLStorageConfiguration represents the configuration of the SQL database.
type SQLStorageConfiguration struct { type SQLStorageConfiguration struct {
Host string `koanf:"host"` Host string `koanf:"host"`
Port int `koanf:"port"` Port int `koanf:"port"`
Database string `koanf:"database"` Database string `koanf:"database"`
Username string `koanf:"username"` Username string `koanf:"username"`
Password string `koanf:"password"` Password string `koanf:"password"`
Timeout time.Duration `koanf:"timeout"`
} }
// MySQLStorageConfiguration represents the configuration of a MySQL database. // MySQLStorageConfiguration represents the configuration of a MySQL database.
@ -31,3 +34,17 @@ type StorageConfiguration struct {
MySQL *MySQLStorageConfiguration `koanf:"mysql"` MySQL *MySQLStorageConfiguration `koanf:"mysql"`
PostgreSQL *PostgreSQLStorageConfiguration `koanf:"postgres"` PostgreSQL *PostgreSQLStorageConfiguration `koanf:"postgres"`
} }
// DefaultPostgreSQLStorageConfiguration represents the default PostgreSQL configuration.
var DefaultPostgreSQLStorageConfiguration = PostgreSQLStorageConfiguration{
SQLStorageConfiguration: SQLStorageConfiguration{
Timeout: 5 * time.Second,
},
}
// DefaultMySQLStorageConfiguration represents the default MySQL configuration.
var DefaultMySQLStorageConfiguration = MySQLStorageConfiguration{
SQLStorageConfiguration: SQLStorageConfiguration{
Timeout: 5 * time.Second,
},
}

View File

@ -204,6 +204,7 @@ var ValidKeys = []string{
"storage.mysql.database", "storage.mysql.database",
"storage.mysql.username", "storage.mysql.username",
"storage.mysql.password", "storage.mysql.password",
"storage.mysql.timeout",
// PostgreSQL Storage Keys. // PostgreSQL Storage Keys.
"storage.postgres.host", "storage.postgres.host",
@ -211,6 +212,7 @@ var ValidKeys = []string{
"storage.postgres.database", "storage.postgres.database",
"storage.postgres.username", "storage.postgres.username",
"storage.postgres.password", "storage.postgres.password",
"storage.postgres.timeout",
"storage.postgres.sslmode", "storage.postgres.sslmode",
// FileSystem Notifier Keys. // FileSystem Notifier Keys.

View File

@ -14,7 +14,7 @@ func ValidateStorage(configuration schema.StorageConfiguration, validator *schem
switch { switch {
case configuration.MySQL != nil: case configuration.MySQL != nil:
validateSQLConfiguration(&configuration.MySQL.SQLStorageConfiguration, validator) validateMySQLConfiguration(&configuration.MySQL.SQLStorageConfiguration, validator)
case configuration.PostgreSQL != nil: case configuration.PostgreSQL != nil:
validatePostgreSQLConfiguration(configuration.PostgreSQL, validator) validatePostgreSQLConfiguration(configuration.PostgreSQL, validator)
case configuration.Local != nil: case configuration.Local != nil:
@ -22,7 +22,11 @@ func ValidateStorage(configuration schema.StorageConfiguration, validator *schem
} }
} }
func validateSQLConfiguration(configuration *schema.SQLStorageConfiguration, validator *schema.StructValidator) { func validateMySQLConfiguration(configuration *schema.SQLStorageConfiguration, validator *schema.StructValidator) {
if configuration.Timeout == 0 {
configuration.Timeout = schema.DefaultMySQLStorageConfiguration.Timeout
}
if configuration.Password == "" || configuration.Username == "" { if configuration.Password == "" || configuration.Username == "" {
validator.Push(errors.New("the SQL username and password must be provided")) validator.Push(errors.New("the SQL username and password must be provided"))
} }
@ -33,7 +37,11 @@ func validateSQLConfiguration(configuration *schema.SQLStorageConfiguration, val
} }
func validatePostgreSQLConfiguration(configuration *schema.PostgreSQLStorageConfiguration, validator *schema.StructValidator) { func validatePostgreSQLConfiguration(configuration *schema.PostgreSQLStorageConfiguration, validator *schema.StructValidator) {
validateSQLConfiguration(&configuration.SQLStorageConfiguration, validator) validateMySQLConfiguration(&configuration.SQLStorageConfiguration, validator)
if configuration.Timeout == 0 {
configuration.Timeout = schema.DefaultPostgreSQLStorageConfiguration.Timeout
}
if configuration.SSLMode == "" { if configuration.SSLMode == "" {
configuration.SSLMode = testModeDisabled configuration.SSLMode = testModeDisabled

View File

@ -3,6 +3,7 @@ package storage
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"time"
_ "github.com/go-sql-driver/mysql" // Load the MySQL Driver used in the connection string. _ "github.com/go-sql-driver/mysql" // Load the MySQL Driver used in the connection string.
@ -68,6 +69,9 @@ func NewMySQLProvider(configuration schema.MySQLStorageConfiguration) *MySQLProv
connectionString += fmt.Sprintf("/%s", configuration.Database) connectionString += fmt.Sprintf("/%s", configuration.Database)
} }
connectionString += "?"
connectionString += fmt.Sprintf("timeout=%ds", int32(configuration.Timeout/time.Second))
db, err := sql.Open("mysql", connectionString) db, err := sql.Open("mysql", connectionString)
if err != nil { if err != nil {
provider.log.Fatalf("Unable to connect to SQL database: %v", err) provider.log.Fatalf("Unable to connect to SQL database: %v", err)

View File

@ -4,6 +4,7 @@ import (
"database/sql" "database/sql"
"fmt" "fmt"
"strings" "strings"
"time"
_ "github.com/jackc/pgx/v4/stdlib" // Load the PostgreSQL Driver used in the connection string. _ "github.com/jackc/pgx/v4/stdlib" // Load the PostgreSQL Driver used in the connection string.
@ -73,6 +74,7 @@ func NewPostgreSQLProvider(configuration schema.PostgreSQLStorageConfiguration)
args = append(args, fmt.Sprintf("sslmode=%s", configuration.SSLMode)) args = append(args, fmt.Sprintf("sslmode=%s", configuration.SSLMode))
} }
args = append(args, fmt.Sprintf("connect_timeout=%d", int32(configuration.Timeout/time.Second)))
connectionString := strings.Join(args, " ") connectionString := strings.Join(args, " ")
db, err := sql.Open("pgx", connectionString) db, err := sql.Open("pgx", connectionString)