Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔥 feat: Add support for configuring TLS Min Version #3248

Merged
merged 7 commits into from
Dec 16, 2024

Conversation

dozheiny
Copy link
Contributor

This pull request introduces a new configuration option to set the minimum TLS version in the listen.go file. The most important changes include adding the TLSMinVersion field to the ListenConfig struct and updating the default configuration and relevant methods to use this new field.

New TLS Configuration Option:

  • listen.go: Added TLSMinVersion field to the ListenConfig struct to allow setting the minimum TLS version.
  • listen.go: Set the default value of TLSMinVersion to tls.VersionTLS12 in the listenConfigDefault function.
  • listen.go: Updated the listenConfigDefault function to ensure TLSMinVersion is set to tls.VersionTLS12 if not provided.

Code Updates to Use New Configuration:

  • listen.go: Modified the Listen method to use the TLSMinVersion from the ListenConfig struct for the tls.Config object.

This commit will resolve #3239

This commit will resolve gofiber#3239
For more info: gofiber#3239
@dozheiny dozheiny requested a review from a team as a code owner December 12, 2024 18:34
@dozheiny dozheiny requested review from gaby, sixcolors, ReneWerner87 and efectn and removed request for a team December 12, 2024 18:34
Copy link
Contributor

coderabbitai bot commented Dec 12, 2024

Walkthrough

The changes introduce a new field, TLSMinVersion, to the ListenConfig struct in the fiber package, allowing users to specify the minimum TLS version for secure connections. The listenConfigDefault function initializes this field to tls.VersionTLS12 if not provided. Additionally, the Listen method in the App struct is updated to utilize the TLSMinVersion for TLS configuration, enhancing flexibility in TLS setup without altering the overall control flow.

Changes

File Change Summary
listen.go Added TLSMinVersion uint16 to ListenConfig; updated listenConfigDefault and Listen methods to utilize TLSMinVersion for TLS configuration.
docs/whats_new.md Updated documentation to reflect changes in version 3, including removal of deprecated methods, introduction of new methods, and adjustments to configuration options.
listen_test.go Added Test_Listen_TLSMinVersion for new TLSMinVersion checks; updated Test_Listen_Prefork with additional assertions.
docs/api/fiber.md Updated documentation for new New method and enhanced ListenConfig structure to include TLSMinVersion and other configuration options.

Assessment against linked issues

Objective Addressed Explanation
Make tls.Config MinVersion configurable (#3239)

Possibly related PRs

Suggested reviewers

  • sixcolors
  • ReneWerner87
  • efectn

Poem

🐇 In the meadow, where bunnies play,
A new TLS version brightens the day.
With TLSMinVersion, oh what a treat,
Secure connections, safe and neat!
Hopping along, we cheer with glee,
For flexible setups, as happy as can be! 🌼

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. This feature will be included in our Pro Plan when released.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 739aef0 and 486dab7.

📒 Files selected for processing (1)
  • listen_test.go (1 hunks)
🔇 Additional comments (1)
listen_test.go (1)

239-274: 🛠️ Refactor suggestion

Enhance test coverage and improve code organization.

While the test covers essential scenarios, consider the following improvements:

  1. Add test case for TLS 1.2 (default version)
  2. Verify the actual TLS version during handshake
  3. Use consistent port numbers across test cases
  4. Extract duplicate shutdown logic into a helper function
 // 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
+        _ = app.Listen(":0", ListenConfig{TLSMinVersion: tls.VersionTLS10}) //nolint:errcheck // ignore error
     })
     require.Panics(t, func() {
-        _ = app.Listen(":443", ListenConfig{TLSMinVersion: tls.VersionTLS11}) //nolint:errcheck // ignore error
+        _ = app.Listen(":0", 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
+        _ = app.Listen(":0", 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
+        _ = app.Listen(":0", ListenConfig{DisableStartupMessage: true, EnablePrefork: true, TLSMinVersion: tls.VersionTLS11}) //nolint:errcheck // ignore error
     })
 
+    // Helper function for shutdown
+    shutdownAfterDelay := func(app *App) {
+        go func() {
+            time.Sleep(1000 * time.Millisecond)
+            assert.NoError(t, app.Shutdown())
+        }()
+    }
+
+    // Test TLS 1.2 (default version)
+    shutdownAfterDelay(app)
+    require.NoError(t, app.Listen(":0", ListenConfig{
+        TLSMinVersion: tls.VersionTLS12,
+        CertFile:    "./.github/testdata/ssl.pem",
+        CertKeyFile: "./.github/testdata/ssl.key",
+    }))
+
     // Valid TLSMinVersion
-    go func() {
-        time.Sleep(1000 * time.Millisecond)
-        assert.NoError(t, app.Shutdown())
-    }()
+    shutdownAfterDelay(app)
     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}))
