Repository: sigstore/fulcio
Pull request #1776 (2024-08-19 11:28:33)

If custom server url exists, use that instead of the default one.
<!--
Thanks for opening a pull request! Please do not just delete this text.  The three fields below are mandatory.

Please remember to:
- This PR requires an issue. If it is a new feature, the issue should proceed the PR and will have allowed sufficent time for discussions to take place. Please use
issue tags such as "Closes #XYZ" or "Resolves sigstore/repo-name#XYZ".
  [documentation](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)
- ensure your commits are signed-off, as sigstore uses the [DCO](https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin) using `git commit -s`, or `git commit -s --amend` if you want to amend already existing commits
- lastly, ensure there are no merge commits!

Thank you :)
-->

#### Summary
<!--
 Explain the **motivation** for making this change. What existing problem does the pull request solve? How can reviewers test this PR?
-->

When producing certificates from ID Tokens issued by GitHub Actions, the server url is always hardcoded to `github.com`. This is not true for all cases, as custom domains may be possible. This PR modifies the behaviour to look for the `enterprise` claim which indicates that a custom domain is used.

#### Release Note

* When issuing certificates for GitHub Actions jobs, the server url is now properly created if custom domains are used. 

#### Documentation
<!--

Does this change require an update to documentation? How will users implement your new feature?

Please reference a PR within https://docs.sigstore.dev

-->


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/sigstore/fulcio/pull/1776?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 50.35%. Comparing base [(`cf238ac`)](https://app.codecov.io/gh/sigstore/fulcio/commit/cf238accd68ef13e1e3425a5d87db2f352de173c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) to head [(`4a3edea`)](https://app.codecov.io/gh/sigstore/fulcio/commit/4a3edea545f7fc88e12a48cef39730ace58b3b5c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore).
> Report is 176 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1776      +/-   ##
==========================================
- Coverage   57.93%   50.35%   -7.58%     
==========================================
  Files          50       70      +20     
  Lines        3119     4184    +1065     
==========================================
+ Hits         1807     2107     +300     
- Misses       1154     1844     +690     
- Partials      158      233      +75     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/sigstore/fulcio/pull/1776?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore).


Patch:
diff --git a/pkg/identity/github/principal.go b/pkg/identity/github/principal.go
index 5eaa74a..da9e444 100644
--- a/pkg/identity/github/principal.go
+++ b/pkg/identity/github/principal.go
@@ -18,6 +18,7 @@ import (
 	"context"
 	"crypto/x509"
 	"errors"
+	"fmt"
 	"net/url"
 
 	"github.com/coreos/go-oidc/v3/oidc"
@@ -105,6 +106,7 @@ func WorkflowPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (ident
 		WorkflowSha          string `json:"workflow_sha"`
 		RunID                string `json:"run_id"`
 		RunAttempt           string `json:"run_attempt"`
+		Enterprise           string `json:"enterprise"`
 	}
 	if err := token.Claims(&claims); err != nil {
 		return nil, err
@@ -159,10 +161,16 @@ func WorkflowPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (ident
 		return nil, errors.New("missing run_attempt claim in ID token")
 	}
 
+	baseURL := `https://github.com/`
+
+	if claims.Enterprise != "" {
+		baseURL = fmt.Sprintf("https://%s.ghe.com/", claims.Enterprise)
+	}
+
 	return &workflowPrincipal{
 		subject:              token.Subject,
 		issuer:               token.Issuer,
-		url:                  `https://github.com/`,
+		url:                  baseURL,
 		sha:                  claims.Sha,
 		eventName:            claims.EventName,
 		repository:           claims.Repository,


Test patch:
diff --git a/pkg/identity/github/principal_test.go b/pkg/identity/github/principal_test.go
index 3b1d01b..7368fef 100644
--- a/pkg/identity/github/principal_test.go
+++ b/pkg/identity/github/principal_test.go
@@ -84,6 +84,53 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) {
 			},
 			WantErr: false,
 		},
+		`Valid token, custom base url authenticates with correct claims`: {
+			Claims: map[string]interface{}{
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
+				"enterprise":            "test",
+			},
+			ExpectPrincipal: workflowPrincipal{
+				issuer:               "https://token.actions.githubusercontent.com",
+				subject:              "repo:sigstore/fulcio:ref:refs/heads/main",
+				url:                  "https://test.ghe.com/",
+				jobWorkflowRef:       "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				sha:                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				eventName:            "push",
+				repository:           "sigstore/fulcio",
+				workflow:             "foo",
+				ref:                  "refs/heads/main",
+				jobWorkflowSha:       "example-sha",
+				runnerEnvironment:    "cloud-hosted",
+				repositoryID:         "12345",
+				repositoryOwner:      "username",
+				repositoryOwnerID:    "345",
+				repositoryVisibility: "public",
+				workflowRef:          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				workflowSha:          "example-sha-other",
+				runID:                "42",
+				runAttempt:           "1",
+			},
+			WantErr: false,
+		},
 		`Token missing job_workflow_ref claim should be rejected`: {
 			Claims: map[string]interface{}{
 				"aud":                   "sigstore",