diff --git a/config-raw.json b/config-raw.json index c85ebe651..b425f7c83 100644 --- a/config-raw.json +++ b/config-raw.json @@ -276,7 +276,7 @@ { "key": "enabled", "default_value": "false", - "comment": "Whether to enable redis or not" + "comment": "Whether to enable redis or not." }, { "key": "host", @@ -286,12 +286,37 @@ { "key": "password", "default_value": "", - "comment": "The password used to authenticate against the redis server" + "comment": "The password used to authenticate against the redis server." }, { "key": "db", "default_value": "0", "comment": "0 means default database" + }, + { + "key": "tls", + "default_value": "false", + "comment": "Whether to enable TLS or not." + }, + { + "key": "tlsclientcertpath", + "default_value": "", + "comment": "The path to a client certificate, if you choose to use one." + }, + { + "key": "tlsclientkeypath", + "default_value": "", + "comment": "The path to the client certificate's private key." + }, + { + "key": "tlscacertpath", + "default_value": "", + "comment": "The path to a certificate authority certificate, for verifying the server's certificate." + }, + { + "key": "tlsskipverify", + "default_value": "true", + "comment": "Whether to skip verification of the server's TLS certificate." } ] }, @@ -379,6 +404,21 @@ "key": "forcessl", "default_value": "false", "comment": "By default, Vikunja will try to connect with starttls, use this option to force it to use ssl." + }, + { + "key": "tlsclientcertpath", + "default_value": "", + "comment": "The path to a client certificate, if you choose to use one." + }, + { + "key": "tlsclientkeypath", + "default_value": "", + "comment": "The path to the client certificate's private key." + }, + { + "key": "tlscacertpath", + "default_value": "", + "comment": "The path to a certificate authority certificate, for verifying the server's certificate." } ] }, diff --git a/pkg/config/config.go b/pkg/config/config.go index 645c7299b..227cf984a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -121,22 +121,30 @@ const ( DatabaseTLS Key = `database.tls` DatabaseSchema Key = `database.schema` - MailerEnabled Key = `mailer.enabled` - MailerHost Key = `mailer.host` - MailerPort Key = `mailer.port` - MailerUsername Key = `mailer.username` - MailerPassword Key = `mailer.password` - MailerAuthType Key = `mailer.authtype` - MailerSkipTLSVerify Key = `mailer.skiptlsverify` - MailerFromEmail Key = `mailer.fromemail` - MailerQueuelength Key = `mailer.queuelength` - MailerQueueTimeout Key = `mailer.queuetimeout` - MailerForceSSL Key = `mailer.forcessl` + MailerEnabled Key = `mailer.enabled` + MailerHost Key = `mailer.host` + MailerPort Key = `mailer.port` + MailerUsername Key = `mailer.username` + MailerPassword Key = `mailer.password` + MailerAuthType Key = `mailer.authtype` + MailerSkipTLSVerify Key = `mailer.skiptlsverify` + MailerFromEmail Key = `mailer.fromemail` + MailerQueuelength Key = `mailer.queuelength` + MailerQueueTimeout Key = `mailer.queuetimeout` + MailerForceSSL Key = `mailer.forcessl` + MailerTLSClientCertPath Key = `mailer.tlsclientcertpath` + MailerTLSClientKeyPath Key = `mailer.tlsclientkeypath` + MailerTLSClientCACertPath Key = `mailer.tlsclientcacertpath` - RedisEnabled Key = `redis.enabled` - RedisHost Key = `redis.host` - RedisPassword Key = `redis.password` - RedisDB Key = `redis.db` + RedisEnabled Key = `redis.enabled` + RedisHost Key = `redis.host` + RedisPassword Key = `redis.password` + RedisDB Key = `redis.db` + RedisTLS Key = `redis.tls` + RedisTLSClientCertPath Key = `redis.tlsclientcertpath` + RedisTLSClientKeyPath Key = `redis.tlsclientkeypath` + RedisTLSClientCACertPath Key = `redis.tlsclientcacertpath` + RedisTLSSkipVerify Key = `redis.tlsskipverify` LogEnabled Key = `log.enabled` LogStandard Key = `log.standard` @@ -425,11 +433,19 @@ func InitDefaultConfig() { MailerQueueTimeout.setDefault(30) MailerForceSSL.setDefault(false) MailerAuthType.setDefault("plain") + MailerTLSClientCertPath.setDefault("") + MailerTLSClientKeyPath.setDefault("") + MailerTLSClientCACertPath.setDefault("") // Redis RedisEnabled.setDefault(false) RedisHost.setDefault("localhost:6379") RedisPassword.setDefault("") RedisDB.setDefault(0) + RedisTLS.setDefault(false) + RedisTLSClientCertPath.setDefault("") + RedisTLSClientKeyPath.setDefault("") + RedisTLSClientCACertPath.setDefault("") + RedisTLSSkipVerify.setDefault(false) // Logger LogEnabled.setDefault(true) LogStandard.setDefault("stdout") diff --git a/pkg/mail/mail.go b/pkg/mail/mail.go index 2cc9e50f5..dc31fa8d1 100644 --- a/pkg/mail/mail.go +++ b/pkg/mail/mail.go @@ -19,6 +19,8 @@ package mail import ( "context" "crypto/tls" + "crypto/x509" + "os" "time" "code.vikunja.io/api/pkg/config" @@ -47,13 +49,33 @@ func getClient() (*mail.Client, error) { tlsPolicy = mail.TLSMandatory } + tlsConfig := &tls.Config{ + //#nosec G402 + InsecureSkipVerify: config.MailerSkipTLSVerify.GetBool(), + ServerName: config.MailerHost.GetString(), + MinVersion: tls.VersionTLS12, + } + + if config.MailerTLSClientCertPath.GetString() != "" && config.MailerTLSClientKeyPath.GetString() != "" { + cert, err := tls.LoadX509KeyPair(config.MailerTLSClientCertPath.GetString(), config.MailerTLSClientKeyPath.GetString()) + if err != nil { + log.Fatal("Error loading client certificate and/or key.") + } + tlsConfig.Certificates = []tls.Certificate{cert} + } + if config.MailerTLSClientCACertPath.GetString() != "" { + caCert, err := os.ReadFile(config.MailerTLSClientCACertPath.GetString()) + if err != nil { + log.Fatal("Error loading CA certificate.") + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + tlsConfig.RootCAs = caCertPool + } + opts := []mail.Option{ mail.WithTLSPortPolicy(tlsPolicy), - mail.WithTLSConfig(&tls.Config{ - //#nosec G402 - InsecureSkipVerify: config.MailerSkipTLSVerify.GetBool(), - ServerName: config.MailerHost.GetString(), - }), + mail.WithTLSConfig(tlsConfig), mail.WithPort(config.MailerPort.GetInt()), mail.WithTimeout((config.MailerQueueTimeout.GetDuration() + 3) * time.Second), // 3s more for us to close before mail server timeout mail.WithLogger(log.NewMailLogger(config.LogEnabled.GetBool(), config.LogMail.GetString(), config.LogMailLevel.GetString(), config.LogFormat.GetString())), diff --git a/pkg/red/redis.go b/pkg/red/redis.go index abdc4f6cb..535ccf2f5 100644 --- a/pkg/red/redis.go +++ b/pkg/red/redis.go @@ -18,6 +18,9 @@ package red import ( "context" + "crypto/tls" + "crypto/x509" + "os" "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/log" @@ -40,11 +43,39 @@ func InitRedis() { log.Fatal("No redis host provided.") } - r = redis.NewClient(&redis.Options{ + redisOpts := &redis.Options{ Addr: config.RedisHost.GetString(), Password: config.RedisPassword.GetString(), DB: config.RedisDB.GetInt(), - }) + } + + if config.RedisTLS.GetBool() { + tlsConfig := &tls.Config{ + MinVersion: tls.VersionTLS12, + } + if config.RedisTLSClientCertPath.GetString() != "" && config.RedisTLSClientKeyPath.GetString() != "" { + cert, err := tls.LoadX509KeyPair(config.RedisTLSClientCertPath.GetString(), config.RedisTLSClientKeyPath.GetString()) + if err != nil { + log.Fatal("Error loading client certificate and/or key.") + } + tlsConfig.Certificates = []tls.Certificate{cert} + } + if config.RedisTLSClientCACertPath.GetString() != "" { + caCert, err := os.ReadFile(config.RedisTLSClientCACertPath.GetString()) + if err != nil { + log.Fatal("Error loading CA certificate.") + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + tlsConfig.RootCAs = caCertPool + } + if config.RedisTLSSkipVerify.GetBool() { + tlsConfig.InsecureSkipVerify = config.RedisTLSSkipVerify.GetBool() + } + redisOpts.TLSConfig = tlsConfig + } + + r = redis.NewClient(redisOpts) err := r.Ping(context.Background()).Err() if err != nil {