From 1d821a0d3a15b853e50c44aa786b846213f0355c Mon Sep 17 00:00:00 2001 From: James Elliott Date: Sat, 22 Oct 2022 15:25:12 +1100 Subject: [PATCH] fix(storage): mysql timestamp parsed incorrectly (#4230) The timestamps in MySQL were not being parsed correctly. The driver treats all timestamp and datetime objects the same which is not correct. --- config.template.yml | 14 ++++---- internal/configuration/config.template.yml | 14 ++++---- internal/storage/const.go | 4 +++ .../storage/sql_provider_backend_mysql.go | 33 ++++++++++++------- 4 files changed, 40 insertions(+), 25 deletions(-) diff --git a/config.template.yml b/config.template.yml index 93133344e..4531e0138 100644 --- a/config.template.yml +++ b/config.template.yml @@ -396,13 +396,13 @@ authentication_backend: # base_dn: dc=example,dc=com ## The attribute holding the username of the user. This attribute is used to populate the username in the session - ## information. It was introduced due to #561 to handle case insensitive search queries. For you information, - ## Microsoft Active Directory usually uses 'sAMAccountName' and OpenLDAP usually uses 'uid'. Beware that this - ## attribute holds the unique identifiers for the users binding the user and the configuration stored in database. - ## Therefore only single value attributes are allowed and the value must never be changed once attributed to a user - ## otherwise it would break the configuration for that user. Technically, non-unique attributes like 'mail' can also - ## be used but we don't recommend using them, we instead advise to use the attributes mentioned above - ## (sAMAccountName and uid) to follow https://www.ietf.org/rfc/rfc2307.txt. + ## information. For your information, Microsoft Active Directory usually uses 'sAMAccountName' and OpenLDAP usually + ## uses 'uid'. Beware that this attribute holds the unique identifiers for the users binding the user and the + ## configuration stored in database. Therefore only single value attributes are allowed and the value must never be + ## changed once attributed to a user otherwise it would break the configuration for that user. Technically, + ## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use + ## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to + ## follow https://www.ietf.org/rfc/rfc2307.txt. # username_attribute: uid ## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users. diff --git a/internal/configuration/config.template.yml b/internal/configuration/config.template.yml index 93133344e..4531e0138 100644 --- a/internal/configuration/config.template.yml +++ b/internal/configuration/config.template.yml @@ -396,13 +396,13 @@ authentication_backend: # base_dn: dc=example,dc=com ## The attribute holding the username of the user. This attribute is used to populate the username in the session - ## information. It was introduced due to #561 to handle case insensitive search queries. For you information, - ## Microsoft Active Directory usually uses 'sAMAccountName' and OpenLDAP usually uses 'uid'. Beware that this - ## attribute holds the unique identifiers for the users binding the user and the configuration stored in database. - ## Therefore only single value attributes are allowed and the value must never be changed once attributed to a user - ## otherwise it would break the configuration for that user. Technically, non-unique attributes like 'mail' can also - ## be used but we don't recommend using them, we instead advise to use the attributes mentioned above - ## (sAMAccountName and uid) to follow https://www.ietf.org/rfc/rfc2307.txt. + ## information. For your information, Microsoft Active Directory usually uses 'sAMAccountName' and OpenLDAP usually + ## uses 'uid'. Beware that this attribute holds the unique identifiers for the users binding the user and the + ## configuration stored in database. Therefore only single value attributes are allowed and the value must never be + ## changed once attributed to a user otherwise it would break the configuration for that user. Technically, + ## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use + ## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to + ## follow https://www.ietf.org/rfc/rfc2307.txt. # username_attribute: uid ## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users. diff --git a/internal/storage/const.go b/internal/storage/const.go index dc249115f..825caae04 100644 --- a/internal/storage/const.go +++ b/internal/storage/const.go @@ -40,6 +40,10 @@ const ( OAuth2SessionTypeOpenIDConnect OAuth2SessionType = "openid connect" ) +const ( + sqlNetworkTypeTCP = "tcp" +) + const ( encryptionNameCheck = "check" ) diff --git a/internal/storage/sql_provider_backend_mysql.go b/internal/storage/sql_provider_backend_mysql.go index 6c313ee57..a336aeac9 100644 --- a/internal/storage/sql_provider_backend_mysql.go +++ b/internal/storage/sql_provider_backend_mysql.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql" // Load the MySQL Driver used in the connection string. "github.com/authelia/authelia/v4/internal/configuration/schema" @@ -30,21 +31,31 @@ func NewMySQLProvider(config *schema.Configuration) (provider *MySQLProvider) { } func dataSourceNameMySQL(config schema.MySQLStorageConfiguration) (dataSourceName string) { - dataSourceName = fmt.Sprintf("%s:%s", config.Username, config.Password) + dconfig := mysql.NewConfig() - if dataSourceName != "" { - dataSourceName += "@" + switch { + case config.Port == 0: + dconfig.Net = sqlNetworkTypeTCP + dconfig.Addr = fmt.Sprintf("%s:%d", config.Host, 3306) + default: + dconfig.Net = sqlNetworkTypeTCP + dconfig.Addr = fmt.Sprintf("%s:%d", config.Host, config.Port) } - address := config.Host - if config.Port > 0 { - address += fmt.Sprintf(":%d", config.Port) + switch config.Port { + case 0: + dconfig.Addr = config.Host + default: + dconfig.Addr = fmt.Sprintf("%s:%d", config.Host, config.Port) } - dataSourceName += fmt.Sprintf("tcp(%s)/%s", address, config.Database) + dconfig.DBName = config.Database + dconfig.User = config.Username + dconfig.Passwd = config.Password + dconfig.Timeout = config.Timeout + dconfig.MultiStatements = true + dconfig.ParseTime = true + dconfig.Loc = time.Local - dataSourceName += "?" - dataSourceName += fmt.Sprintf("timeout=%ds&multiStatements=true&parseTime=true", int32(config.Timeout/time.Second)) - - return dataSourceName + return dconfig.FormatDSN() }