Allow gh auth git-credential to authenticate GitHub Gist requests (#3064)
* Allow `gh auth git-credential` to authenticate GitHub Gist requests When there are stored credentials for `example.com`, allow using them to authenticate requests to `gist.example.com` as well. * Fix writing out of credential config * remove unneccessary function * actually delete Co-authored-by: nate smith <vilmibm@github.com>
This commit is contained in:
parent
5c2ee024a2
commit
583af3e54c
5 changed files with 134 additions and 23 deletions
|
|
@ -72,13 +72,23 @@ func RESTPrefix(hostname string) string {
|
|||
}
|
||||
|
||||
func GistPrefix(hostname string) string {
|
||||
prefix := "https://"
|
||||
|
||||
if strings.EqualFold(hostname, localhost) {
|
||||
prefix = "http://"
|
||||
}
|
||||
|
||||
return prefix + GistHost(hostname)
|
||||
}
|
||||
|
||||
func GistHost(hostname string) string {
|
||||
if IsEnterprise(hostname) {
|
||||
return fmt.Sprintf("https://%s/gist/", hostname)
|
||||
return fmt.Sprintf("%s/gist/", hostname)
|
||||
}
|
||||
if strings.EqualFold(hostname, localhost) {
|
||||
return fmt.Sprintf("http://%s/gist/", hostname)
|
||||
return fmt.Sprintf("%s/gist/", hostname)
|
||||
}
|
||||
return fmt.Sprintf("https://gist.%s/", hostname)
|
||||
return fmt.Sprintf("gist.%s/", hostname)
|
||||
}
|
||||
|
||||
func HostPrefix(hostname string) string {
|
||||
|
|
|
|||
|
|
@ -100,12 +100,18 @@ func helperRun(opts *CredentialOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
lookupHost := wants["host"]
|
||||
var gotUser string
|
||||
gotToken, source, _ := cfg.GetWithSource(wants["host"], "oauth_token")
|
||||
gotToken, source, _ := cfg.GetWithSource(lookupHost, "oauth_token")
|
||||
if gotToken == "" && strings.HasPrefix(lookupHost, "gist.") {
|
||||
lookupHost = strings.TrimPrefix(lookupHost, "gist.")
|
||||
gotToken, source, _ = cfg.GetWithSource(lookupHost, "oauth_token")
|
||||
}
|
||||
|
||||
if strings.HasSuffix(source, "_TOKEN") {
|
||||
gotUser = tokenUser
|
||||
} else {
|
||||
gotUser, _, _ = cfg.GetWithSource(wants["host"], "user")
|
||||
gotUser, _, _ = cfg.GetWithSource(lookupHost, "user")
|
||||
}
|
||||
|
||||
if gotUser == "" || gotToken == "" {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,32 @@ func Test_helperRun(t *testing.T) {
|
|||
`),
|
||||
wantStderr: "",
|
||||
},
|
||||
{
|
||||
name: "gist host",
|
||||
opts: CredentialOptions{
|
||||
Operation: "get",
|
||||
Config: func() (config, error) {
|
||||
return tinyConfig{
|
||||
"_source": "/Users/monalisa/.config/gh/hosts.yml",
|
||||
"github.com:user": "monalisa",
|
||||
"github.com:oauth_token": "OTOKEN",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
input: heredoc.Doc(`
|
||||
protocol=https
|
||||
host=gist.github.com
|
||||
username=monalisa
|
||||
`),
|
||||
wantErr: false,
|
||||
wantStdout: heredoc.Doc(`
|
||||
protocol=https
|
||||
host=gist.github.com
|
||||
username=monalisa
|
||||
password=OTOKEN
|
||||
`),
|
||||
wantStderr: "",
|
||||
},
|
||||
{
|
||||
name: "url input",
|
||||
opts: CredentialOptions{
|
||||
|
|
|
|||
|
|
@ -63,25 +63,46 @@ func (flow *GitCredentialFlow) Setup(hostname, username, authToken string) error
|
|||
|
||||
func (flow *GitCredentialFlow) gitCredentialSetup(hostname, username, password string) error {
|
||||
if flow.helper == "" {
|
||||
// first use a blank value to indicate to git we want to sever the chain of credential helpers
|
||||
preConfigureCmd, err := git.GitCommand("config", "--global", "--replace-all", gitCredentialHelperKey(hostname), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = run.PrepareCmd(preConfigureCmd).Run(); err != nil {
|
||||
return err
|
||||
credHelperKeys := []string{
|
||||
gitCredentialHelperKey(hostname),
|
||||
}
|
||||
|
||||
// use GitHub CLI as a credential helper (for this host only)
|
||||
configureCmd, err := git.GitCommand(
|
||||
"config", "--global", "--add",
|
||||
gitCredentialHelperKey(hostname),
|
||||
fmt.Sprintf("!%s auth git-credential", shellQuote(flow.Executable)),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
gistHost := strings.TrimSuffix(ghinstance.GistHost(hostname), "/")
|
||||
if strings.HasPrefix(gistHost, "gist.") {
|
||||
credHelperKeys = append(credHelperKeys, gitCredentialHelperKey(gistHost))
|
||||
}
|
||||
return run.PrepareCmd(configureCmd).Run()
|
||||
|
||||
var configErr error
|
||||
|
||||
for _, credHelperKey := range credHelperKeys {
|
||||
if configErr != nil {
|
||||
break
|
||||
}
|
||||
// first use a blank value to indicate to git we want to sever the chain of credential helpers
|
||||
preConfigureCmd, err := git.GitCommand("config", "--global", "--replace-all", credHelperKey, "")
|
||||
if err != nil {
|
||||
configErr = err
|
||||
break
|
||||
}
|
||||
if err = run.PrepareCmd(preConfigureCmd).Run(); err != nil {
|
||||
configErr = err
|
||||
break
|
||||
}
|
||||
|
||||
// second configure the actual helper for this host
|
||||
configureCmd, err := git.GitCommand(
|
||||
"config", "--global", "--add",
|
||||
credHelperKey,
|
||||
fmt.Sprintf("!%s auth git-credential", shellQuote(flow.Executable)),
|
||||
)
|
||||
if err != nil {
|
||||
configErr = err
|
||||
} else {
|
||||
configErr = run.PrepareCmd(configureCmd).Run()
|
||||
}
|
||||
}
|
||||
|
||||
return configErr
|
||||
}
|
||||
|
||||
// clear previous cached credentials
|
||||
|
|
@ -121,7 +142,8 @@ func (flow *GitCredentialFlow) gitCredentialSetup(hostname, username, password s
|
|||
}
|
||||
|
||||
func gitCredentialHelperKey(hostname string) string {
|
||||
return fmt.Sprintf("credential.%s.helper", strings.TrimSuffix(ghinstance.HostPrefix(hostname), "/"))
|
||||
host := strings.TrimSuffix(ghinstance.HostPrefix(hostname), "/")
|
||||
return fmt.Sprintf("credential.%s.helper", host)
|
||||
}
|
||||
|
||||
func gitCredentialHelper(hostname string) (helper string, err error) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,54 @@ func TestGitCredentialSetup_configureExisting(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGitCredentialSetup_setOurs(t *testing.T) {
|
||||
func TestGitCredentialsSetup_setOurs_GH(t *testing.T) {
|
||||
cs, restoreRun := run.Stub()
|
||||
defer restoreRun(t)
|
||||
cs.Register(`git config --global --replace-all credential\.`, 0, "", func(args []string) {
|
||||
if key := args[len(args)-2]; key != "credential.https://github.com.helper" {
|
||||
t.Errorf("git config key was %q", key)
|
||||
}
|
||||
if val := args[len(args)-1]; val != "" {
|
||||
t.Errorf("global credential helper configured to %q", val)
|
||||
}
|
||||
})
|
||||
cs.Register(`git config --global --add credential\.`, 0, "", func(args []string) {
|
||||
if key := args[len(args)-2]; key != "credential.https://github.com.helper" {
|
||||
t.Errorf("git config key was %q", key)
|
||||
}
|
||||
if val := args[len(args)-1]; val != "!/path/to/gh auth git-credential" {
|
||||
t.Errorf("global credential helper configured to %q", val)
|
||||
}
|
||||
})
|
||||
cs.Register(`git config --global --replace-all credential\.`, 0, "", func(args []string) {
|
||||
if key := args[len(args)-2]; key != "credential.https://gist.github.com.helper" {
|
||||
t.Errorf("git config key was %q", key)
|
||||
}
|
||||
if val := args[len(args)-1]; val != "" {
|
||||
t.Errorf("global credential helper configured to %q", val)
|
||||
}
|
||||
})
|
||||
cs.Register(`git config --global --add credential\.`, 0, "", func(args []string) {
|
||||
if key := args[len(args)-2]; key != "credential.https://gist.github.com.helper" {
|
||||
t.Errorf("git config key was %q", key)
|
||||
}
|
||||
if val := args[len(args)-1]; val != "!/path/to/gh auth git-credential" {
|
||||
t.Errorf("global credential helper configured to %q", val)
|
||||
}
|
||||
})
|
||||
|
||||
f := GitCredentialFlow{
|
||||
Executable: "/path/to/gh",
|
||||
helper: "",
|
||||
}
|
||||
|
||||
if err := f.gitCredentialSetup("github.com", "monalisa", "PASSWD"); err != nil {
|
||||
t.Errorf("GitCredentialSetup() error = %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGitCredentialSetup_setOurs_nonGH(t *testing.T) {
|
||||
cs, restoreRun := run.Stub()
|
||||
defer restoreRun(t)
|
||||
cs.Register(`git config --global --replace-all credential\.`, 0, "", func(args []string) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue