Skip to content

Commit

Permalink
Add GitLab project_visibility
Browse files Browse the repository at this point in the history
Signed-off-by: Philip Harrison <philip@mailharrison.com>
  • Loading branch information
feelepxyz committed Jul 18, 2023
1 parent 6237781 commit 1072133
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 70 deletions.
2 changes: 1 addition & 1 deletion docs/oid-info.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ that Sigstore operates.
| workflow_sha | ci_config_sha ([WIP][gitlab-wip-cliams]) | ?? | ?? | Build Config Digest | An immutable reference to the specific version of the top-level build instructions. Should include the digest type followed by the digest, e.g. `sha1:abc123`. |
| event_name | pipeline_source | ?? | ?? | Build Trigger | The event or action that triggered the build. |
| server_url + repository + "/actions/runs/" + run_id + "/attempts/" + run_attempt | server_url + project_path + /-/jobs/ + job_id | ?? | ?? | Run Invocation URI | An immutable identifier that can uniquely identify the build execution |
| repository_visibility | ?? | ?? | ?? | Source Repository Visibility At Signing | Source repository visibility at the time of signing the certificate |
| repository_visibility | project_visibility | ?? | ?? | Source Repository Visibility At Signing | Source repository visibility at the time of signing the certificate |

[github-oidc-doc]: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token
[oid-link]: http://oid-info.com/get/1.3.6.1.4.1.57264
Expand Down
1 change: 1 addition & 0 deletions pkg/identity/gitlabcom/issuer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func TestIssuer(t *testing.T) {
"ref": "main",
"ref_type": "branch",
"ref_protected": "true",
"project_visibility": "public",
"jti": "914910cc-09f6-4217-8091-a1d3231a37db",
"iss": "https://gitlab.com",
"iat": 1674658264,
Expand Down
34 changes: 20 additions & 14 deletions pkg/identity/gitlabcom/principal.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ type jobPrincipal struct {

// The type of runner used by the job. May be one of gitlab-hosted or self-hosted.
runnerEnvironment string

// Visibility of the source project
projectVisibility string
}

func JobPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.Principal, error) {
Expand All @@ -95,6 +98,7 @@ func JobPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.P
Sha string `json:"sha"`
RunnerEnvironment string `json:"runner_environment"`
RunnerID int64 `json:"runner_id"`
ProjectVisibility string `json:"project_visibility"`
}

if err := token.Claims(&claims); err != nil {
Expand Down Expand Up @@ -180,6 +184,7 @@ func JobPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.P
sha: claims.Sha,
runnerID: claims.RunnerID,
runnerEnvironment: claims.RunnerEnvironment,
projectVisibility: claims.ProjectVisibility,
}, nil
}

