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(git): improve SSH auth with key discovery #370

Merged
merged 5 commits into from
Mar 10, 2025
Merged

Conversation

hcavarsan
Copy link
Owner

  • Use SSH agent first (works with ssh-add keys)
  • Read git config for custom SSH settings
  • Support environment variables for custom paths
  • Try standard locations before directory scanning

relates: #336

@hcavarsan hcavarsan self-assigned this Mar 10, 2025
Copy link
Contributor

coderabbitai bot commented Mar 10, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • crates/kftray-tauri/Cargo.toml is excluded by !**/*.toml

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The pull request introduces significant modifications to the SSH authentication process within the get_git_credentials function. It now checks if the URL indicates an SSH connection and attempts to authenticate using the new try_ssh_authentication function, which retrieves SSH keys from various sources. The try_stored_credentials function has been simplified by removing the username requirement, and logging has been improved. Additionally, the setup_git_callbacks function limits authentication attempts to three.

Changes

File(s) Change Summary
crates/kftray-tauri/.../commands/github.rs - Added try_ssh_authentication for SSH key handling.
- Updated get_git_credentials to check for SSH URLs and use SSH authentication.
- Simplified the signatures of try_stored_credentials and try_credential_helper.
- Enhanced logging and error handling.
- Limited authentication attempts in setup_git_callbacks.
frontend/src/components/AddConfigModal/index.tsx - Refactored useQuery calls to use the object format with queryKey and queryFn properties.
- Separated error handling into distinct useEffect hooks for improved clarity.
frontend/src/components/AutoImportModal/index.tsx - Transitioned useQuery to @tanstack/react-query with modular error handling via useEffect hooks.
- Simplified useQuery call structure.
frontend/src/main.tsx - Updated import statement for QueryClient and QueryClientProvider from react-query to @tanstack/react-query.

Possibly related PRs

Suggested labels

enhancement, bug


🪧 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.
  • @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
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 (5)
crates/kftray-tauri/src/commands/github.rs (5)

119-120: Consider sanitizing or redacting the URL if it could contain sensitive data.
While logging the URL is helpful for debugging, in some setups the URL might contain embedded tokens or credentials. Confirm that no PII or secrets can be leaked here.


121-125: Extend SSH URL detection for more robust coverage.
The conditional covers common SSH URL patterns (git@, ssh://), but you may also encounter custom schemes (e.g., ssh://user@host). Consider broadening the checks or implementing a more thorough URL parsing method.


126-128: Add debug logging upon SSH auth failure.
Currently, if try_ssh_authentication fails, the code silently falls back to helper credentials. For better visibility, consider adding a debug log to indicate that SSH authentication was attempted but failed.


334-345: Store partial authentication failures for better troubleshooting.
While iterating through .git-credentials, you may consider capturing the last error or logging it, so the user knows why each attempt failed if this final fallback also fails.


371-373: Validate concurrency assumptions around the atomic attempts counter.
If this code is invoked in a multi-threaded scenario, the atomic usage is correct. If it’s strictly single-threaded, a simple variable might suffice. In either case, the approach to limit to 3 attempts is a good safeguard.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 923b251 and 046df11.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
  • crates/kftray-tauri/Cargo.toml is excluded by !**/*.toml
