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: whitelist connection gater #31

Merged
merged 23 commits into from
Oct 28, 2024
Merged

Conversation

skosito
Copy link
Contributor

@skosito skosito commented Oct 22, 2024

  • removes dht code
  • adds whitelist peers conn gater

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a whitelist mechanism for peer connections, enhancing security and control over which peers can connect.
    • Added functionality to convert Bech32 encoded public keys to peer IDs.
  • Bug Fixes

    • Improved error handling in peer communication setup and initialization processes.
  • Tests

    • Updated test suites to incorporate whitelisted peers in communication setups, refining peer interaction during tests.

Copy link

coderabbitai bot commented Oct 23, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request introduces significant modifications across several files to integrate a peer whitelisting mechanism into the communication and TSS (Threshold Signature Scheme) functionalities. Key changes include the addition of whitelistedPeers []peer.ID as a parameter in various functions, enhancing the initialization of communication instances and TSS servers. The new functionality allows for better control over peer interactions by filtering connections based on a specified whitelist, which is populated using the Bech32PubkeyToPeerID function.

Changes

File Path Change Summary
cmd/tss/main.go Added import for peer package; modified NewTss to accept []peer.ID as a new parameter.
conversion/conversion.go Introduced Bech32PubkeyToPeerID function for converting Bech32 public keys to peer.ID.
keygen/ecdsa/keygen_test.go Updated SetUpTest to include whitelistedPeers in NewCommunication calls.
keygen/eddsa/keygen_test.go Updated SetUpTest to include whitelistedPeers in NewCommunication calls.
keysign/ecdsa/keysign_old_test.go Updated SetUpTest to include whitelistedPeers in NewCommunication calls.
keysign/ecdsa/keysign_test.go Updated SetUpTest to include whitelistedPeers in NewCommunication calls.
keysign/eddsa/keysign_test.go Updated SetUpTest to include whitelistedPeers in NewCommunication calls.
p2p/communication.go Added whitelistedPeers field to Communication struct; updated NewCommunication to accept it.
p2p/communication_test.go Updated tests to include whitelistedPeers in NewCommunication calls.
p2p/whitelist_connection_gater.go Introduced WhitelistConnectionGater struct for managing connections based on a whitelist.
tss/tss.go Updated NewTss to accept whitelistedPeers and enhanced error handling.
tss/tss_4nodes_test.go Updated getTssServer to include whitelistedPeers in NewTss calls.
tss/tss_4nodes_zeta_test.go Updated getTssServer to include whitelistedPeers in NewTss calls.

Possibly related PRs

  • Add concurrency and scale testing #22: This PR modifies the NewCommunication function to include a whitelistedPeers parameter, directly related to the changes in the main PR where the NewTss function was updated to accept a list of peer.ID. Both PRs enhance peer communication handling through a whitelist mechanism.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5558cea and 48efd48.

📒 Files selected for processing (1)
  • p2p/whitelist_connection_gater.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • p2p/whitelist_connection_gater.go

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 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

@ws4charlie ws4charlie left a comment

Choose a reason for hiding this comment

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

looks good. minor comment

Copy link
Collaborator

@brewmaster012 brewmaster012 left a comment

Choose a reason for hiding this comment

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

Looks good.
Is there a negative test--i.e. a non-whitelisted connection is blocked?

@skosito skosito requested a review from brewmaster012 October 28, 2024 18:52
@skosito
Copy link
Contributor Author

skosito commented Oct 28, 2024

Looks good. Is there a negative test--i.e. a non-whitelisted connection is blocked?

added

@skosito skosito marked this pull request as ready for review October 28, 2024 18:52
@skosito skosito changed the title Whitelist connection gater [draft] Whitelist connection gater Oct 28, 2024
@skosito skosito changed the title Whitelist connection gater feat: whitelist connection gater Oct 28, 2024
Copy link

@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: 12

🧹 Outside diff range and nitpick comments (10)
p2p/communication_test.go (2)

21-21: Consider adding test cases for non-empty whitelist scenarios.

While testing with an empty whitelist is valid, consider adding test cases that verify behavior with non-empty whitelists to ensure comprehensive coverage of the new functionality.

