Repository: sigstore/fulcio (go)

Issue:
Signing from Codefresh fails when scm_repo_url claim is not provided
**Description**

After the migration of OIDC providers to the new configuration in https://github.com/sigstore/fulcio/pull/1743/files
signing from Codefresh is failing when scm_repo_url is not provided.

This is the error received from Cosign - 
` Error: signing [ilmedcodefresh/cosign-build-test@sha256:9a14f704ed630d8a73246acf9085e68c9971636fe88f459f408dbaa4669bcad8]: getting signer: getting key from Fulcio: retrieving cert: POST https://fulcio.sigstore.dev/api/v1/signingCert returned 400 Bad Request: "{\"code\":3,\"message\":\"value <scm_repo_url> not present in either claims or defaults. {\\n\\t\\\"ExtensionName\\\": \\\"SourceRepositoryURI\\\",\\n\\t\\\"Issuer\\\": \\\"https://oidc.codefresh.io\\\"\\n}\",\"details\":[]}"`

Repository urls are not always present in the pipeline context in Codefresh - for example when a build is executed manually and not triggered from git.

When I added the Codefresh OIDC provider initially it was taken to consideration, but with the new configuration it seems like all claims are mandatory.



Pull request:
set empty string as defaults for codefresh's optional fields
<!--
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
Closes #1770

It set empty string as default value for optional fields on codefresh workflow.

<!--
 Explain the **motivation** for making this change. What existing problem does the pull request solve? How can reviewers test this PR?
-->

#### Release Note
<!--
Add a release note for each of the following conditions:

* Config changes (additions, deletions, updates)
* API additions—new endpoint, new response fields, or newly accepted request parameters
* Database changes (any)
* Websocket additions or changes
* Anything noteworthy to an administrator running private sigstore instances (err on the side of over-communicating)
* New features and improvements, including behavioural changes, UI changes and CLI changes
* Bug fixes and fixes of previous known issues
* Deprecation warnings, breaking changes, or compatibility notes

If no release notes are required write NONE. Use past-tense.

-->

#### 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

-->


Patch:
diff --git a/config/identity/config.yaml b/config/identity/config.yaml
index 77ef00f..6f9aba8 100644
--- a/config/identity/config.yaml
+++ b/config/identity/config.yaml
@@ -203,6 +203,9 @@ ci-issuer-metadata:
       # for cases that the claimed data doesn't exist.
       # platform_url: Codefresh platform url
       platform_url: "https://g.codefresh.io"
+      scm_repo_url: ""
+      scm_ref: ""
+      runner_environment: ""
     extension-templates:
       # workflow_id: The ID of the specific workflow authorized in the claim.
       # For example, 64f447c02199f903000gh20.