+    shutdownAfterDelay(app)
+    require.NoError(t, app.Listen(":0", ListenConfig{DisableStartupMessage: true, EnablePrefork: true, TLSMinVersion: tls.VersionTLS13}))
+
+    // Verify TLS version during handshake
+    ln := fasthttputil.NewInmemoryListener()
+    go func() {
+        app.Listener(ln, ListenConfig{
+            TLSMinVersion: tls.VersionTLS13,
+            CertFile:    "./.github/testdata/ssl.pem",
+            CertKeyFile: "./.github/testdata/ssl.key",
+        })
+    }()
+
+    conn, err := tls.Dial("tcp", ln.Addr().String(), &tls.Config{
+        InsecureSkipVerify: true,
+    })
+    require.NoError(t, err)
+    require.Equal(t, uint16(tls.VersionTLS13), conn.ConnectionState().Version)
+    conn.Close()
 }

Likely invalid or redundant comment.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented Dec 12, 2024

Codecov Report

Attention: Patch coverage is 80.00000% with 2 lines in your changes missing coverage. Please review.

Project coverage is 82.70%. Comparing base (1134e1f) to head (486dab7).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
listen.go 80.00% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3248   +/-   ##
=======================================
  Coverage   82.69%   82.70%           
=======================================
  Files         115      115           
  Lines       11383    11389    +6     
=======================================
+ Hits         9413     9419    +6     
  Misses       1562     1562           
  Partials      408      408           
Flag Coverage Δ
unittests 82.70% <80.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
listen.go (1)

136-136: Consider using TLS 1.3 as the default minimum version.

While TLS 1.2 is secure, TLS 1.3 (introduced in 2018) offers improved security and performance. Consider using tls.VersionTLS13 as the default, while allowing users to downgrade to TLS 1.2 if needed for compatibility.

-TLSMinVersion:   tls.VersionTLS12,
+TLSMinVersion:   tls.VersionTLS13,
-   cfg.TLSMinVersion = tls.VersionTLS12
+   cfg.TLSMinVersion = tls.VersionTLS13

Also applies to: 156-159

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a63bd34 and 6256c85.

📒 Files selected for processing (1)
  • listen.go (5 hunks)
🔇 Additional comments (2)
listen.go (2)

53-57: LGTM! Field addition is well-documented and properly typed.

The new TLSMinVersion field is correctly implemented with appropriate type and documentation.


182-182: Verify TLSConfigFunc behavior with MinVersion.

The implementation correctly sets MinVersion in both TLS configurations. However, be aware that TLSConfigFunc can override this setting. Consider documenting this behavior.

Also applies to: 206-206

✅ Verification successful

Let me gather more information about the actual implementation of TLSConfigFunc usage in the codebase.


Let me try a different approach to find the TLSConfigFunc usage.


Let me check the full context around where TLSConfigFunc is called to understand the order of operations.


TLSConfigFunc behavior with MinVersion is correctly implemented

The code shows that MinVersion is set before TLSConfigFunc is called, and TLSConfigFunc is explicitly designed to allow customization of the TLS configuration. This is the expected behavior as:

  1. MinVersion is set first in the TLS configuration
  2. TLSConfigFunc is called afterward, allowing intentional overrides if needed
  3. The behavior is documented in the config struct with clear comments
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any TLSConfigFunc usage that might override MinVersion
rg -l 'TLSConfigFunc.*tls\.Config' | while read -r file; do
  echo "=== $file ==="
  rg -A 5 'TLSConfigFunc.*tls\.Config' "$file"
