Skip to content

Commit

Permalink
fix(git): add support for credential.useHttpPath
Browse files Browse the repository at this point in the history
In some scenarios the host machines git config sets
`credential.useHttpPath=true` but the git config in either the agent or
actual workspace doesn't.
Until now this would break git credential forwarding because we
wouldn't provide the `path` component to the machines git credential
helper.
  • Loading branch information
pascalbreuninger committed Jan 13, 2025
1 parent a2bf7f7 commit 468632d
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
15 changes: 15 additions & 0 deletions pkg/agent/tunnelserver/tunnelserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,21 @@ func (t *tunnelServer) GitCredentials(ctx context.Context, message *tunnel.Messa
credentials.Username = t.gitCredentialsOverride.username
credentials.Password = t.gitCredentialsOverride.token
} else {
if t.workspace.Source.GitRepository != "" {
path, err := gitcredentials.GetHTTPPath(ctx, gitcredentials.GetHttpPathParameters{
Host: credentials.Host,
Protocol: credentials.Protocol,
CurrentPath: credentials.Path,
Repository: t.workspace.Source.GitRepository,
})
if err != nil {
return nil, fmt.Errorf("get http path: %w", err)
}
// Set the credentials `path` field to the path component of the git repository URL.
// This allows downstream credential helpers to figure out which passwords needs to be fetched
credentials.Path = path
}

response, err := gitcredentials.GetCredentials(credentials)
if err != nil {
return nil, perrors.Wrap(err, "get git response")
Expand Down
36 changes: 36 additions & 0 deletions pkg/gitcredentials/gitcredentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gitcredentials
import (
"context"
"fmt"
netUrl "net/url"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -224,6 +225,41 @@ func GetCredentials(requestObj *GitCredentials) (*GitCredentials, error) {
return Parse(string(stdout))
}

type GetHttpPathParameters struct {
Host string
Protocol string
CurrentPath string
Repository string
}

// GetHTTPPath checks for gits `credential.useHttpPath` setting for a given host+protocol and returns the path component
// of `GitCredential` if the setting is true
func GetHTTPPath(ctx context.Context, params GetHttpPathParameters) (string, error) {
// No need to look up the HTTP Path if we already have one
if params.CurrentPath != "" {
return params.CurrentPath, nil
}

// Check if we need to respect gits `credential.useHttpPath`
// The actual format for the key is `credential.$PROTOCOL://$HOST.useHttpPath`, i.e. `credential.https://github.com.useHttpPath`
configKey := fmt.Sprintf("credential.%s://%s.useHttpPath", params.Protocol, params.Host)
out, err := git.CommandContext(ctx, "config", "--get", configKey).Output()
if err != nil {
return "", fmt.Errorf("inspect useHttpPath for host %s: %w", params.Host, err)
}
if strings.TrimSpace(string(out)) != "true" {
return "", nil
}
// We can assume the GitRepository is always HTTP(S) based as otherwise we wouldn't
// request credentials for it
url, err := netUrl.Parse(params.Repository)
if err != nil {
return "", fmt.Errorf("parse workspace repository: %w", err)
}

return url.Path, nil
}

func SetupGpgGitKey(gitSignKey string) error {
gitConfigCmd := exec.Command("git", []string{"config", "--global", "user.signingKey", gitSignKey}...)

Expand Down

0 comments on commit 468632d

Please sign in to comment.