diff --git a/go.mod b/go.mod
index 1a340ba..2986a11 100644
--- a/go.mod
+++ b/go.mod
@@ -19,10 +19,10 @@ require (
 	github.com/google/tink/go v1.7.0
 	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.21.0
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0
 	github.com/hashicorp/golang-lru v1.0.2
 	github.com/magiconair/properties v1.8.7
-	github.com/prometheus/client_golang v1.19.1
+	github.com/prometheus/client_golang v1.20.0
 	github.com/prometheus/client_model v0.6.1
 	github.com/prometheus/common v0.55.0
 	github.com/rs/cors v1.11.0
@@ -37,8 +37,8 @@ require (
 	github.com/spiffe/go-spiffe/v2 v2.3.0
 	go.step.sm/crypto v0.51.1
 	go.uber.org/zap v1.27.0
-	google.golang.org/api v0.191.0
-	google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f
+	google.golang.org/api v0.192.0
+	google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142
 	google.golang.org/grpc v1.65.0
 	google.golang.org/protobuf v1.34.2
 	gopkg.in/yaml.v3 v3.0.1
@@ -47,7 +47,7 @@ require (
 
 require (
 	cloud.google.com/go v0.115.0 // indirect
-	cloud.google.com/go/auth v0.8.0 // indirect
+	cloud.google.com/go/auth v0.8.1 // indirect
 	cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect
 	cloud.google.com/go/compute/metadata v0.5.0 // indirect
 	cloud.google.com/go/iam v1.1.12 // indirect
@@ -106,6 +106,7 @@ require (
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jellydator/ttlcache/v3 v3.2.0 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
+	github.com/klauspost/compress v1.17.9 // indirect
 	github.com/kylelemons/godebug v1.1.0 // indirect
 	github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect
 	github.com/miekg/pkcs11 v1.1.1 // indirect
@@ -151,7 +152,7 @@ require (
 	golang.org/x/text v0.17.0 // indirect
 	golang.org/x/time v0.6.0 // indirect
 	google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	k8s.io/klog/v2 v2.120.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 1b04ec5..a2f422f 100644
--- a/go.sum
+++ b/go.sum
@@ -5,8 +5,8 @@ chainguard.dev/sdk v0.1.23/go.mod h1:TojPLtaHmy1TThjHjvPQbwKRDCusBPpQWSBZ2EkQFFk
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14=
 cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU=
-cloud.google.com/go/auth v0.8.0 h1:y8jUJLl/Fg+qNBWxP/Hox2ezJvjkrPb952PC1p0G6A4=
-cloud.google.com/go/auth v0.8.0/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc=
+cloud.google.com/go/auth v0.8.1 h1:QZW9FjC5lZzN864p13YxvAtGUlQ+KgRL+8Sg45Z6vxo=
+cloud.google.com/go/auth v0.8.1/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc=
 cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI=
 cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I=
 cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
@@ -179,8 +179,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa
 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 h1:JYghRBlGCZyCF2wNUJ8W0cwaQdtpcssJ4CgC406g+WU=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.21.0 h1:CWyXh/jylQWp2dtiV33mY4iSSp6yf4lmn+c7/tN+ObI=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.21.0/go.mod h1:nCLIt0w3Ept2NwF8ThLmrppXsfT07oC8k0XNDxd8sVU=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
 github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -220,6 +220,8 @@ github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs=
 github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
+github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -268,8 +270,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
 github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
-github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
-github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
+github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
+github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -490,8 +492,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/api v0.191.0 h1:cJcF09Z+4HAB2t5qTQM1ZtfL/PemsLFkcFG67qq2afk=
-google.golang.org/api v0.191.0/go.mod h1:tD5dsFGxFza0hnQveGfVk9QQYKcfp+VzgRqyXFxE0+E=
+google.golang.org/api v0.192.0 h1:PljqpNAfZaaSpS+TnANfnNAXKdzHM/B9bKhwRlo7JP0=
+google.golang.org/api v0.192.0/go.mod h1:9VcphjvAxPKLmSxVSzPlSRXy/5ARMEw5bf58WoVXafQ=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@@ -500,10 +502,10 @@ google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfG
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf h1:OqdXDEakZCVtDiZTjcxfwbHPCT11ycCEsTKesBVKvyY=
 google.golang.org/genproto v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:mCr1K1c8kX+1iSBREvU3Juo11CB+QOEWxbRS01wWl5M=
-google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f h1:b1Ln/PG8orm0SsBbHZWke8dDp2lrCD4jSmfglFpTZbk=
-google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf h1:liao9UHurZLtiEwBgT9LMOnKYsHze6eA6w1KQCMVN2Q=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
+google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
+google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
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/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go
index aafae57..07d4c76 100644
--- a/pkg/identity/ciprovider/principal_test.go
+++ b/pkg/identity/ciprovider/principal_test.go
@@ -247,6 +247,7 @@ func TestApplyTemplateOrReplace(t *testing.T) {
 		"url":         "https://github.com",
 		"claim_foo":   "default",
 		"default_foo": "default_bar",
+		"empty_value": "",
 	}
 
 	tests := map[string]struct {
@@ -309,6 +310,11 @@ func TestApplyTemplateOrReplace(t *testing.T) {
 			ExpectedResult: "bar",
 			ExpectErr:      false,
 		},
+		`Should return empty string for empty default`: {
+			Template:       "{{ .empty_value }}/123",
+			ExpectedResult: "/123",
+			ExpectErr:      false,
+		},
 	}
 
 	for name, test := range tests {
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",