Would you like me to help generate additional test cases for various whitelist scenarios?


99-104: Enhance test case documentation.

While the test case correctly verifies behavior with empty whitelist, the comment could be more descriptive to explain the expected behavior.

-  // same as above, just without whitelisted peers
+  // Verify that connections fail when no peers are whitelisted, even with valid multiaddrs
conversion/conversion.go (1)

216-226: Add documentation for the new function.

Consider adding a doc comment to describe the function's purpose, parameters, and potential error cases.

+// Bech32PubkeyToPeerID converts a Bech32-encoded public key to a libp2p peer ID.
+// It expects a valid Bech32-encoded public key string and returns the corresponding
+// peer.ID or an error if the conversion fails.
 func Bech32PubkeyToPeerID(pubKey string) (peer.ID, error) {
keygen/eddsa/keygen_test.go (1)

103-108: LGTM! Consider extracting test data setup.

The whitelist initialization is well-implemented with proper error handling. However, consider moving the test public keys conversion to a helper function or SetUpSuite to keep the test setup more maintainable.

 func (s *EddsaKeygenTestSuite) SetUpSuite(c *C) {
     common.InitLog("info", true, "keygen_test")
     conversion.SetupBech32Prefix()
+    // Initialize whitelisted peers
+    for _, pk := range testPubKeys {
+        peer, err := conversion.Bech32PubkeyToPeerID(pk)
+        c.Assert(err, IsNil)
+        s.whitelistedPeers = append(s.whitelistedPeers, peer)
+    }
     // ... rest of the setup
 }
keysign/eddsa/keysign_test.go (1)

155-156: LGTM: Non-bootstrap nodes setup with whitelist.

The communication setup for non-bootstrap nodes correctly incorporates both the whitelist parameter and multiAddr for peer discovery.

Consider adding test cases that verify:

  1. Successful connections between whitelisted peers
  2. Network formation with partial whitelist (subset of peers)
keygen/ecdsa/keygen_test.go (2)

117-122: LGTM! Consider adding negative test cases.

The whitelisted peers initialization looks good. However, consider adding test cases to verify the behavior with invalid public keys.

Add test cases to verify:

  1. Invalid Bech32 public key format
  2. Empty public key
  3. Malformed public key

127-129: LGTM! Consider adding documentation.

The bootstrap node setup is correct. Consider adding a comment explaining that this is the bootstrap node configuration.

Add a comment before line 127:

// Configure the bootstrap node (first party) with no initial peers
keysign/ecdsa/keysign_test.go (1)

152-153: Improve clarity of NewCommunication initialization.

The empty string parameter and the distinction between bootstrap and subsequent nodes could be made more explicit:

-comm, err := p2p.NewCommunication("asgard", nil, ports[i], "", whitelistedPeers)
+const bootstrapAddr = "" // Empty string for bootstrap node
+comm, err := p2p.NewCommunication("asgard", nil, ports[i], bootstrapAddr, whitelistedPeers)

Consider adding a comment to explain the different initialization patterns:

// Initialize bootstrap node without multiaddress
if i == 0 {
    comm, err := p2p.NewCommunication("asgard", nil, ports[i], bootstrapAddr, whitelistedPeers)
    // ...
} else {
    // Initialize subsequent nodes with bootstrap node's multiaddress
    comm, err := p2p.NewCommunication("asgard", []maddr.Multiaddr{multiAddr}, ports[i], bootstrapAddr, whitelistedPeers)
    // ...
}

Also applies to: 158-159

p2p/communication.go (2)

65-65: Add documentation for the whitelisted peers field.

Consider adding a comment explaining the purpose and implications of the whitelistedPeers field, particularly its role in connection gating.

+	// whitelistedPeers contains the list of peer IDs that are allowed to connect
+	// to this node. If empty, all peer connections will be rejected.
 	whitelistedPeers []peer.ID

Line range hint 331-346: Consider complete DHT removal.

The code still initializes and uses DHT for peer discovery, although it's scheduled for shutdown after 5 minutes. Since the PR objective is to remove DHT:

  1. Consider removing DHT initialization entirely since peer connections are now whitelisted
  2. The 5-minute DHT shutdown might be unnecessary if we're not using DHT for discovery
-	kademliaDHT, err := dht.New(ctx, h, dht.Mode(dht.ModeServer))
-	if err != nil {
-		return fmt.Errorf("fail to create DHT: %w", err)
-	}
-	c.logger.Debug().Msg("Bootstrapping the DHT")
-	if err = kademliaDHT.Bootstrap(ctx); err != nil {
-		return fmt.Errorf("fail to bootstrap DHT: %w", err)
-	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f8b548c and 5558cea.

📒 Files selected for processing (13)
  • cmd/tss/main.go (2 hunks)
  • conversion/conversion.go (1 hunks)
  • keygen/ecdsa/keygen_test.go (1 hunks)
  • keygen/eddsa/keygen_test.go (1 hunks)
  • keysign/ecdsa/keysign_old_test.go (1 hunks)
  • keysign/ecdsa/keysign_test.go (1 hunks)
  • keysign/eddsa/keysign_test.go (1 hunks)
  • p2p/communication.go (3 hunks)
  • p2p/communication_test.go (3 hunks)
  • p2p/whitelist_connection_gater.go (1 hunks)
  • tss/tss.go (3 hunks)
  • tss/tss_4nodes_test.go (2 hunks)
  • tss/tss_4nodes_zeta_test.go (2 hunks)
🔇 Additional comments (18)
cmd/tss/main.go (2)

15-15: LGTM: Import required for peer whitelisting.

The addition of the peer package import is necessary for the new whitelisting functionality.


67-67: Verify whitelist implementation and test coverage.

Let's verify the existence of negative tests and proper implementation of connection gating.

✅ Verification successful

Let me gather more information with a different search strategy.


Whitelist implementation is properly secured with comprehensive connection gating

The implementation includes:

  • Robust whitelist validation in tss/tss.go that prevents initialization with empty whitelist
  • Complete connection gating implementation in p2p/whitelist_connection_gater.go that:
    • Intercepts peer connections at multiple levels (dial, secure, upgrade)
    • Properly validates peers against whitelist
    • Includes detailed logging for both allowed and denied connections
  • Test coverage across multiple packages including tss, keygen, and keysign
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for negative tests and connection gating implementation

# Test 1: Look for negative test cases
echo "Checking for negative test cases..."
rg -l "TestTssServer.*Whitelist" -g "**/*_test.go"

# Test 2: Verify connection gating implementation
echo "Checking connection gating implementation..."
ast-grep --pattern 'func ($handler *$_) HandlePeerDial($_) {
  $$$
}'

Length of output: 304


Script:

#!/bin/bash
# Search for whitelist-related code and tests more broadly

# Look for whitelist-related test files
echo "Searching for whitelist-related test files..."
rg -l "whitelist|allowlist" -g "**/*_test.go" -i

# Look for whitelist implementation
echo "Searching for whitelist implementation..."
rg -A 5 "whitelist|allowlist" -g "!**/*_test.go" -i

# Check for connection handling/gating
echo "Checking connection handling..."
rg -A 5 "HandlePeerDial|ConnGater" -i

Length of output: 6800

p2p/communication_test.go (3)

42-55: LGTM! Well-structured test setup.

The peer ID generation and bootstrap setup is well-implemented with proper error handling and use of generated keys for test peers.


76-89: LGTM! Comprehensive error handling test cases.

The test cases effectively verify both failure scenarios with invalid peers and recovery scenarios with mixed valid/invalid peers.


63-69: 🛠️ Refactor suggestion

Add validation for whitelist enforcement.

While the test verifies successful communication setup, it should also validate that the whitelist is being enforced. Consider adding assertions to verify that only whitelisted peers can establish connections.

Add assertions like:

// Verify connection is allowed for whitelisted peer
c.Assert(comm.IsAllowed(id1), Equals, true)
// Verify connection is denied for non-whitelisted peer
c.Assert(comm.IsAllowed(nonWhitelistedID), Equals, false)
conversion/conversion.go (1)

216-226: Implementation looks good, verify integration with whitelist feature.

The function implementation is clean and follows good practices. Let's verify its usage in the whitelist feature implementation.

✅ Verification successful

Integration with whitelist feature verified and properly implemented

The Bech32PubkeyToPeerID function is correctly integrated with the whitelist feature:

  • Used in tss, keygen, and keysign packages to convert public keys to peer IDs for whitelist initialization
  • Integrated with WhitelistConnectionGater in p2p package for peer validation
  • Properly enforced in NewTss constructor with validation for empty whitelist
  • Successfully used in test suites across multiple packages demonstrating correct integration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of Bech32PubkeyToPeerID in whitelist implementation

# Test 1: Check for function usage in test files
echo "Checking usage in test files..."
rg -l "Bech32PubkeyToPeerID" --type go

# Test 2: Check for whitelist-related code that might use this function
echo "Checking whitelist implementation..."
rg -A 5 "whitelistedPeers" --type go

Length of output: 14332

tss/tss_4nodes_zeta_test.go (2)

17-17: LGTM!

The addition of the peer package import is appropriate for the new whitelisting functionality.


238-244: Verify non-whitelisted connection rejection.

While the PR comments mention adding negative tests, this test file doesn't explicitly verify that non-whitelisted connections are rejected. Consider adding test cases that:

  1. Attempt to connect with a non-whitelisted peer
  2. Verify that the connection is rejected
  3. Ensure the TSS operation fails appropriately

Let's check if negative tests exist elsewhere:

✅ Verification successful

Non-whitelisted peer rejection is properly implemented

The codebase already implements robust peer whitelisting through libp2p's ConnectionGater interface:

  1. The WhitelistConnectionGater is configured during host creation with whitelisted peers
  2. Connection attempts are intercepted at multiple levels:
    • InterceptPeerDial: Validates outbound connection attempts
    • InterceptSecured: Validates both inbound and outbound connections after security handshake
  3. The peerAllowed method enforces whitelist validation by checking against the pre-configured whitelist map

The test can focus on the successful case since the connection rejection is handled at the libp2p level through the connection gater, which is a proven and tested component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test files that might contain negative tests for whitelisting
rg -l "whitelistedPeers.*\[\]peer\.ID" --type go | grep "_test\.go$" | while read -r file; do
    echo "=== Checking $file for negative tests ==="
    rg -A 5 "TestNon.*Whitelist|test.*reject.*connection" "$file"
done

Length of output: 1982


Script:

#!/bin/bash
# Let's check for any whitelist-related connection handling code
rg -A 10 "func.*NewTss" tss/tss.go

# Check for any connection rejection or whitelist validation logic
rg -A 10 "whitelist.*peer" tss/tss.go p2p/communication.go

# Check for any connection handling in p2p layer
rg -A 10 "func.*handleNewPeer|func.*handlePeer" p2p/communication.go

Length of output: 3322


Script:

#!/bin/bash
# Let's check the p2p connection handling implementation
rg -A 15 "func \(c \*Communication\) Connect" p2p/communication.go

# Check for peer validation or connection rejection logic
rg -A 10 "func.*validatePeer|func.*checkPeer|func.*isWhitelisted" p2p/communication.go

# Check the host configuration to see how connections are filtered
rg -A 10 "NewHost|libp2p\.New" p2p/communication.go

Length of output: 597


Script:

#!/bin/bash
# Let's check the WhitelistConnectionGater implementation
rg -A 15 "type WhitelistConnectionGater|func.*WhitelistConnectionGater" p2p/connection_gater.go

# Check for connection rejection methods
rg -A 10 "func.*InterceptPeerDial|func.*InterceptSecured|func.*InterceptAccept" p2p/connection_gater.go

Length of output: 331


Script:

#!/bin/bash
# Let's find the connection gater file first
fd -t f -e go gater

# Search for whitelist-related files
fd -t f whitelist

# Search for connection handling in all Go files
rg -A 10 "InterceptPeerDial|InterceptSecured|InterceptAccept" --type go

Length of output: 1974

keygen/eddsa/keygen_test.go (2)

113-114: LGTM! Bootstrap node setup is correct.

The whitelisting configuration is properly applied to the bootstrap node with appropriate error handling.


119-120: 🛠️ Refactor suggestion

Add negative test case for whitelist enforcement.

While the whitelisting setup is correct, consider adding a test case that verifies non-whitelisted peers are properly rejected. This aligns with the PR comment discussion about negative testing.

Add a test case like:

func (s *EddsaKeygenTestSuite) TestNonWhitelistedPeerRejection(c *C) {
    // Setup a peer not in the whitelist
    nonWhitelistedPrivKey := generateTestPrivKey()
    comm, err := p2p.NewCommunication("asgard", []maddr.Multiaddr{multiAddr}, 19670, "", whitelistedPeers)
    c.Assert(err, IsNil)
    
    // Attempt connection with non-whitelisted peer
    err = comm.Start(nonWhitelistedPrivKey)
    c.Assert(err, NotNil)
    c.Assert(err.Error(), Matches, "peer not in whitelist")
}

Let's verify the current test coverage:

tss/tss.go (1)

62-62: LGTM: Function signature change is well-structured.

The addition of whitelistedPeers []peer.ID parameter follows Go conventions and uses appropriate types.

keysign/eddsa/keysign_test.go (2)

139-144: Add negative test case for non-whitelisted peer rejection.

While the whitelist initialization is correct, consider adding a test case that verifies non-whitelisted peers are properly rejected. This aligns with the PR objective and validates the security aspect of the whitelisting mechanism.

Would you like me to help generate a test case that attempts to connect with a non-whitelisted peer?


149-150: LGTM: Bootstrap node setup with whitelist.

The bootstrap node's communication setup correctly incorporates the whitelist parameter while maintaining proper error handling.

keygen/ecdsa/keygen_test.go (1)

133-134: LGTM! Consider adding whitelist enforcement test.

The peer configuration looks good. However, consider adding a test case to verify that non-whitelisted peers are rejected.

Let's verify if there are any existing test cases for whitelist enforcement:

tss/tss_4nodes_test.go (1)

18-18: LGTM: Import statement properly placed

The peer package import is correctly grouped with other libp2p-related imports and is necessary for the new whitelisting functionality.

keysign/ecdsa/keysign_old_test.go (2)

129-134: LGTM: Proper initialization of whitelisted peers

The implementation correctly converts public keys to peer IDs and builds the whitelist array with appropriate error handling.


139-140: LGTM: Proper bootstrap node configuration

The bootstrap node is correctly configured with whitelist support while maintaining its role as the initial node (empty bootstrap address).

p2p/communication.go (1)

312-312: Verify whitelist connection gater implementation.

The connection gater integration looks correct, but we should verify:

  1. The gater's thread-safety for concurrent connection attempts
  2. Proper handling of bootstrap peer connections
  3. Logging of rejected connections for monitoring
✅ Verification successful

Let me gather more information about the connection gater implementation.


Connection gater implementation is secure and correctly handles bootstrap peers

The WhitelistConnectionGater implementation has been verified and shows:

  1. Thread-safety is maintained through immutable whitelisted peers map, initialized at construction
  2. Bootstrap peer connections are properly handled as they must be in the whitelist to connect
  3. Comprehensive logging of both allowed and rejected connections at appropriate levels (Debug/Info)
  4. Clean separation of concerns with dedicated methods for different connection interception points
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the connection gater implementation
echo "Searching for connection gater implementation..."
rg -p "NewWhitelistConnectionGater"

# Check for concurrent connection handling
echo "Checking concurrent connection handling..."
ast-grep --pattern 'func $_($$) bool {
  $$$
  sync.$_ $$$
  $$$
}'

Length of output: 567


Script:

#!/bin/bash
# Check the WhitelistConnectionGater implementation
echo "Checking WhitelistConnectionGater implementation..."
cat p2p/whitelist_connection_gater.go

# Look for bootstrap peer handling
echo -e "\nChecking bootstrap peer handling..."
rg -p "bootstrap" -A 5 -B 5

Length of output: 18333

@skosito skosito merged commit 62ae2bb into master Oct 28, 2024
6 checks passed
@skosito skosito deleted the whitelist-connection-gater branch October 28, 2024 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants