github.com/yogeshkumararora/slsa-github-generator@v1.10.1-0.20240520161934-11278bd5afb4/slsa/provenance.go (about) 1 // Copyright 2022 SLSA Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package slsa 16 17 import ( 18 "context" 19 "fmt" 20 "regexp" 21 22 intoto "github.com/in-toto/in-toto-golang/in_toto" 23 slsacommon "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common" 24 slsa02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2" 25 ) 26 27 const ( 28 // GithubHostedActionsBuilderID is a default builder ID for Github hosted actions. 29 GithubHostedActionsBuilderID = "https://github.com/Attestations/GitHubHostedActions@v1" 30 ) 31 32 var githubComReplace = regexp.MustCompile(`^(https?://)?github\.com/?`) 33 34 // HostedActionsGenerator is a SLSA provenance generator for Github Hosted 35 // Actions. Provenance is generated based on a "build type" which defines the 36 // format for many of the fields in the provenance metadata. Builders for 37 // different ecosystems (languages etc.) can implement a build type from 38 // scratch or by extending GithubActionsBuild. 39 type HostedActionsGenerator struct { 40 buildType BuildType 41 clients ClientProvider 42 } 43 44 // NewHostedActionsGenerator returns a SLSA provenance generator for the given build type. 45 func NewHostedActionsGenerator(bt BuildType) *HostedActionsGenerator { 46 return &HostedActionsGenerator{ 47 buildType: bt, 48 clients: &DefaultClientProvider{}, 49 } 50 } 51 52 // Generate generates an in-toto provenance statement in SLSA v0.2 format. 53 func (g *HostedActionsGenerator) Generate(ctx context.Context) (*intoto.ProvenanceStatement, error) { 54 // NOTE: Use buildType as the audience as that closely matches the intended 55 // recipient of the OIDC token. 56 // NOTE: GitHub doesn't allow github.com in the audience so remove it. 57 audience := githubComReplace.ReplaceAllString(g.buildType.URI(), "") 58 59 oidcClient, err := g.clients.OIDCClient() 60 if err != nil { 61 return nil, err 62 } 63 64 // We allow nil OIDC client to support e2e tests on pull requests. 65 builderID := GithubHostedActionsBuilderID 66 if oidcClient != nil { 67 t, err := oidcClient.Token(ctx, []string{audience}) 68 if err != nil { 69 return nil, err 70 } 71 72 if t.JobWorkflowRef != "" { 73 builderID = fmt.Sprintf("https://github.com/%s", t.JobWorkflowRef) 74 } 75 } 76 77 subject, err := g.buildType.Subject(ctx) 78 if err != nil { 79 return nil, err 80 } 81 82 invocation, err := g.buildType.Invocation(ctx) 83 if err != nil { 84 return nil, err 85 } 86 87 buildConfig, err := g.buildType.BuildConfig(ctx) 88 if err != nil { 89 return nil, err 90 } 91 92 materials, err := g.buildType.Materials(ctx) 93 if err != nil { 94 return nil, err 95 } 96 97 metadata, err := g.buildType.Metadata(ctx) 98 if err != nil { 99 return nil, err 100 } 101 102 return &intoto.ProvenanceStatement{ 103 StatementHeader: intoto.StatementHeader{ 104 Type: intoto.StatementInTotoV01, 105 PredicateType: slsa02.PredicateSLSAProvenance, 106 Subject: subject, 107 }, 108 Predicate: slsa02.ProvenancePredicate{ 109 BuildType: g.buildType.URI(), 110 Builder: slsacommon.ProvenanceBuilder{ 111 ID: builderID, 112 }, 113 Invocation: invocation, 114 BuildConfig: buildConfig, 115 Materials: materials, 116 Metadata: metadata, 117 }, 118 }, nil 119 } 120 121 // WithClients overrides the default ClientProvider. Useful for tests where 122 // clients are not available. 123 func (g *HostedActionsGenerator) WithClients(c ClientProvider) *HostedActionsGenerator { 124 g.clients = c 125 return g 126 }