📒 Files selected for processing (1)
  • crates/kftray-tauri/src/commands/github.rs (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Clippy
  • GitHub Check: build-and-push-docker
🔇 Additional comments (3)
crates/kftray-tauri/src/commands/github.rs (3)

2-2: No issues with adding PathBuf.
This import is appropriate given its usage within the file.


131-131: Fallback to stored credentials is well-structured.
This provides a useful final attempt for legacy .git-credentials usage.


317-330: Credential helper fallback looks solid.
This attempts to retrieve system credentials in a straightforward manner. No issues noted.

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

🧹 Nitpick comments (1)
crates/kftray-tauri/src/commands/github.rs (1)

147-190: Git SSH config parsing could be more robust.

The parsing of core.sshCommand is somewhat brittle as it assumes a specific format with " -i " followed by the key path. This might not handle all valid formats or configurations.

Consider using a regex or a more robust parsing approach:

-        let key_arg_pos = key_path_str.find(" -i ").ok_or_else(|| {
-            info!("No -i flag in core.sshCommand");
-            git2::Error::from_str("No -i flag in core.sshCommand")
-        })?;
-
-        let key_path_start = key_arg_pos + 4;
-        let key_path_end = key_path_str[key_path_start..]
-            .find(' ')
-            .map(|pos| key_path_start + pos)
-            .unwrap_or(key_path_str.len());
-
-        let key_path_str = &key_path_str[key_path_start..key_path_end];
+        // Support various formats: "-i path", "-ipath", etc.
+        let mut key_path_str = None;
+        
+        // Try to find "-i " or "-i" pattern
+        if let Some(pos) = key_path_str.find(" -i ") {
+            key_path_str = Some(&key_path_str[pos + 4..].split_whitespace().next().unwrap_or(""));
+        } else if let Some(pos) = key_path_str.find(" -i") {
+            // Handle case where there's no space between -i and the path
+            if let Some(rest) = key_path_str.get(pos + 3..) {
+                key_path_str = Some(rest.split_whitespace().next().unwrap_or(""));
+            }
+        }
+        
+        let key_path_str = key_path_str.ok_or_else(|| {
+            info!("No -i flag in core.sshCommand");
+            git2::Error::from_str("No -i flag in core.sshCommand")
+        })?;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 046df11 and 8be8f66.

📒 Files selected for processing (1)
  • crates/kftray-tauri/src/commands/github.rs (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build-and-push-docker
  • GitHub Check: Clippy
🔇 Additional comments (12)
crates/kftray-tauri/src/commands/github.rs (12)

119-132: Updated SSH detection and authentication logic looks good.

The changes to get_git_credentials correctly detect SSH URLs and route them to the specialized SSH authentication function, while maintaining fallback options for other authentication methods.


134-145: Well-implemented SSH agent authentication.

Good implementation of SSH agent authentication with proper logging. This is a good first choice as it will work with keys that have already been added to the SSH agent, including those that might require passphrases.


192-218: Solid environment variable support for SSH keys.

Good implementation of environment variable support for SSH keys, with proper existence checks and error handling.


220-232: Good cross-platform directory detection.

The function properly handles different environment variables for cross-platform support, including both Unix-like systems (HOME) and Windows (USERPROFILE).


234-260: Comprehensive standard key name checking.

Good approach to try standard key names in multiple directories. The implementation checks all common SSH key types in priority order.


262-286: Thorough key file validation.

The function correctly filters out files that are definitely not private keys, which helps avoid unnecessary authentication attempts with invalid files.


288-328: Break down directory scanning functions into smaller parts.

The scan_directory_for_keys and scan_subdirectories_for_keys functions share similar logic and are quite lengthy. Consider extracting common functionality to reduce duplication and improve maintainability.

Extract the common directory reading logic into a helper function:

fn read_directory(dir: &Path) -> Result<std::fs::ReadDir, git2::Error> {
    if !dir.exists() || !dir.is_dir() {
        return Err(git2::Error::from_str(
            "Directory doesn't exist or is not a directory",
        ));
    }

    match std::fs::read_dir(dir) {
        Ok(entries) => Ok(entries),
        Err(e) => {
            info!("Failed to read directory {}: {}", dir.display(), e);
            Err(git2::Error::from_str(&format!(
                "Failed to read directory: {}",
                e
            )))
        }
    }
}

Then simplify both scanning functions by using this helper.

Also applies to: 330-384


386-418: Well-structured SSH authentication function with proper prioritization.

The function tries authentication methods in a sensible priority order, starting with the most convenient (SSH agent) and progressively falling back to more manual methods. This provides a good user experience while maintaining robustness.


420-435: Simplified credential helper implementation.

The function now handles its own config opening, which simplifies the interface and usage.


437-449: Simplified stored credentials function.

The function no longer requires a username parameter, simplifying its interface.


474-483: Good authentication attempt limiting.

Adding a counter to limit authentication attempts to 3 is a good security practice to prevent brute force attacks and avoid excessive authentication prompts for users.


493-505: Clean authentication logic for different URL types.

The code now clearly separates authentication logic for HTTPS vs SSH URLs, making it easier to understand and maintain.

@hcavarsan hcavarsan merged commit b571a6d into main Mar 10, 2025
7 checks passed
@hcavarsan hcavarsan deleted the fix-ssh-clone branch March 11, 2025 01: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.

1 participant