done

Length of output: 1510


Script:

#!/bin/bash
# Search for the actual implementation where TLSConfigFunc is called
ast-grep --pattern 'if $_.TLSConfigFunc != nil {
  $$$
}'

Length of output: 59


Script:

#!/bin/bash
# Search for TLSConfigFunc usage in the implementation
rg -A 5 'TLSConfigFunc.*\(' --type go

Length of output: 994


Script:

#!/bin/bash
# Get more context around the TLSConfigFunc usage
rg -B 10 -A 10 'cfg\.TLSConfigFunc\(tlsConfig\)' --type go

Length of output: 781

@gaby gaby changed the title Make tls.Config MinVersion configurable 🔥 feat: Add support for configuring TLS Min Version Dec 13, 2024
@gaby gaby added this to the v3 milestone Dec 13, 2024
@gaby
Copy link
Member

gaby commented Dec 13, 2024

@dozheiny Can you also update the documentation under the docs directory.

To fix the struct issue, the Makefile in this repo has a make betteralign command that will fix it. https://github.com/gofiber/fiber/blob/main/Makefile#L58

listen.go Outdated Show resolved Hide resolved
@dozheiny
Copy link
Contributor Author

Should I change the default value of the TLS version to 1.3?

@gaby
Copy link
Member

gaby commented Dec 13, 2024

Should I change the default value of the TLS version to 1.3?

V1.2 is fine as default. Not everything supports 1.3, and 1.2 is still active

@gaby
Copy link
Member

gaby commented Dec 13, 2024

@dozheiny Although we shouldn't allow the usage of TLS1.0 and TLS1.1

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
docs/whats_new.md (1)

133-139: Enhance TLS minimum version documentation.

While the documentation accurately describes the new feature, consider adding:

  1. List of available TLS version constants (e.g., tls.VersionTLS10, tls.VersionTLS11, tls.VersionTLS12, tls.VersionTLS13).
  2. Security implications of choosing different TLS versions.
  3. Information about the default value behavior.
  4. More comprehensive configuration examples.

Consider expanding the documentation with this example:

 ### 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.
 
