Skip to content

Commit

Permalink
Add GitLab.com OIDC to Fulcio
Browse files Browse the repository at this point in the history
Signed-off-by: cpanato <[email protected]>
  • Loading branch information
cpanato committed Jan 27, 2023
1 parent 27f081f commit 21d3af4
Show file tree
Hide file tree
Showing 8 changed files with 525 additions and 4 deletions.
5 changes: 5 additions & 0 deletions config/fulcio-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ data:
"Type": "spiffe",
"SPIFFETrustDomain": "allow.pub"
},
"https://gitlab.com": {
"IssuerURL": "https://gitlab.com",
"ClientID": "sigstore",
"Type": "gitlab-pipeline"
},
"https://oauth2.sigstore.dev/auth": {
"IssuerURL": "https://oauth2.sigstore.dev/auth",
"ClientID": "sigstore",
Expand Down
18 changes: 18 additions & 0 deletions federation/gitlab.com/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2023 The Sigstore Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

url: https://gitlab.com
contact: [email protected]
description: "GitLab OIDC tokens for job identity"
type: "gitlab-pipeline"
3 changes: 3 additions & 0 deletions pkg/challenges/challenges.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/sigstore/fulcio/pkg/identity/buildkite"
"github.com/sigstore/fulcio/pkg/identity/email"
"github.com/sigstore/fulcio/pkg/identity/github"
"github.com/sigstore/fulcio/pkg/identity/gitlab_com"
"github.com/sigstore/fulcio/pkg/identity/kubernetes"
"github.com/sigstore/fulcio/pkg/identity/spiffe"
"github.com/sigstore/fulcio/pkg/identity/uri"
Expand Down Expand Up @@ -60,6 +61,8 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin
switch iss.Type {
case config.IssuerTypeBuildkiteJob:
principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok)
case config.IssuerTypeGitLabPipeline:
principal, err = gitlab_com.JobPrincipalFromIDToken(ctx, tok)
case config.IssuerTypeEmail:
principal, err = email.PrincipalFromIDToken(ctx, tok)
case config.IssuerTypeSpiffe:
Expand Down
3 changes: 3 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ const (
IssuerTypeBuildkiteJob = "buildkite-job"
IssuerTypeEmail = "email"
IssuerTypeGithubWorkflow = "github-workflow"
IssuerTypeGitLabPipeline = "gitlab-pipeline"
IssuerTypeKubernetes = "kubernetes"
IssuerTypeSpiffe = "spiffe"
IssuerTypeURI = "uri"
Expand Down Expand Up @@ -462,6 +463,8 @@ func issuerToChallengeClaim(issType IssuerType) string {
switch issType {
case IssuerTypeBuildkiteJob:
return "sub"
case IssuerTypeGitLabPipeline:
return "sub"
case IssuerTypeEmail:
return "email"
case IssuerTypeGithubWorkflow:
Expand Down
3 changes: 3 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,9 @@ func Test_issuerToChallengeClaim(t *testing.T) {
if claim := issuerToChallengeClaim(IssuerTypeGithubWorkflow); claim != "sub" {
t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim)
}
if claim := issuerToChallengeClaim(IssuerTypeGitLabPipeline); claim != "sub" {
t.Fatalf("expected sub subject claim for GitLab issuer, got %s", claim)
}
if claim := issuerToChallengeClaim(IssuerTypeKubernetes); claim != "sub" {
t.Fatalf("expected sub subject claim for K8S issuer, got %s", claim)
}
Expand Down
124 changes: 124 additions & 0 deletions pkg/identity/gitlab_com/principal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright 2023 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gitlab_com

import (
"context"
"crypto/x509"
"errors"
"fmt"
"net/url"

"github.com/coreos/go-oidc/v3/oidc"
"github.com/sigstore/fulcio/pkg/certificate"
"github.com/sigstore/fulcio/pkg/identity"
)

type jobPrincipal struct {
// Subject matches the 'sub' claim from the OIDC ID token this is what is
// signed as proof of possession for Buildkite job identities
subject string

// OIDC Issuer URL. Matches 'iss' claim from ID token. The real issuer URL is
// https://agent.buildkite.com/.well-known/openid-configuration
issuer string

// 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

// Event that triggered this workflow run. E.g "push", "tag" etc
pipelineSource string

// Repository building built
projectPath string

// Job that is running
jobID string

// Git ref being built
ref string
}

func JobPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) {
var claims struct {
ProjectPath string `json:"project_path"`
PipelineID string `json:"pipeline_id"`
PipelineSource string `json:"pipeline_source"`
JobID string `json:"job_id"`
Ref string `json:"ref"`
RefType string `json:"ref_type"`
}
if err := token.Claims(&claims); err != nil {
return nil, err
}

if claims.ProjectPath == "" {
return nil, errors.New("missing project_path claim in ID token")
}

if claims.PipelineID == "" {
return nil, errors.New("missing pipeline_id claim in ID token")
}

if claims.PipelineSource == "" {
return nil, errors.New("missing pipeline_source claim in ID token")
}

if claims.JobID == "" {
return nil, errors.New("missing job_id claim in ID token")
}

if claims.Ref == "" {
return nil, errors.New("missing ref claim in ID token")
}

if claims.RefType == "" {
return nil, errors.New("missing ref_type claim in ID token")
}

return &jobPrincipal{
subject: token.Subject,
issuer: token.Issuer,
url: fmt.Sprintf("https://gitlab.com/%s/-/jobs/%s", claims.ProjectPath, claims.JobID),
pipelineSource: claims.PipelineSource,
projectPath: claims.ProjectPath,
jobID: claims.JobID,
ref: claims.Ref,
}, nil
}

func (p jobPrincipal) Name(ctx context.Context) string {
return p.subject
}

func (p jobPrincipal) Embed(ctx context.Context, cert *x509.Certificate) error {
// Set SubjectAlternativeName to the pipeline URL on the certificate
parsed, err := url.Parse(p.url)
if err != nil {
return err
}
cert.URIs = []*url.URL{parsed}

// Embed additional information into custom extensions
cert.ExtraExtensions, err = certificate.Extensions{
Issuer: p.issuer,
}.Render()
if err != nil {
return err
}

return nil
}
Loading

0 comments on commit 21d3af4

Please sign in to comment.