Skip to content

Commit 1af72d4

Browse files
authored
Bugfix: tokenFromGHCLI not stripping api. from ghe.com hosts. Resolves #3188 (#3190)
* fix: resolve gh CLI token lookup for GHEC (.ghe.com) hosts tokenFromGHCLI only mapped api.github.com → github.com before calling `gh auth token --hostname`. For GHEC hosts (api.<slug>.ghe.com), the api. prefix was not stripped, causing the CLI lookup to fail silently and the provider to fall back to an unauthenticated client (401 errors). Strip the api. prefix for GHEC hosts using the existing GHECAPIHostMatch regex so the hostname matches how `gh` stores credentials. Fixes #3188 * Add test cases * Code updates according to PR feedback - move hostname modification to separate function for easier testing - test omdified to only test ghCLIHostFromAPIHost() without OS specific scripts - line ending fixed
1 parent d2d9d44 commit 1af72d4

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

github/provider.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,17 +497,27 @@ func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc {
497497
}
498498
}
499499

500+
// ghCLIHostFromAPIHost maps an API hostname to the corresponding
501+
// gh-CLI --hostname value. For example api.github.com -> github.com
502+
// and api.<slug>.ghe.com -> <slug>.ghe.com.
503+
// for unrecognized hostnames, input is returned unmodified.
504+
func ghCLIHostFromAPIHost(host string) string {
505+
if host == DotComAPIHost {
506+
return DotComHost
507+
} else if GHECAPIHostMatch.MatchString(host) {
508+
return strings.TrimPrefix(host, "api.")
509+
}
510+
return host
511+
}
512+
500513
// See https://github.com/integrations/terraform-provider-github/issues/1822
501514
func tokenFromGHCLI(u *url.URL) string {
502515
ghCliPath := os.Getenv("GH_PATH")
503516
if ghCliPath == "" {
504517
ghCliPath = "gh"
505518
}
506519

507-
host := u.Host
508-
if host == DotComAPIHost {
509-
host = DotComHost
510-
}
520+
host := ghCLIHostFromAPIHost(u.Host)
511521

512522
out, err := exec.Command(ghCliPath, "auth", "token", "--hostname", host).Output()
513523
if err != nil {

github/provider_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,46 @@ data "github_ip_ranges" "test" {}
259259
})
260260
})
261261
}
262+
263+
func Test_ghCLIHostFromAPIHost(t *testing.T) {
264+
testCases := []struct {
265+
name string
266+
host string
267+
expectedHost string
268+
}{
269+
{
270+
name: "dotcom API host is mapped to dotcom host",
271+
host: "api.github.com",
272+
expectedHost: "github.com",
273+
},
274+
{
275+
name: "ghec API host has api. prefix stripped",
276+
host: "api.my-enterprise.ghe.com",
277+
expectedHost: "my-enterprise.ghe.com",
278+
},
279+
{
280+
name: "ghec API host with numbers has api. prefix stripped",
281+
host: "api.customer-123.ghe.com",
282+
expectedHost: "customer-123.ghe.com",
283+
},
284+
{
285+
name: "ghes host is passed through unchanged",
286+
host: "github.example.com",
287+
expectedHost: "github.example.com",
288+
},
289+
{
290+
name: "ghes host with port is passed through unchanged",
291+
host: "github.example.com:8443",
292+
expectedHost: "github.example.com:8443",
293+
},
294+
}
295+
296+
for _, tc := range testCases {
297+
t.Run(tc.name, func(t *testing.T) {
298+
got := ghCLIHostFromAPIHost(tc.host)
299+
if got != tc.expectedHost {
300+
t.Errorf("ghCLIHostFromAPIHost(%q) = %q, want %q", tc.host, got, tc.expectedHost)
301+
}
302+
})
303+
}
304+
}

0 commit comments

Comments
 (0)