Skip to content

Commit 40c607f

Browse files
authored
feat: Record vars in SLSA generators (#3633)
# Summary Records the GitHub [vars context](https://docs.github.com/en/actions/learn-github-actions/contexts#vars-context) in the SLSA invocation in the generic generator and container generator. The `vars` context is passed to the "builder" binary as a JSON blob via the `GITHUB_VARS` environment variable. The values are then recorded in the `invocation.parameters.vars` field of the provenance predicate. Masking of inputs or vars is not supported. Note that the `vars` context is set to the variables for the *repository that initiated the GitHub Actions run* and not the reusable workflow's repository. Updates #1555 ## Testing Process - Set a variable on the test repo - Go to Settings -> Secrets & variables -> Actions and then click on the Variables tab. - Set some test variables. - Generate provenance as normal using the generic generator or container generator - Note that the `compile-generator: true` input must be set. - Examine the `invocation.parameters.vars` field in the resulting provenance. The vars should be recorded there. ## Checklist - [x] Review the contributing [guidelines](https://github.com/slsa-framework/slsa-github-generator/blob/main/CONTRIBUTING.md) - [x] Add a reference to related issues in the PR description. - [x] Update documentation if applicable (added #3627 to track) - [x] Add unit tests if applicable. - [x] Add changes to the [CHANGELOG](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md) if applicable. --------- Signed-off-by: Ian Lewis <[email protected]> Signed-off-by: Ian Lewis <[email protected]>
1 parent 556329f commit 40c607f

File tree

12 files changed

+322
-24
lines changed

12 files changed

+322
-24
lines changed

.github/workflows/generator_container_slsa3.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ jobs:
266266
UNTRUSTED_IMAGE: "${{ inputs.image }}"
267267
UNTRUSTED_DIGEST: "${{ inputs.digest }}"
268268
GITHUB_CONTEXT: "${{ toJSON(github) }}"
269+
VARS_CONTEXT: "${{ toJSON(vars) }}"
269270
UNTRUSTED_PROVENANCE_REPOSITORY: "${{ inputs.provenance-repository }}"
270271
run: |
271272
set -euo pipefail

.github/workflows/generator_generic_slsa3.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ jobs:
218218
# See: https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections
219219
env:
220220
GITHUB_CONTEXT: "${{ toJSON(github) }}"
221+
VARS_CONTEXT: "${{ toJSON(vars) }}"
221222
UNTRUSTED_PROVENANCE_NAME: "${{ inputs.provenance-name }}"
222223
run: |
223224
set -euo pipefail

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
<!-- toc -->
1111

12+
- [Unreleased](#unreleased)
13+
- [Unreleased: Vars context recorded in provenance](#unreleased-vars-context-recorded-in-provenance)
1214
- [v2.0.0](#v200)
1315
- [v2.0.0: Breaking Change: upload-artifact and download-artifact](#v200-breaking-change-upload-artifact-and-download-artifact)
1416
- [v2.0.0: Breaking Change: attestation-name Workflow Input and Output](#v200-breaking-change-attestation-name-workflow-input-and-output)
@@ -102,6 +104,14 @@ Use the format "X.Y.Z: Go builder" etc. for format headers to avoid header name
102104
duplication."
103105
-->
104106

107+
## Unreleased
108+
109+
### Unreleased: Vars context recorded in provenance
110+
111+
- **Updated**: GitHub `vars` context is now recorded in provenance for the generic and
112+
container generators. The `vars` context cannot affect the build in the Go
113+
builder so it is not recorded.
114+
105115
## v2.0.0
106116

107117
### v2.0.0: Breaking Change: upload-artifact and download-artifact

github/workflow.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,26 @@ import (
2323

2424
const (
2525
githubContextEnvKey = "GITHUB_CONTEXT"
26+
varsContextEnvKey = "VARS_CONTEXT"
2627
)
2728

29+
// VarsContext is the `vars` context.
30+
//
31+
// See: https://docs.github.com/en/actions/learn-github-actions/contexts#vars-context
32+
type VarsContext map[string]string
33+
34+
// GetVarsContext returns the current GitHub Actions 'vars' context.
35+
func GetVarsContext() (VarsContext, error) {
36+
v := VarsContext(make(map[string]string))
37+
varsContext, ok := os.LookupEnv(varsContextEnvKey)
38+
if !ok {
39+
return v, fmt.Errorf("%s environment variable not set", varsContextEnvKey)
40+
}
41+
42+
err := json.Unmarshal([]byte(varsContext), &v)
43+
return v, err
44+
}
45+
2846
// WorkflowContext is the `github` context given to workflows that contains
2947
// information about the GitHub Actions workflow run.
3048
//
@@ -70,7 +88,7 @@ func GetWorkflowContext() (WorkflowContext, error) {
7088
w := WorkflowContext{}
7189
ghContext, ok := os.LookupEnv(githubContextEnvKey)
7290
if !ok {
73-
return w, errors.New("GITHUB_CONTEXT environment variable not set")
91+
return w, fmt.Errorf("%s environment variable not set", githubContextEnvKey)
7492
}
7593

7694
err := json.Unmarshal([]byte(ghContext), &w)

internal/builders/container/generate.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ that it is being run in the context of a Github Actions workflow.`,
4141
ghContext, err := github.GetWorkflowContext()
4242
check(err)
4343

44+
varsContext, err := github.GetVarsContext()
45+
check(err)
46+
4447
ctx := context.Background()
4548

4649
b := common.GenericBuild{
4750
// NOTE: Subjects are nil because we are only writing the predicate.
48-
GithubActionsBuild: slsa.NewGithubActionsBuild(nil, &ghContext),
51+
GithubActionsBuild: slsa.NewGithubActionsBuild(nil, &ghContext, varsContext),
4952
BuildTypeURI: containerBuildType,
5053
}
5154

internal/builders/container/generate_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func checkTest(t *testing.T) func(err error) {
3535

3636
func Test_generateCmd_default_predicate(t *testing.T) {
3737
t.Setenv("GITHUB_CONTEXT", "{}")
38+
t.Setenv("VARS_CONTEXT", "{}")
3839

3940
// Change to temporary dir
4041
currentDir, err := os.Getwd()
@@ -69,6 +70,7 @@ func Test_generateCmd_default_predicate(t *testing.T) {
6970

7071
func Test_generateCmd_custom_predicate(t *testing.T) {
7172
t.Setenv("GITHUB_CONTEXT", "{}")
73+
t.Setenv("VARS_CONTEXT", "{}")
7274

7375
// Change to temporary dir
7476
currentDir, err := os.Getwd()
@@ -104,6 +106,7 @@ func Test_generateCmd_custom_predicate(t *testing.T) {
104106

105107
func Test_generateCmd_invalid_path(t *testing.T) {
106108
t.Setenv("GITHUB_CONTEXT", "{}")
109+
t.Setenv("VARS_CONTEXT", "{}")
107110

108111
// Change to temporary dir
109112
currentDir, err := os.Getwd()

internal/builders/generic/attest.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ run in the context of a Github Actions workflow.`,
5151
ghContext, err := github.GetWorkflowContext()
5252
check(err)
5353

54+
varsContext, err := github.GetVarsContext()
55+
check(err)
56+
5457
subjectsBytes, err := utils.SafeReadFile(subjectsFilename)
5558
check(err)
5659
parsedSubjects, err := parseSubjects(string(subjectsBytes))
@@ -78,7 +81,7 @@ run in the context of a Github Actions workflow.`,
7881
ctx := context.Background()
7982

8083
b := common.GenericBuild{
81-
GithubActionsBuild: slsa.NewGithubActionsBuild(parsedSubjects, &ghContext),
84+
GithubActionsBuild: slsa.NewGithubActionsBuild(parsedSubjects, &ghContext, varsContext),
8285
BuildTypeURI: provenanceOnlyBuildType,
8386
}
8487
if provider != nil {

internal/builders/generic/attest_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ func createTmpFile(content string) (string, error) {
223223
// Test_attestCmd tests the attest command.
224224
func Test_attestCmd_default_single_artifact(t *testing.T) {
225225
t.Setenv("GITHUB_CONTEXT", "{}")
226+
t.Setenv("VARS_CONTEXT", "{}")
226227

227228
// Change to temporary dir
228229
currentDir, err := os.Getwd()
@@ -265,6 +266,7 @@ func Test_attestCmd_default_single_artifact(t *testing.T) {
265266

266267
func Test_attestCmd_default_multi_artifact(t *testing.T) {
267268
t.Setenv("GITHUB_CONTEXT", "{}")
269+
t.Setenv("VARS_CONTEXT", "{}")
268270

269271
// Change to temporary dir
270272
currentDir, err := os.Getwd()
@@ -309,6 +311,7 @@ b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c artifact2`)))
309311

310312
func Test_attestCmd_custom_provenance_name(t *testing.T) {
311313
t.Setenv("GITHUB_CONTEXT", "{}")
314+
t.Setenv("VARS_CONTEXT", "{}")
312315

313316
// Change to temporary dir
314317
currentDir, err := os.Getwd()
@@ -352,6 +355,7 @@ func Test_attestCmd_custom_provenance_name(t *testing.T) {
352355

353356
func Test_attestCmd_invalid_extension(t *testing.T) {
354357
t.Setenv("GITHUB_CONTEXT", "{}")
358+
t.Setenv("VARS_CONTEXT", "{}")
355359

356360
// Change to temporary dir
357361
currentDir, err := os.Getwd()
@@ -405,6 +409,7 @@ func Test_attestCmd_invalid_extension(t *testing.T) {
405409

406410
func Test_attestCmd_invalid_path(t *testing.T) {
407411
t.Setenv("GITHUB_CONTEXT", "{}")
412+
t.Setenv("VARS_CONTEXT", "{}")
408413

409414
// Change to temporary dir
410415
currentDir, err := os.Getwd()
@@ -460,6 +465,7 @@ func Test_attestCmd_invalid_path(t *testing.T) {
460465
// subjects in subdirectories.
461466
func Test_attestCmd_subdirectory_artifact(t *testing.T) {
462467
t.Setenv("GITHUB_CONTEXT", "{}")
468+
t.Setenv("VARS_CONTEXT", "{}")
463469

464470
// Change to temporary dir
465471
currentDir, err := os.Getwd()

internal/builders/go/pkg/provenance.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func GenerateProvenance(name, digest, command, envs, workingDir string,
9999
"sha256": digest,
100100
},
101101
},
102-
}, &gh),
102+
}, &gh, nil),
103103
buildConfig: buildConfig{
104104
Version: buildConfigVersion,
105105
Steps: []step{

internal/builders/go/pkg/provenance_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func TestGenerateProvenance_withErr(t *testing.T) {
2626
// TODO(github.com/slsa-framework/slsa-github-generator/issues/124): Remove
2727
t.Setenv("GITHUB_EVENT_NAME", "non_event")
2828
t.Setenv("GITHUB_CONTEXT", "{}")
29+
t.Setenv("VARS_CONTEXT", "{}")
2930
sha256 := "2e0390eb024a52963db7b95e84a9c2b12c004054a7bad9a97ec0c7c89d4681d2"
3031
_, err := GenerateProvenance(
3132
"foo", sha256, "", "", "/home/foo",

0 commit comments

Comments
 (0)