-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GitLab.com OIDC to Fulcio #983
Conversation
Codecov Report
@@ Coverage Diff @@
## main #983 +/- ##
==========================================
+ Coverage 55.91% 56.02% +0.11%
==========================================
Files 48 50 +2
Lines 2783 2904 +121
==========================================
+ Hits 1556 1627 +71
- Misses 1097 1133 +36
- Partials 130 144 +14
|
this is a payload from a self-hosted instance (changed the gitlab url for security) but that pointed to the base url for the self hosted instance {
"namespace_id": "4",
"namespace_path": "cpanato",
"project_id": "10",
"project_path": "cpanato/testing-cosign",
"user_id": "2",
"user_login": "cpanato",
"user_email": "cpanato@example.dev",
"pipeline_id": "322",
"pipeline_source": "push",
"job_id": "1139",
"ref": "main",
"ref_type": "branch",
"ref_protected": "true",
"jti": "f94ba179-77b2-4b3f-b179-b2df0698ed70",
"iss": "https://xxxxxxxxx",
"iat": 1674821675,
"nbf": 1674821670,
"exp": 1674825275,
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"aud": "sigstore"
} |
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package gitlabcom |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for not just having gitlab
as the package name without the TLD (like github and buildkite)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe to make it clear this is scoped to gitlab.com (the hosted instance) for now and custom gitlab deployments are not supported (yet)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can rename that, did this in the beginning because i don't know how we want to deal with GitLab self-hosted instances
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the tokens should have the same shape, just like Kubernetes tokens, but the issuer will vary.
Will take a closer look on Monday, thanks for adding this! |
@cpanato thanks for working on this! As an FYI we are likely going to stand up a separate OIDC issuer for CI job tokens. I'm hoping we can get that done very soon but we have not established a timeline just yet. Feel free to chime in on the discussion here: https://gitlab.com/groups/gitlab-org/-/epics/9212#note_1256006253 I think we can proceed with integrating our current issuer, but we should be mindful that the issuer claim embedded in the certs is subject to change. |
pkg/identity/gitlabcom/principal.go
Outdated
return &jobPrincipal{ | ||
subject: token.Subject, | ||
issuer: token.Issuer, | ||
url: fmt.Sprintf("https://gitlab.com/%s/-/jobs/%s", claims.ProjectPath, claims.JobID), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve been told that jobID is likely the best option because it most closely maps to something like the job workflow ref from GH
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree Job ID is closest to job_workflow_ref
, but I don't know if it fits the same intent for the SAN. Thinking about it's use in cosign verify --certificate-identity
, SANs map more closely to a service account identity rather than a specific identifier of build instructions.
If we used the Job ID I suspect most users would use --certificate-identity-regexp="https://gitlab.com/my/repo/.*"
and match on other values instead - it would be very rare that you would want to match on exact Job IDs because they are a unique identifier per run.
I think https://gitlab.com/org/repo@ref
probably makes the most sense right now. @marshall007 mentioned that this may become more granular in the future, but for now GitLab CI pipelines only have a single config per repo.
cc @aladh @marshall007 Any opinions here?
pkg/identity/gitlabcom/principal.go
Outdated
PipelineID string `json:"pipeline_id"` | ||
PipelineSource string `json:"pipeline_source"` | ||
JobID string `json:"job_id"` | ||
Ref string `json:"ref"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the claim is not going to be used, we can omit it from the struct.
@marshall007 Thanks for the information! If it would be helpful to start testing integrations with GitLab-bound certificates, then I would be fine merging this in with a warning that the issuer will change in the near future, and we would only roll this out to staging, not production. If this is not yet doing to be used, then I'd hold off on this PR until #945 is in and the issuer has been stood up for GitLab. |
@marshall007 @haydentherapper, thanks for the updates and clarification. I will keep my eye on the GitLab issue. @haydentherapper should we pause this or should I make the changes you requested and move forward? |
Once this lands, we should get ambient cred support into cosign: #890 (comment) |
@haydentherapper sure thing |
Moving this to draft for now |
Does anyone in this thread know if there's been any progress on standing up a separate issuer? cc @wlynch |
@haydentherapper Unfortunately, there doesn't seem to have been any progress on the new OIDC issuer. Here's the issue for reference: https://gitlab.com/gitlab-org/gitlab/-/issues/390711. I'll try to follow up internally and find out when it should be ready. |
@cpanato @haydentherapper Hey all. I'm sorry that roadblocks got thrown up here and slowed the momentum on this. After some discussion, we've decided that we won't be going through with the changes proposed in https://gitlab.com/gitlab-org/gitlab/-/issues/390711. Please let me know if there's anything GitLab can do to help get this PR finished. We're happy to lend a hand in this effort. |
62c55c5
to
d757969
Compare
Not a blocker for us if you’d prefer to reuse the issuer! We will want to include the newly added extensions in this PR too. I see an open PR being worked on now to update the mapping between extension and value, we would appreciate any feedback there since y’all have the most up to date view of the purpose of each identity token claim. |
ca97df4
to
e8eac6d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@wlynch Can you take a pass over this and make sure this looks good? I'll take a look after! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thanks @cpanato! 🎉
|
||
// reflect hack because "claims" field is unexported by oidc IDToken | ||
// https://github.com/coreos/go-oidc/pull/329 | ||
func withClaims(token *oidc.IDToken, data []byte) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of scope for this PR, but we should look into pulling this out into a library so we're not copying the same hacks for each identity provider. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good, i can work on that in a follow up
pkg/identity/gitlabcom/principal.go
Outdated
} | ||
|
||
// Set workflow ref URL to SubjectAlternativeName on certificate | ||
cert.URIs = []*url.URL{baseURL.JoinPath(p.repository, "/-/jobs/", p.jobID)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wlynch Is this correct for the SAN? I recall you said that job was too granular. pipeline_ref? Or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch - you're right. This should be
cert.URIs = []*url.URL{baseURL.JoinPath(p.repository, "/-/jobs/", p.jobID)} | |
cert.URIs = []*url.URL{baseURL.JoinPath(p.repository, "@", ref)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is pipeline ref too granular? That represents the build configuration, but I could imagine creating policy around that.
If not, for ref, i think we’d need a different delimiter, unless @ creates a valid uri
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@
can be a valid URI (i.e. ssh://user@host
- we also use it in the GitHub Actions SAN)
re pipeline_ref: the pipeline_ref can be a URI to a location not even on GitLab which makes me a little doubtful of whether we want to use that as the SAN.
Most pipeline_refs will be just .gitlab-ci.yml
, which means most SANs will be identical unless we transform them. If we do something like prepend the project URL then it becomes harder to distinguish whether the SAN was originally given to us as a URI.
As an example, if you had a repo using a config fetched from http://example.com
, I think my preference would be to use https://gitlab.com/user/repo@refs/heads/main
rather than http://example.com
, since knowing it came from the repo from a trusted branch seems like a more useful base identifier. You'd still have the pipeline_ref in another claim as a way to have finer-grained policies.
That said, we could use it if we really wanted. What do you think? Happy to talk this through more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM on @ in the SAN.
Hm, I definitely agree that if pipeline_ref points to a URI outside of gitlab, then we should avoid that. I'm good with this then. Thanks for the background!
|
||
var ref string | ||
switch claims.RefType { | ||
case "branch": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally we don't want to mutate any claims, thoughts on removing this? I saw the comment from @wlynch though. If you think this would be good to standardize on, let's first open a PR to discuss requiring this prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is without the prefix ref alone is ambiguous - you could have ref/tags/main
or ref/heads/v1.0.0
. ref_type
is what informs what the full-formed ref is. Ideally it would be better if GitLab had a full_ref claim (this way they could also support non branch/tag refs as well), but for now I think this is the best we can do.
cc @marshall007 @Brcrwilliams FYI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that ref type comes from the token, this looks alright.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally it would be better if GitLab had a full_ref claim
@wlynch we can certainly do that: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119075
In the code, we currently refer to this as the ref_path
. Do you think that makes sense as a user-facing name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds fine. Thanks! 🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks y'all! So we'll assume that ref_path
will be equivalent to what's here and will update once it's implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we wait for the MR on the GitLab side to be merged or we stick with this implementation for now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine to proceed. The result should be the same in the end for branches/tags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, @cpanato, if you can apply the suggested change, we'll be good to go!
I'll cut a new release early next week and get the change out in staging.
return &jobPrincipal{ | ||
subject: token.Subject, | ||
issuer: token.Issuer, | ||
url: `https://gitlab.com/`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment for this field says:
// The URL of the pipeline, the container of many builds. This will be
// set as a human-friendly SubjectAlternativeName URI in the certificate.
url string
To make that comment accurate, this should be
url: `https://gitlab.com/`, | |
url: fmt.Sprintf("https://gitlab.com/%s/-/pipelines/%s", claims.ProjectPath, claims.ProjectID) |
We could also add another claim for this in the JWT if need be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL is just the base URL, Embed takes the URL and appends that.
We should update the comment to note that (a previous iteration of Fulcio had the URL as the SAN, some refactoring changed that). Thanks for noticing.
We do the same in GH - https://github.com/sigstore/fulcio/blob/main/pkg/identity/github/principal.go#L187-L188, and the URL comment https://github.com/sigstore/fulcio/blob/main/pkg/identity/github/principal.go#L37
url: `https://gitlab.com/`, | ||
eventName: claims.PipelineSource, | ||
pipelineID: claims.PipelineID, | ||
repository: claims.ProjectPath, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In GitLab, we distinguish between projects and repositories. https://gitlab.com/gitlab-org/gitlab is a URL to a project, https://gitlab.com/gitlab-org/gitlab.git is a URL to a repository. A project contains a repository, along with other things like issues, merge requests, pipelines, etc.
TL;DR: project
is the correct thing to call this, but repository
is ok if we want to keep consistency with the other principals.
dff2b0c
to
58353d4
Compare
|
||
var ref string | ||
switch claims.RefType { | ||
case "branch": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine to proceed. The result should be the same in the end for branches/tags.
Signed-off-by: cpanato <ctadeu@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @cpanato!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Summary
Initial work to support gitlab.com, for self-hosted we will need to discuss how we want to deal with it.
similar work that was done in #890
sample gitlab pipeline
sample token payload
Fixes #243