Expand Down Expand Up @@ -212,20 +217,21 @@ func (p jobPrincipal) Embed(_ context.Context, cert *x509.Certificate) error {

// Embed additional information into custom extensions
cert.ExtraExtensions, err = certificate.Extensions{
Issuer: p.issuer,
BuildConfigURI: ciConfigRefURL.String(),
BuildConfigDigest: p.ciConfigSha,
BuildSignerURI: ciConfigRefURL.String(),
BuildSignerDigest: p.ciConfigSha,
RunnerEnvironment: p.runnerEnvironment,
SourceRepositoryURI: baseURL.JoinPath(p.repository).String(),
SourceRepositoryDigest: p.sha,
SourceRepositoryRef: p.ref,
SourceRepositoryIdentifier: p.repositoryID,
SourceRepositoryOwnerURI: baseURL.JoinPath(p.repositoryOwner).String(),
SourceRepositoryOwnerIdentifier: p.repositoryOwnerID,
BuildTrigger: p.eventName,
RunInvocationURI: baseURL.JoinPath(p.repository, "/-/jobs/", p.jobID).String(),
Issuer: p.issuer,
BuildConfigURI: ciConfigRefURL.String(),
BuildConfigDigest: p.ciConfigSha,
BuildSignerURI: ciConfigRefURL.String(),
BuildSignerDigest: p.ciConfigSha,
RunnerEnvironment: p.runnerEnvironment,
SourceRepositoryURI: baseURL.JoinPath(p.repository).String(),
SourceRepositoryDigest: p.sha,
SourceRepositoryRef: p.ref,
SourceRepositoryIdentifier: p.repositoryID,
SourceRepositoryOwnerURI: baseURL.JoinPath(p.repositoryOwner).String(),
SourceRepositoryOwnerIdentifier: p.repositoryOwnerID,
BuildTrigger: p.eventName,
RunInvocationURI: baseURL.JoinPath(p.repository, "/-/jobs/", p.jobID).String(),
SourceRepositoryVisibilityAtSigning: p.projectVisibility,
}.Render()
if err != nil {
return err
Expand Down
161 changes: 106 additions & 55 deletions pkg/identity/gitlabcom/principal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
"sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"runner_id": 1,
"runner_environment": "gitlab-hosted",
"project_visibility": "public",
},
ExpectPrincipal: jobPrincipal{
issuer: "https://gitlab.com",
Expand All @@ -75,64 +76,68 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
runnerID: 1,
runnerEnvironment: "gitlab-hosted",
sha: "714a629c0b401fdce83e847fc9589983fc6f46bc",
projectVisibility: "public",
},
WantErr: false,
},
`Token missing pipeline_source claim should be rejected`: {
Claims: map[string]interface{}{
"aud": "sigstore",
"exp": 0,
"iss": "https://gitlab.com",
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"ci_config_ref_uri": "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
"ci_config_sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"project_id": "42831435",
"project_path": "cpanato/testing-cosign",
"namespace_path": "cpanato",
"namespace_id": "1730270",
"pipeline_id": "757451528",
"job_id": "3659681386",
"ref": "main",
"ref_type": "branch",
"aud": "sigstore",
"exp": 0,
"iss": "https://gitlab.com",
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"ci_config_ref_uri": "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
"ci_config_sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"project_id": "42831435",
"project_path": "cpanato/testing-cosign",
"namespace_path": "cpanato",
"namespace_id": "1730270",
"pipeline_id": "757451528",
"job_id": "3659681386",
"ref": "main",
"ref_type": "branch",
"project_visibility": "public",
},
WantErr: true,
ErrContains: "pipeline_source",
},
`Token missing project_path claim should be rejected`: {
Claims: map[string]interface{}{
"aud": "sigstore",
"exp": 0,
"iss": "https://gitlab.com",
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"ci_config_ref_uri": "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
"ci_config_sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"project_id": "42831435",
"pipeline_id": "757451528",
"namespace_id": "1730270",
"pipeline_source": "push",
"namespace_path": "cpanato",
"job_id": "3659681386",
"ref": "main",
"ref_type": "branch",
"aud": "sigstore",
"exp": 0,
"iss": "https://gitlab.com",
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"ci_config_ref_uri": "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
"ci_config_sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"project_id": "42831435",
"pipeline_id": "757451528",
"namespace_id": "1730270",
"pipeline_source": "push",
"namespace_path": "cpanato",
"job_id": "3659681386",
"ref": "main",
"ref_type": "branch",
"project_visibility": "public",
},
WantErr: true,
ErrContains: "project_path",
},
`Token missing ci_config_ref_uri claim should be rejected`: {
Claims: map[string]interface{}{
"aud": "sigstore",
"exp": 0,
"iss": "https://gitlab.com",
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"project_id": "42831435",
"project_path": "cpanato/testing-cosign",
"pipeline_id": "757451528",
"namespace_id": "1730270",
"pipeline_source": "push",
"namespace_path": "cpanato",
"job_id": "3659681386",
"ref": "main",
"ref_type": "branch",
"aud": "sigstore",
"exp": 0,
"iss": "https://gitlab.com",
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"project_id": "42831435",
"project_path": "cpanato/testing-cosign",
"pipeline_id": "757451528",
"namespace_id": "1730270",
"pipeline_source": "push",
"namespace_path": "cpanato",
"job_id": "3659681386",
"ref": "main",
"ref_type": "branch",
"project_visibility": "public",
},
WantErr: true,
ErrContains: "ci_config_ref_uri",
Expand All @@ -156,6 +161,7 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
"sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"runner_id": 1,
"runner_environment": "gitlab-hosted",
"project_visibility": "public",
},
ExpectPrincipal: jobPrincipal{
issuer: "https://gitlab.com",
Expand All @@ -173,6 +179,48 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
runnerID: 1,
runnerEnvironment: "gitlab-hosted",
sha: "714a629c0b401fdce83e847fc9589983fc6f46bc",
projectVisibility: "public",
},
WantErr: false,
},
`Token missing project_visibility is ok`: {
Claims: map[string]interface{}{
"aud": "sigstore",
"exp": 0,
"iss": "https://gitlab.com",
"sub": "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
"project_id": "42831435",
"project_path": "cpanato/testing-cosign",
"namespace_path": "cpanato",
"namespace_id": "1730270",
"pipeline_id": "757451528",
"pipeline_source": "push",
"ci_config_ref_uri": "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
"ci_config_sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"job_id": "3659681386",
"ref": "main",
"ref_type": "branch",
"sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"runner_id": 1,
"runner_environment": "gitlab-hosted",
},
ExpectPrincipal: jobPrincipal{
issuer: "https://gitlab.com",
subject: "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
url: "https://gitlab.com/",
eventName: "push",
pipelineID: "757451528",
ciConfigRefURI: "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
ciConfigSha: "714a629c0b401fdce83e847fc9589983fc6f46bc",
repository: "cpanato/testing-cosign",
repositoryID: "42831435",
repositoryOwner: "cpanato",
repositoryOwnerID: "1730270",
jobID: "3659681386",
ref: "refs/heads/main",
runnerID: 1,
runnerEnvironment: "gitlab-hosted",
sha: "714a629c0b401fdce83e847fc9589983fc6f46bc",
},
WantErr: false,
},
Expand Down Expand Up @@ -249,6 +297,7 @@ func TestName(t *testing.T) {
"sha": "714a629c0b401fdce83e847fc9589983fc6f46bc",
"runner_id": 1,
"runner_environment": "gitlab-hosted",
"project_visibility": "public",
},
ExpectName: "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
},
Expand Down Expand Up @@ -304,23 +353,25 @@ func TestEmbed(t *testing.T) {
runnerID: 1,
runnerEnvironment: "gitlab-hosted",
sha: "sha",
projectVisibility: "public",
},
WantErr: false,
WantFacts: map[string]func(x509.Certificate) error{
`Certificate has correct issuer (v2) extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://gitlab.com"),
`Certificate has correct builder signer URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
`Certificate has correct builder signer digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
`Certificate has correct runner environment extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "gitlab-hosted"),
`Certificate has correct source repo URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://gitlab.com/cpanato/testing-cosign"),
`Certificate has correct source repo digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"),
`Certificate has correct source repo ref extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"),
`Certificate has correct source repo ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "42831435"),
`Certificate has correct source repo owner URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://gitlab.com/cpanato"),
`Certificate has correct source repo owner ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "1730270"),
`Certificate has correct build config URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
`Certificate has correct build config digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
`Certificate has correct build trigger extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "push"),
`Certificate has correct run invocation ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://gitlab.com/cpanato/testing-cosign/-/jobs/3659681386"),
`Certificate has correct issuer (v2) extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://gitlab.com"),
`Certificate has correct builder signer URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
`Certificate has correct builder signer digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
`Certificate has correct runner environment extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "gitlab-hosted"),
`Certificate has correct source repo URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://gitlab.com/cpanato/testing-cosign"),
`Certificate has correct source repo digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"),
`Certificate has correct source repo ref extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"),
`Certificate has correct source repo ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "42831435"),
`Certificate has correct source repo owner URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://gitlab.com/cpanato"),
`Certificate has correct source repo owner ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "1730270"),
`Certificate has correct build config URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
`Certificate has correct build config digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
`Certificate has correct build trigger extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "push"),
`Certificate has correct run invocation ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://gitlab.com/cpanato/testing-cosign/-/jobs/3659681386"),
`Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"),
},
},
`GitLab job principal with bad URL fails`: {
Expand Down
3 changes: 3 additions & 0 deletions pkg/server/grpc_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,7 @@ type gitlabClaims struct {
Sha string `json:"sha"`
RunnerEnvironment string `json:"runner_environment"`
RunnerID int64 `json:"runner_id"`
ProjectVisibility string `json:"project_visibility"`
}

// Tests API for GitLab subject types
Expand Down Expand Up @@ -1004,6 +1005,7 @@ func TestAPIWithGitLab(t *testing.T) {
Sha: "714a629c0b401fdce83e847fc9589983fc6f46bc",
RunnerID: 1,
RunnerEnvironment: "gitlab-hosted",
ProjectVisibility: "public",
}

gitLabSubject := fmt.Sprintf("project_path:%s:ref_type:%s:ref:%s", claims.ProjectPath, claims.RefType, claims.Ref)
Expand Down Expand Up @@ -1081,6 +1083,7 @@ func TestAPIWithGitLab(t *testing.T) {
19: claims.CiConfigSha,
20: claims.PipelineSource,
21: baseURL + claims.ProjectPath + "/-/jobs/" + claims.JobID,
22: claims.ProjectVisibility,
}
for o, value := range expectedExts {
ext, found := findCustomExtension(leafCert, asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, o})
Expand Down

0 comments on commit 1072133

Please sign in to comment.