Skip to content

Commit 7083535

Browse files
authored
feat: Share util functions (slsa-framework#598)
* Share util functions * update * update * update * comments * update
1 parent 55827f2 commit 7083535

File tree

17 files changed

+405
-423
lines changed

17 files changed

+405
-423
lines changed

.github/actions/secure-download-artifact/action.yml

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ inputs:
1717
runs:
1818
using: "composite"
1919
steps:
20+
- name: Validate the artifact path
21+
shell: bash
22+
env:
23+
UNTRUSTED_PATH: "${{ inputs.path }}"
24+
run: |
25+
26+
set -euo pipefail
27+
28+
if [ -e "$UNTRUSTED_PATH" ]; then
29+
echo "Path $UNTRUSTED_PATH already exists"
30+
exit 5
31+
fi
32+
2033
- name: Download the artifact
2134
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # tag=v3.0.0
2235
with:

go.sum

+6-62
Large diffs are not rendered by default.

internal/builders/generic/attest.go

+4-56
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ import (
2020
"context"
2121
"encoding/base64"
2222
"encoding/json"
23-
"io"
2423
"os"
25-
"path/filepath"
2624
"regexp"
2725
"strings"
2826

@@ -64,16 +62,6 @@ type errNoName struct {
6462
errors.WrappableError
6563
}
6664

67-
// errInvalidPath indicates an invalid path.
68-
type errInvalidPath struct {
69-
errors.WrappableError
70-
}
71-
72-
// errInternal indicates an internal error.
73-
type errInternal struct {
74-
errors.WrappableError
75-
}
76-
7765
// errDuplicateSubject indicates a duplicate subject name.
7866
type errDuplicateSubject struct {
7967
errors.WrappableError
@@ -135,46 +123,6 @@ func parseSubjects(b64str string) ([]intoto.Subject, error) {
135123
return parsed, nil
136124
}
137125

138-
func pathIsUnderCurrentDirectory(path string) error {
139-
wd, err := os.Getwd()
140-
if err != nil {
141-
return errors.Errorf(&errInternal{}, "os.Getwd(): %w", err)
142-
}
143-
p, err := filepath.Abs(path)
144-
if err != nil {
145-
return errors.Errorf(&errInternal{}, "filepath.Abs(): %w", err)
146-
}
147-
148-
if !strings.HasPrefix(p, wd+"/") &&
149-
wd != p {
150-
return errors.Errorf(&errInvalidPath{}, "invalid path: %q", path)
151-
}
152-
153-
return nil
154-
}
155-
156-
func getFile(path string) (io.Writer, error) {
157-
if path == "-" {
158-
return os.Stdout, nil
159-
}
160-
161-
if err := pathIsUnderCurrentDirectory(path); err != nil {
162-
return nil, err
163-
}
164-
165-
return os.OpenFile(filepath.Clean(path), os.O_WRONLY|os.O_CREATE, 0o600)
166-
}
167-
168-
func verifyAttestationPath(path string) error {
169-
if !strings.HasSuffix(path, "intoto.jsonl") {
170-
return errors.Errorf(&errInvalidPath{}, "invalid suffix: %q. Must be .intoto.jsonl", path)
171-
}
172-
if err := pathIsUnderCurrentDirectory(path); err != nil {
173-
return err
174-
}
175-
return nil
176-
}
177-
178126
type provenanceOnlyBuild struct {
179127
*slsa.GithubActionsBuild
180128
}
@@ -202,7 +150,7 @@ run in the context of a Github Actions workflow.`,
202150
check(err)
203151

204152
// Verify the extension path and extension.
205-
err = verifyAttestationPath(attPath)
153+
err = utils.VerifyAttestationPath(attPath)
206154
check(err)
207155

208156
var parsedSubjects []intoto.Subject
@@ -236,7 +184,7 @@ run in the context of a Github Actions workflow.`,
236184
p, err := g.Generate(ctx)
237185
check(err)
238186

239-
// Note: we verify the path within getFile().
187+
// Note: the path is validated within CreateNewFileUnderCurrentDirectory().
240188
if attPath != "" {
241189
var attBytes []byte
242190
if utils.IsPresubmitTests() {
@@ -257,7 +205,7 @@ run in the context of a Github Actions workflow.`,
257205
attBytes = att.Bytes()
258206
}
259207

260-
f, err := getFile(attPath)
208+
f, err := utils.CreateNewFileUnderCurrentDirectory(attPath, os.O_WRONLY)
261209
check(err)
262210

263211
_, err = f.Write(attBytes)
@@ -268,7 +216,7 @@ run in the context of a Github Actions workflow.`,
268216
pb, err := json.Marshal(p.Predicate)
269217
check(err)
270218

271-
pf, err := getFile(predicatePath)
219+
pf, err := utils.CreateNewFileUnderCurrentDirectory(predicatePath, os.O_WRONLY)
272220
check(err)
273221

274222
_, err = pf.Write(pb)

internal/builders/generic/attest_test.go

-114
Original file line numberDiff line numberDiff line change
@@ -11,120 +11,6 @@ import (
1111
"github.com/slsa-framework/slsa-github-generator/internal/errors"
1212
)
1313

14-
func Test_pathIsUnderCurrentDirectory(t *testing.T) {
15-
t.Parallel()
16-
17-
tests := []struct {
18-
name string
19-
path string
20-
expected error
21-
}{
22-
{
23-
name: "valid same path",
24-
path: "./",
25-
expected: nil,
26-
},
27-
{
28-
name: "valid path no slash",
29-
path: "./some/valid/path",
30-
expected: nil,
31-
},
32-
{
33-
name: "valid path with slash",
34-
path: "./some/valid/path/",
35-
expected: nil,
36-
},
37-
{
38-
name: "valid path with no dot",
39-
path: "some/valid/path/",
40-
expected: nil,
41-
},
42-
{
43-
name: "some valid path",
44-
path: "../generic/some/valid/path",
45-
expected: nil,
46-
},
47-
{
48-
name: "parent invalid path",
49-
path: "../invalid/path",
50-
expected: &errInvalidPath{},
51-
},
52-
{
53-
name: "some invalid fullpath",
54-
path: "/some/invalid/fullpath",
55-
expected: &errInvalidPath{},
56-
},
57-
}
58-
for _, tt := range tests {
59-
tt := tt // Re-initializing variable so it is not changed while executing the closure below
60-
t.Run(tt.name, func(t *testing.T) {
61-
t.Parallel()
62-
63-
err := pathIsUnderCurrentDirectory(tt.path)
64-
if (err == nil && tt.expected != nil) ||
65-
(err != nil && tt.expected == nil) {
66-
t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
67-
}
68-
69-
if err != nil && !errors.As(err, &tt.expected) {
70-
t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
71-
}
72-
})
73-
}
74-
}
75-
76-
func Test_verifyAttestationPath(t *testing.T) {
77-
t.Parallel()
78-
79-
tests := []struct {
80-
name string
81-
path string
82-
expected error
83-
}{
84-
{
85-
name: "valid file",
86-
path: "./path/to/valid.intoto.jsonl",
87-
expected: nil,
88-
},
89-
{
90-
name: "invalid path",
91-
path: "../some/invalid/valid.intoto.jsonl",
92-
expected: &errInvalidPath{},
93-
},
94-
{
95-
name: "invalid extension",
96-
path: "some/file.ntoto.jsonl",
97-
expected: &errInvalidPath{},
98-
},
99-
{
100-
name: "invalid not exntension",
101-
path: "some/file.intoto.jsonl.",
102-
expected: &errInvalidPath{},
103-
},
104-
{
105-
name: "invalid folder exntension",
106-
path: "file.intoto.jsonl/file",
107-
expected: &errInvalidPath{},
108-
},
109-
}
110-
for _, tt := range tests {
111-
tt := tt // Re-initializing variable so it is not changed while executing the closure below
112-
t.Run(tt.name, func(t *testing.T) {
113-
t.Parallel()
114-
115-
err := verifyAttestationPath(tt.path)
116-
if (err == nil && tt.expected != nil) ||
117-
(err != nil && tt.expected == nil) {
118-
t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
119-
}
120-
121-
if err != nil && !errors.As(err, &tt.expected) {
122-
t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
123-
}
124-
})
125-
}
126-
}
127-
12814
// TestParseSubjects tests the parseSubjects function.
12915
func TestParseSubjects(t *testing.T) {
13016
testCases := []struct {

internal/builders/go/main.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"flag"
2121
"fmt"
2222
"io"
23-
"io/ioutil"
2423
"os"
2524
"os/exec"
2625
"path/filepath"
@@ -31,6 +30,7 @@ import (
3130
_ "github.com/sigstore/cosign/pkg/providers/github"
3231

3332
"github.com/slsa-framework/slsa-github-generator/internal/builders/go/pkg"
33+
"github.com/slsa-framework/slsa-github-generator/internal/utils"
3434
)
3535

3636
func usage(p string) {
@@ -84,7 +84,11 @@ func runProvenanceGeneration(subject, digest, commands, envs, workingDir, rekor
8484
}
8585

8686
filename := fmt.Sprintf("%s.intoto.jsonl", subject)
87-
err = ioutil.WriteFile(filename, attBytes, 0o600)
87+
f, err := utils.CreateNewFileUnderCurrentDirectory(filename, os.O_WRONLY)
88+
if err != nil {
89+
return err
90+
}
91+
_, err = f.Write(attBytes)
8892
if err != nil {
8993
return err
9094
}

internal/builders/go/main_test.go

+6-10
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,18 @@ import (
1111
"regexp"
1212
"testing"
1313

14-
"github.com/slsa-framework/slsa-github-generator/internal/builders/go/pkg"
15-
1614
"github.com/google/go-cmp/cmp"
1715
"github.com/google/go-cmp/cmp/cmpopts"
16+
17+
"github.com/slsa-framework/slsa-github-generator/internal/builders/go/pkg"
18+
"github.com/slsa-framework/slsa-github-generator/internal/utils"
1819
)
1920

2021
func errCmp(e1, e2 error) bool {
2122
return errors.Is(e1, e2) || errors.Is(e2, e1)
2223
}
2324

24-
func Test_runVerify(t *testing.T) {
25+
func Test_runBuild(t *testing.T) {
2526
t.Parallel()
2627
tests := []struct {
2728
subject string
@@ -237,11 +238,6 @@ func Test_runVerify(t *testing.T) {
237238
config: "./pkg/testdata/releaser-invalid-envs.yml",
238239
err: pkg.ErrorInvalidEnvironmentVariable,
239240
},
240-
{
241-
name: "invalid main",
242-
config: "./pkg/testdata/releaser-invalid-main.yml",
243-
err: pkg.ErrorInvalidDirectory,
244-
},
245241
{
246242
name: "invalid path",
247243
config: "../pkg/testdata/releaser-invalid-main.yml",
@@ -391,12 +387,12 @@ func extract(lines string) ([]string, []string, string, string, error) {
391387
return []string{}, []string{}, "", "", err
392388
}
393389

394-
cmd, err := pkg.UnmarshallList(scmd)
390+
cmd, err := utils.UnmarshalList(scmd)
395391
if err != nil {
396392
return []string{}, []string{}, "", "", err
397393
}
398394

399-
env, err := pkg.UnmarshallList(senv)
395+
env, err := utils.UnmarshalList(senv)
400396
if err != nil {
401397
return []string{}, []string{}, "", "", err
402398
}

internal/builders/go/pkg/build.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"regexp"
2323
"strings"
2424
"syscall"
25+
26+
"github.com/slsa-framework/slsa-github-generator/internal/utils"
2527
)
2628

2729
var (
@@ -117,7 +119,7 @@ func (b *GoBuild) Run(dry bool) error {
117119

118120
// Share the resolved name of the binary.
119121
fmt.Printf("::set-output name=go-binary-name::%s\n", filename)
120-
command, err := marshallToString(com)
122+
command, err := utils.MarshalToString(com)
121123
if err != nil {
122124
return err
123125
}
@@ -129,7 +131,7 @@ func (b *GoBuild) Run(dry bool) error {
129131
return err
130132
}
131133

132-
menv, err := marshallToString(env)
134+
menv, err := utils.MarshalToString(env)
133135
if err != nil {
134136
return err
135137
}

0 commit comments

Comments
 (0)