From 154c74d5785aa3f6db2f9f51c206e4891c5477e7 Mon Sep 17 00:00:00 2001 From: Iliya Date: Mon, 16 Dec 2024 11:37:41 +0330 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20feat:=20Add=20support=20for=20co?= =?UTF-8?q?nfiguring=20TLS=20Min=20Version=20(#3248)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make tls.Config MinVersion configurable This commit will resolve #3239 For more info: https://github.com/gofiber/fiber/issues/3239 * Add documents about tls minimum version configurable * Add if statement for don't allow to use TLS1.0 and TLS1.1 * Fix lint issues, add test for panic() * Update docs * Add test with valid TLS version --------- Co-authored-by: Juan Calderon-Perez --- docs/api/fiber.md | 3 ++- docs/whats_new.md | 8 ++++++++ listen.go | 23 +++++++++++++++++++---- listen_test.go | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/docs/api/fiber.md b/docs/api/fiber.md index a34a5d94..17cf3896 100644 --- a/docs/api/fiber.md +++ b/docs/api/fiber.md @@ -116,7 +116,8 @@ app.Listen(":8080", fiber.ListenConfig{ | OnShutdownError | `func(err error)` | Allows to customize error behavior when gracefully shutting down the server by given signal. Prints error with `log.Fatalf()` | `nil` | | OnShutdownSuccess | `func()` | Allows customizing success behavior when gracefully shutting down the server by given signal. | `nil` | | TLSConfigFunc | `func(tlsConfig *tls.Config)` | Allows customizing `tls.Config` as you want. | `nil` | -| AutoCertManager | `func(tlsConfig *tls.Config)` | Manages TLS certificates automatically using the ACME protocol. Enables integration with Let's Encrypt or other ACME-compatible providers. | `nil` | +| AutoCertManager | `*autocert.Manager` | Manages TLS certificates automatically using the ACME protocol. Enables integration with Let's Encrypt or other ACME-compatible providers. | `nil` | +| TLSMinVersion | `uint16` | Allows customizing the TLS minimum version. | `tls.VersionTLS12` | ### Listen diff --git a/docs/whats_new.md b/docs/whats_new.md index bfc6f25c..eadc1afa 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -130,6 +130,14 @@ In this example, a custom context `CustomCtx` is created with an additional meth +### Configurable TLS Minimum Version + +We have added support for configuring the TLS minimum version. This field allows you to set the TLS minimum version for TLSAutoCert and the server listener. + +```go +app.Listen(":444", fiber.ListenConfig{TLSMinVersion: tls.VersionTLS12}) +``` + #### TLS AutoCert support (ACME / Let's Encrypt) We have added native support for automatic certificates management from Let's Encrypt and any other ACME-based providers. diff --git a/listen.go b/listen.go index e0c55369..793d36d2 100644 --- a/listen.go +++ b/listen.go @@ -108,6 +108,12 @@ type ListenConfig struct { // Default: 10 * time.Second ShutdownTimeout time.Duration `json:"shutdown_timeout"` + // TLSMinVersion allows to set TLS minimum version. + // + // Default: tls.VersionTLS12 + // WARNING: TLS1.0 and TLS1.1 versions are not supported. + TLSMinVersion uint16 `json:"tls_min_version"` + // When set to true, it will not print out the «Fiber» ASCII art and listening address. // // Default: false @@ -128,6 +134,7 @@ type ListenConfig struct { func listenConfigDefault(config ...ListenConfig) ListenConfig { if len(config) < 1 { return ListenConfig{ + TLSMinVersion: tls.VersionTLS12, ListenerNetwork: NetworkTCP4, OnShutdownError: func(err error) { log.Fatalf("shutdown: %v", err) //nolint:revive // It's an option @@ -147,6 +154,14 @@ func listenConfigDefault(config ...ListenConfig) ListenConfig { } } + if cfg.TLSMinVersion == 0 { + cfg.TLSMinVersion = tls.VersionTLS12 + } + + if cfg.TLSMinVersion != tls.VersionTLS12 && cfg.TLSMinVersion != tls.VersionTLS13 { + panic("unsupported TLS version, please use tls.VersionTLS12 or tls.VersionTLS13") + } + return cfg } @@ -168,8 +183,8 @@ func (app *App) Listen(addr string, config ...ListenConfig) error { } tlsHandler := &TLSHandler{} - tlsConfig = &tls.Config{ - MinVersion: tls.VersionTLS12, + tlsConfig = &tls.Config{ //nolint:gosec // This is a user input + MinVersion: cfg.TLSMinVersion, Certificates: []tls.Certificate{ cert, }, @@ -192,8 +207,8 @@ func (app *App) Listen(addr string, config ...ListenConfig) error { // Attach the tlsHandler to the config app.SetTLSHandler(tlsHandler) } else if cfg.AutoCertManager != nil { - tlsConfig = &tls.Config{ - MinVersion: tls.VersionTLS12, + tlsConfig = &tls.Config{ //nolint:gosec // This is a user input + MinVersion: cfg.TLSMinVersion, GetCertificate: cfg.AutoCertManager.GetCertificate, NextProtos: []string{"http/1.1", "acme-tls/1"}, } diff --git a/listen_test.go b/listen_test.go index 123cf2b3..032f7d32 100644 --- a/listen_test.go +++ b/listen_test.go @@ -236,6 +236,43 @@ func Test_Listen_Prefork(t *testing.T) { require.NoError(t, app.Listen(":99999", ListenConfig{DisableStartupMessage: true, EnablePrefork: true})) } +// go test -run Test_Listen_TLSMinVersion +func Test_Listen_TLSMinVersion(t *testing.T) { + testPreforkMaster = true + + app := New() + + // Invalid TLSMinVersion + require.Panics(t, func() { + _ = app.Listen(":443", ListenConfig{TLSMinVersion: tls.VersionTLS10}) //nolint:errcheck // ignore error + }) + require.Panics(t, func() { + _ = app.Listen(":443", ListenConfig{TLSMinVersion: tls.VersionTLS11}) //nolint:errcheck // ignore error + }) + + // Prefork + require.Panics(t, func() { + _ = app.Listen(":443", ListenConfig{DisableStartupMessage: true, EnablePrefork: true, TLSMinVersion: tls.VersionTLS10}) //nolint:errcheck // ignore error + }) + require.Panics(t, func() { + _ = app.Listen(":443", ListenConfig{DisableStartupMessage: true, EnablePrefork: true, TLSMinVersion: tls.VersionTLS11}) //nolint:errcheck // ignore error + }) + + // Valid TLSMinVersion + go func() { + time.Sleep(1000 * time.Millisecond) + assert.NoError(t, app.Shutdown()) + }() + require.NoError(t, app.Listen(":0", ListenConfig{TLSMinVersion: tls.VersionTLS13})) + + // Valid TLSMinVersion with Prefork + go func() { + time.Sleep(1000 * time.Millisecond) + assert.NoError(t, app.Shutdown()) + }() + require.NoError(t, app.Listen(":99999", ListenConfig{DisableStartupMessage: true, EnablePrefork: true, TLSMinVersion: tls.VersionTLS13})) +} + // go test -run Test_Listen_TLS func Test_Listen_TLS(t *testing.T) { app := New()