github.com/henvic/wedeploycli@v1.7.6-0.20200319005353-3630f582f284/deployment/transport/git/pushhack.go (about) 1 // Hack to make git push work fine on Windows 2 // without a git-credential-helper issue / Invalid credentials error. 3 // See https://github.com/wedeploy/cli/issues/323 4 // This passes the token as part of the remote address 5 // Security risk: prone to sniffing (on the same machine) on most operating systems. 6 7 package git 8 9 import ( 10 "bytes" 11 "errors" 12 "fmt" 13 "os/exec" 14 "runtime" 15 "strings" 16 17 "github.com/henvic/wedeploycli/deployment/internal/groupuid" 18 19 version "github.com/hashicorp/go-version" 20 "github.com/henvic/wedeploycli/envs" 21 "github.com/henvic/wedeploycli/verbose" 22 ) 23 24 // Tests were made on the following git versions on Windows: 25 // 2.5.0, 2.5.1, 2.5.2, 2.5.2.2, 2.5.3, 2.6.0, 2.6.4, 2.7.4, 2.8.4, 26 // 2.9.0, 2.9.2, 2.10.1, 2.12.1, 2.13.0, 2.13.3, 2.14.2.2, 2.14.2.3. 27 // This issue doesn't appear to affect git on Linux (not even with 1.9.1). 28 // Related: https://github.com/git-for-windows/git 29 30 // Special treatment constraints: 31 // 2.5.0 (Aug 18, 2015): weird git credential- error message, but still works 32 // 2.5.1 (Aug 28, 2015): weird git credential- error message, but still works 33 // 2.5.3 (Sep 18, 2015): starts breaking 34 // 2.13.3 (Jul 13, 2017): working again 35 const gitAffectedVersions = "> 2.5.1, < 2.13.3" 36 37 func (t *Transport) pushHack() (groupUID string, err error) { 38 var params = []string{"push", t.getGitRemote(), "master", "--force", "--no-verify"} 39 40 if verbose.Enabled { 41 params = append(params, "--verbose") 42 } 43 44 verbose.Debug(fmt.Sprintf("Running git push %v master -force", 45 verbose.SafeEscape(t.getGitRemote()))) 46 47 var wectx = t.settings.ConfigContext 48 49 var cmd = exec.CommandContext(t.ctx, "git", params...) // #nosec 50 cmd.Env = append(t.getConfigEnvs(), 51 "GIT_TERMINAL_PROMPT=0", 52 envs.GitCredentialRemoteToken+"="+wectx.Token(), 53 ) 54 cmd.Dir = t.settings.WorkDir 55 56 var bufErr *bytes.Buffer 57 58 switch verbose.IsUnsafeMode() { 59 case true: 60 bufErr = copyErrStreamAndVerbose(cmd) 61 default: 62 bufErr = &bytes.Buffer{} 63 cmd.Stderr = bufErr 64 } 65 66 err = cmd.Run() 67 68 if err != nil { 69 bs := bufErr.String() 70 switch { 71 case strings.Contains(bs, "fatal: Authentication failed for"), 72 strings.Contains(bs, "could not read Username"): 73 return "", errors.New("invalid credentials: please update git and try again http://git-scm.com") 74 case strings.Contains(bs, "error: "): 75 return "", fmt.Errorf("git error: %v", verbose.SafeEscape(getGitErrors(bs).Error())) 76 default: 77 return "", err 78 } 79 } 80 81 return groupuid.Extract(bufErr.String()) 82 } 83 84 func (t *Transport) addRemoteHack() error { 85 verbose.Debug("Adding remote with token") 86 var wectx = t.settings.ConfigContext 87 88 var gitServer = fmt.Sprintf("https://%v:@git.%v/%v.git", 89 wectx.Token(), 90 wectx.InfrastructureDomain(), 91 t.settings.ProjectID) 92 93 var params = []string{"remote", "add", t.getGitRemote(), gitServer} 94 95 verbose.Debug(fmt.Sprintf("Running git remote add %v %v", 96 t.getGitRemote(), 97 verbose.SafeEscape(gitServer))) 98 99 var cmd = exec.CommandContext(t.ctx, "git", params...) // #nosec 100 cmd.Env = t.getConfigEnvs() 101 cmd.Dir = t.settings.WorkDir 102 103 if verbose.IsUnsafeMode() { 104 cmd.Stderr = errStream 105 } 106 107 return cmd.Run() 108 } 109 110 func (t *Transport) useCredentialHack() bool { 111 if runtime.GOOS != "windows" { 112 return false 113 } 114 115 v, err := version.NewVersion(t.gitVersion) 116 117 if err != nil { 118 return false 119 } 120 121 constraints, err := version.NewConstraint(gitAffectedVersions) 122 123 if err != nil { 124 verbose.Debug(err) 125 return false 126 } 127 128 p := constraints.Check(v) 129 130 if p { 131 verbose.Debug("git version " + t.gitVersion + " is not compatible with credential-helper due to a bug") 132 verbose.Debug("fall back to passing token on remote") 133 verbose.Debug("limited debug messages for security reasons") 134 verbose.Debug("updating git is highly recommended") 135 } 136 137 return p 138 }