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

zoekt-mirror-gerrit: handle http authentication #770

Merged
merged 3 commits into from
Apr 30, 2024

Conversation

xavier-calland
Copy link
Contributor

issue: #763

@cla-bot cla-bot bot added the cla-signed label Apr 25, 2024
Copy link
Member

@keegancsmith keegancsmith left a comment

Choose a reason for hiding this comment

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

It doesn't look like you need the credential helper that writes to disk. You can instead generate authenticated clone URLs. This would be a simpler implementation if I am not mistaken?

cmd/zoekt-mirror-gerrit/main.go Outdated Show resolved Hide resolved
@xavier-calland
Copy link
Contributor Author

It doesn't look like you need the credential helper that writes to disk. You can instead generate authenticated clone URLs. This would be a simpler implementation if I am not mistaken?

Yes it works too.

But I'm not a fan of putting the password in plain text in the address
There is a risk of secrets leaking to the newspapers.
Additionally, the code would be closely tied to the git implementation.
Here we could more easily integrate with other git credential helpers.

@keegancsmith
Copy link
Member

They both will communicate the credentials over the wire in the same way. The only difference I can tell is we store the credentials as part of the clone URL in ./.git/config vs ./credential-store. FYI when I suggest using the clone URL then one does have to clean up the code path which extracts repo name from cloneURL to not include secrets.

Co-authored-by: Keegan Carruthers-Smith <[email protected]>
@xavier-calland
Copy link
Contributor Author

FYI when I suggest using the clone URL then one does have to clean up the code path which extracts repo name from cloneURL to not include secrets.

I'm not sure I understand what you mean.

What is expected for the config values:

  • remote.url (clone URL): https://user:password@gerrit-host/repo
  • zoekt.gerrit-host: https://gerrit-host/repo

@keegancsmith
Copy link
Member

What is expected for the config values

Yes what you listed. Sorry I need to read the gerrit code much closer, but I took a cursory look at noticed the cloneURL was directly used to construct the name/etc. So without checking further I was just mentioning some care may need to be taken to avoid leaking auth into the name of the repo/etc.

@xavier-calland
Copy link
Contributor Author

OK, done.

Comment on lines +239 to +243
func addPassword(u string, user *url.Userinfo) string {
password, _ := user.Password()
username := user.Username()
return strings.Replace(u, fmt.Sprintf("://%s@", username), fmt.Sprintf("://%s:%s@", username, password), 1)
}
Copy link
Member

Choose a reason for hiding this comment

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

This is prone to breaking, I suggest using url.URL

Suggested change
func addPassword(u string, user *url.Userinfo) string {
password, _ := user.Password()
username := user.Username()
return strings.Replace(u, fmt.Sprintf("://%s@", username), fmt.Sprintf("://%s:%s@", username, password), 1)
}
func addPassword(rawURL string, user *url.Userinfo) string {
u, err := url.Parse(rawURL)
if err != nil {
return rawURL
}
u.User = user
return u.String()
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem with this solution is that il will encode the path and ${project} is transformed to $%7Bproject%7D and break all strings.Replace(…, "${project}")

I can replace $%7Bproject%7D${project} before return (but I'm not sure it's a good solution)
or I can use $%7Bproject%7D everywhere in the file
(I'm not convinced by either solution)

(besides, I noticed that the management of paths (host + repo name) could surely be simplified to centralize part of the logic)

What do you think is the solution?

Copy link
Member

Choose a reason for hiding this comment

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

Alright I see now why we avoided URL parsing before, its not really a URL but a URL template. I think we will stick with this then, but a potential better solution is to only add in the password at the time we create the cloneURL.

@keegancsmith keegancsmith merged commit 68d0465 into sourcegraph:main Apr 30, 2024
9 checks passed
@keegancsmith
Copy link
Member

FYI I don't have any experience with the gerrit APIs (only used it as a normal user), hence why my reviews are not that great on this :) If you wanna keep making improvements to this go ahead :) Maybe a few simple tests can help with making bigger changes more confidently.

@xavier-calland xavier-calland deleted the gerrit-auth branch April 30, 2024 09:37
@xavier-calland
Copy link
Contributor Author

I just remembered another reason why I didn't choose the option to put the password in the repository URL.
With this solution the password will not be updated if it changes.

@xavier-calland
Copy link
Contributor Author

To make sure the credentials are ok we can:

  1. force remote.origin.url in

    zoekt/gitindex/clone.go

    Lines 63 to 66 in 72f9500

    // Repository exists, ensure settings are in sync
    if err := updateZoektGitConfig(repoDest, settings); err != nil {
    return "", fmt.Errorf("failed to update repository settings: %w", err)
    }
  2. force remote.origin.url in
    if dest, err := gitindex.CloneRepo(*dest, name, cloneURL.String(), config); err != nil {
    log.Fatalf("CloneRepo: %v", err)
    } else {
    fmt.Println(dest)
    }
  3. use git credential

@keegancsmith What solution should I make a PR for?

@keegancsmith
Copy link
Member

Making it update origin in the case of calling clone on an existing repo makes sense to me.

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

Successfully merging this pull request may close these issues.

2 participants