+Available TLS version constants:
+- `tls.VersionTLS10` (not recommended for security reasons)
+- `tls.VersionTLS11` (not recommended for security reasons)
+- `tls.VersionTLS12` (recommended minimum)
+- `tls.VersionTLS13` (most secure)
+
+The default value is `tls.VersionTLS12` if not specified.
+
+Example usage:
 ```go
 app.Listen(":444", fiber.ListenConfig{TLSMinVersion: tls.VersionTLS12})

+For enhanced security, you can enforce TLS 1.3:
+```go
+app.Listen(":444", fiber.ListenConfig{

  • TLSMinVersion: tls.VersionTLS13,
  • // Additional TLS configuration...
    +})
    +```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6256c853a2d6ea2226470a77d0d6ac4fdb6a26d1 and b5ae998fce2cdcb0975c3e5c7b408b9e6343d126.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `docs/whats_new.md` (1 hunks)
* `listen.go` (5 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* listen.go

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

@dozheiny
Copy link
Contributor Author

@gaby So I think creating a type for TLS versions is the best way.

@gaby
Copy link
Member

gaby commented Dec 13, 2024

@dozheiny You can compare using:

if cfg.TLSMinVersion == 0 {
    cfg.TLSMinVersion = tls.VersionTLS12
}

if cfg.TLSMinVersion =! tls.VersionTLS12 || cfg.TLSMinVersion =! tls.VersionTLS13 {
    panic("Supported TLS versions: 1.2, 1.3")
}

Right? That way we dont have a custom type

@dozheiny
Copy link
Contributor Author

@gaby But we break the application with panic.
Also if we raise the error, We change the output of functions.

@gaby
Copy link
Member

gaby commented Dec 13, 2024

@gaby But we break the application with panic. Also if we raise the error, We change the output of functions.

That's fine cause its an invalid configuration. If you search for "panic" in the code base you will see we use it often for bad configs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
listen.go (2)

111-115: LGTM! Consider enhancing the documentation.

The new TLSMinVersion field is well-integrated with appropriate type and documentation.

Consider adding the actual TLS version constants in the documentation for clarity:

 // TLSMinVersion allows to set tls minimum version.
 //
-// Default: VersionTLS12
+// Default: tls.VersionTLS12 (0x0303)
+// Supported: tls.VersionTLS12 (0x0303), tls.VersionTLS13 (0x0304)
 // WARNING: TLS1.0 and TLS1.1 versions are not supported.

157-163: LGTM! Consider improving the error message.

The initialization and validation of TLSMinVersion are well-implemented. The panic on invalid versions aligns with the framework's approach to configuration errors.

Consider making the panic message more informative:

-		panic("Supported TLS versions: 1.2, 1.3")
+		panic(fmt.Sprintf("fiber: unsupported TLS version: %#x. Supported versions are tls.VersionTLS12 (0x0303) and tls.VersionTLS13 (0x0304)", cfg.TLSMinVersion))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5ae998 and e977d53.

📒 Files selected for processing (1)
  • listen.go (5 hunks)

listen.go Show resolved Hide resolved
@dozheiny dozheiny requested a review from gaby December 14, 2024 11:02
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e977d53 and d668fa8.

📒 Files selected for processing (2)
  • listen.go (5 hunks)
  • listen_test.go (1 hunks)
🔇 Additional comments (4)
listen.go (3)

111-115: LGTM! Well-documented field addition.

The new TLSMinVersion field is properly typed and documented, with clear warnings about unsupported versions.


157-163: LGTM! Robust validation of TLS version.

The validation ensures only secure TLS versions (1.2 and 1.3) are allowed, with appropriate error handling via panic, which is consistent with the codebase's approach to configuration errors.


186-187: LGTM! Consistent TLS version configuration.

The TLSMinVersion is correctly applied in both TLS configuration scenarios.

Also applies to: 210-211

listen_test.go (1)

236-248: LGTM! Comprehensive validation tests.

The test cases thoroughly verify that using unsupported TLS versions (1.0 and 1.1) triggers panics in both regular and prefork modes.

listen_test.go Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
listen.go (1)

157-163: Consider using constants for supported TLS versions.

The validation logic is correct, but consider defining constants for supported TLS versions to improve code maintainability.

+const (
+    MinTLSVersion = tls.VersionTLS12
+    MaxTLSVersion = tls.VersionTLS13
+)

 if cfg.TLSMinVersion == 0 {
-    cfg.TLSMinVersion = tls.VersionTLS12
+    cfg.TLSMinVersion = MinTLSVersion
 }

-if cfg.TLSMinVersion != tls.VersionTLS12 && cfg.TLSMinVersion != tls.VersionTLS13 {
+if cfg.TLSMinVersion < MinTLSVersion || cfg.TLSMinVersion > MaxTLSVersion {
     panic("unsupported TLS version, please use tls.VersionTLS12 or tls.VersionTLS13")
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d668fa8 and 739aef0.

📒 Files selected for processing (2)
  • docs/api/fiber.md (1 hunks)
  • listen.go (5 hunks)
🔇 Additional comments (2)
listen.go (1)

111-115: LGTM! Well-documented field addition.

The new TLSMinVersion field is properly documented with clear default value and warning about unsupported versions.

docs/api/fiber.md (1)

119-120: LGTM! Clear and accurate documentation.

The documentation for both AutoCertManager and TLSMinVersion fields is clear, accurate, and consistent with the implementation.

listen.go Show resolved Hide resolved
@dozheiny
Copy link
Contributor Author

@gaby Thanks for fixing lint issues and adding tests

Copy link
Member

@gaby gaby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@ReneWerner87 ReneWerner87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

🔥 feat: Make tls.Config MinVersion configurable
3 participants