Skip to content

Commit b2a77c4

Browse files
authored
Merge pull request #6210 from tonistiigi/provenance-custom-env
provenance: add custom fields support
2 parents ba23d6f + 8ecdc0a commit b2a77c4

File tree

15 files changed

+193
-46
lines changed

15 files changed

+193
-46
lines changed

client/client_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11323,14 +11323,14 @@ func (s *server) run(a agent.Agent) error {
1132311323

1132411324
type secModeSandbox struct{}
1132511325

11326-
func (*secModeSandbox) UpdateConfigFile(in string) string {
11327-
return in
11326+
func (*secModeSandbox) UpdateConfigFile(in string) (string, func() error) {
11327+
return in, nil
1132811328
}
1132911329

1133011330
type secModeInsecure struct{}
1133111331

11332-
func (*secModeInsecure) UpdateConfigFile(in string) string {
11333-
return in + "\n\ninsecure-entitlements = [\"security.insecure\"]\n"
11332+
func (*secModeInsecure) UpdateConfigFile(in string) (string, func() error) {
11333+
return in + "\n\ninsecure-entitlements = [\"security.insecure\"]\n", nil
1133411334
}
1133511335

1133611336
var (
@@ -11340,19 +11340,19 @@ var (
1134011340

1134111341
type netModeHost struct{}
1134211342

11343-
func (*netModeHost) UpdateConfigFile(in string) string {
11344-
return in + "\n\ninsecure-entitlements = [\"network.host\"]\n"
11343+
func (*netModeHost) UpdateConfigFile(in string) (string, func() error) {
11344+
return in + "\n\ninsecure-entitlements = [\"network.host\"]\n", nil
1134511345
}
1134611346

1134711347
type netModeDefault struct{}
1134811348

11349-
func (*netModeDefault) UpdateConfigFile(in string) string {
11350-
return in
11349+
func (*netModeDefault) UpdateConfigFile(in string) (string, func() error) {
11350+
return in, nil
1135111351
}
1135211352

1135311353
type netModeBridgeDNS struct{}
1135411354

11355-
func (*netModeBridgeDNS) UpdateConfigFile(in string) string {
11355+
func (*netModeBridgeDNS) UpdateConfigFile(in string) (string, func() error) {
1135611356
return in + `
1135711357
# configure bridge networking
1135811358
[worker.oci]
@@ -11365,7 +11365,7 @@ cniConfigPath = "/etc/buildkit/dns-cni.conflist"
1136511365
1136611366
[dns]
1136711367
nameservers = ["10.11.0.1"]
11368-
`
11368+
`, nil
1136911369
}
1137011370

1137111371
var (

cmd/buildkitd/config/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ type Config struct {
4242
} `toml:"frontend"`
4343

4444
System *SystemConfig `toml:"system"`
45+
46+
// ProvenanceEnvDir is the directory where extra config is loaded
47+
// that is added to the provenance of builds. Defaults to /etc/buildkit/provenance.d/ ,
48+
ProvenanceEnvDir string `toml:"provenanceEnvDir"`
4549
}
4650

4751
type SystemConfig struct {

cmd/buildkitd/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,11 @@ func newController(ctx context.Context, c *cli.Context, cfg *config.Config) (*co
860860
cfg.Entitlements = append(cfg.Entitlements, "device")
861861
}
862862

863+
provenanceEnv, err := loadProvenanceEnv(cfg.ProvenanceEnvDir)
864+
if err != nil {
865+
return nil, err
866+
}
867+
863868
return control.NewController(control.Opt{
864869
SessionManager: sessionManager,
865870
WorkerController: wc,
@@ -876,6 +881,7 @@ func newController(ctx context.Context, c *cli.Context, cfg *config.Config) (*co
876881
HistoryConfig: cfg.History,
877882
GarbageCollect: w.GarbageCollect,
878883
GracefulStop: ctx.Done(),
884+
ProvenanceEnv: provenanceEnv,
879885
})
880886
}
881887

cmd/buildkitd/util.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package main
22

33
import (
4+
"encoding/json"
5+
"os"
6+
"path/filepath"
47
"strconv"
58
"strings"
69

710
"github.com/moby/buildkit/cmd/buildkitd/config"
11+
"github.com/moby/buildkit/util/appdefaults"
812
"github.com/moby/buildkit/util/disk"
913
"github.com/pkg/errors"
1014
)
@@ -66,3 +70,33 @@ func stringToGCConfig(in string) (config.GCConfig, error) {
6670
cfg.GCMaxUsedSpace = config.DiskSpace{Bytes: max * 1e6}
6771
return cfg, nil
6872
}
73+
74+
func loadProvenanceEnv(dir string) (map[string]any, error) {
75+
if dir == "" {
76+
dir = filepath.Join(appdefaults.ConfigDir, "provenance.d")
77+
}
78+
entries, err := os.ReadDir(dir)
79+
if err != nil {
80+
if os.IsNotExist(err) {
81+
return nil, nil
82+
}
83+
return nil, err
84+
}
85+
env := make(map[string]any)
86+
for _, entry := range entries {
87+
if entry.IsDir() {
88+
continue
89+
}
90+
if !strings.HasSuffix(entry.Name(), ".json") {
91+
continue
92+
}
93+
data, err := os.ReadFile(filepath.Join(dir, entry.Name()))
94+
if err != nil {
95+
return nil, err
96+
}
97+
if err := json.Unmarshal(data, &env); err != nil {
98+
return nil, errors.Wrapf(err, "failed to parse %s", entry.Name())
99+
}
100+
}
101+
return env, nil
102+
}

control/control.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type Opt struct {
7474
HistoryConfig *config.HistoryConfig
7575
GarbageCollect func(context.Context) error
7676
GracefulStop <-chan struct{}
77+
ProvenanceEnv map[string]any
7778
}
7879

7980
type Controller struct { // TODO: ControlService
@@ -114,6 +115,7 @@ func NewController(opt Opt) (*Controller, error) {
114115
SessionManager: opt.SessionManager,
115116
Entitlements: opt.Entitlements,
116117
HistoryQueue: hq,
118+
ProvenanceEnv: opt.ProvenanceEnv,
117119
})
118120
if err != nil {
119121
return nil, errors.Wrap(err, "failed to create solver")
@@ -524,7 +526,7 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
524526
params[k] = v
525527
}
526528
}
527-
procs = append(procs, proc.ProvenanceProcessor(slsaVersion, params))
529+
procs = append(procs, proc.ProvenanceProcessor(slsaVersion, params, c.opt.ProvenanceEnv))
528530
}
529531

530532
resp, err := c.solver.Solve(ctx, req.Ref, req.Session, frontend.SolveRequest{

frontend/dockerfile/dockerfile_provenance_test.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ import (
4444
)
4545

4646
var provenanceTests = integration.TestFuncs(
47-
testProvenanceAttestation,
4847
testGitProvenanceAttestationSHA1,
4948
testGitProvenanceAttestationSHA256,
5049
testMultiPlatformProvenance,
@@ -180,6 +179,11 @@ RUN echo ok> /foo
180179
_, isClient := f.(*clientFrontend)
181180
_, isGateway := f.(*gatewayFrontend)
182181

182+
expCustom := provenancetypes.ProvenanceCustomEnv{
183+
"foo": "bar",
184+
"numbers": []any{1.0, 2.0, 3.0},
185+
}
186+
183187
if slsaVersion == "v1" {
184188
type stmtT struct {
185189
Predicate provenancetypes.ProvenancePredicateSLSA1 `json:"predicate"`
@@ -193,6 +197,8 @@ RUN echo ok> /foo
193197

194198
require.Equal(t, "", pred.BuildDefinition.ExternalParameters.ConfigSource.URI)
195199

200+
require.Equal(t, expCustom, pred.BuildDefinition.InternalParameters.ProvenanceCustomEnv)
201+
196202
args := pred.BuildDefinition.ExternalParameters.Request.Args
197203
if isClient {
198204
require.Equal(t, "", pred.BuildDefinition.ExternalParameters.Request.Frontend)
@@ -294,6 +300,8 @@ RUN echo ok> /foo
294300

295301
require.Equal(t, "", pred.Invocation.ConfigSource.URI)
296302

303+
require.Equal(t, expCustom, pred.Invocation.Environment.ProvenanceCustomEnv)
304+
297305
args := pred.Invocation.Parameters.Args
298306
if isClient {
299307
require.Equal(t, "", pred.Invocation.Parameters.Frontend)
@@ -2007,3 +2015,51 @@ COPY --from=base /out /
20072015
require.NoError(t, json.Unmarshal(dt, &pred))
20082016
}
20092017
}
2018+
2019+
type provenanceEnvSimple struct{}
2020+
2021+
func (*provenanceEnvSimple) UpdateConfigFile(in string) (string, func() error) {
2022+
dir, err := os.MkdirTemp("", "provenanceenv")
2023+
if err != nil {
2024+
panic(err)
2025+
}
2026+
dt, err := json.Marshal(map[string]any{
2027+
"foo": "bar",
2028+
})
2029+
if err != nil {
2030+
panic(err)
2031+
}
2032+
if err := os.WriteFile(filepath.Join(dir, "foo.json"), dt, 0600); err != nil {
2033+
panic(err)
2034+
}
2035+
dt, err = json.Marshal(map[string]any{
2036+
"numbers": []int{1, 2, 3},
2037+
})
2038+
if err != nil {
2039+
panic(err)
2040+
}
2041+
if err := os.WriteFile(filepath.Join(dir, "numbers.json"), dt, 0600); err != nil {
2042+
panic(err)
2043+
}
2044+
2045+
// make all paths readable for the rootless user
2046+
if err := os.Chmod(dir, 0755); err != nil {
2047+
panic(err)
2048+
}
2049+
if err := os.Chmod(filepath.Join(dir, "foo.json"), 0644); err != nil {
2050+
panic(err)
2051+
}
2052+
if err := os.Chmod(filepath.Join(dir, "numbers.json"), 0644); err != nil {
2053+
panic(err)
2054+
}
2055+
2056+
in = in + fmt.Sprintf("\n\nprovenanceEnvDir = %q\n", dir)
2057+
2058+
return in, func() error {
2059+
return os.RemoveAll(dir)
2060+
}
2061+
}
2062+
2063+
var (
2064+
provenanceEnvSimpleConfig integration.ConfigUpdater = &provenanceEnvSimple{}
2065+
)

frontend/dockerfile/dockerfile_test.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,11 @@ func TestIntegration(t *testing.T) {
298298
"granted": networkHostGranted,
299299
"denied": networkHostDenied,
300300
}))...)
301+
302+
integration.Run(t, integration.TestFuncs(testProvenanceAttestation), append(opts,
303+
integration.WithMatrix("env", map[string]any{
304+
"simple": provenanceEnvSimpleConfig,
305+
}))...)
301306
}
302307

303308
func testEmptyStringArgInEnv(t *testing.T, sb integration.Sandbox) {
@@ -10386,14 +10391,14 @@ func (nopWriteCloser) Close() error { return nil }
1038610391

1038710392
type secModeSandbox struct{}
1038810393

10389-
func (*secModeSandbox) UpdateConfigFile(in string) string {
10390-
return in
10394+
func (*secModeSandbox) UpdateConfigFile(in string) (string, func() error) {
10395+
return in, nil
1039110396
}
1039210397

1039310398
type secModeInsecure struct{}
1039410399

10395-
func (*secModeInsecure) UpdateConfigFile(in string) string {
10396-
return in + "\n\ninsecure-entitlements = [\"security.insecure\"]\n"
10400+
func (*secModeInsecure) UpdateConfigFile(in string) (string, func() error) {
10401+
return in + "\n\ninsecure-entitlements = [\"security.insecure\"]\n", nil
1039710402
}
1039810403

1039910404
var (
@@ -10403,14 +10408,14 @@ var (
1040310408

1040410409
type networkModeHost struct{}
1040510410

10406-
func (*networkModeHost) UpdateConfigFile(in string) string {
10407-
return in + "\n\ninsecure-entitlements = [\"network.host\"]\n"
10411+
func (*networkModeHost) UpdateConfigFile(in string) (string, func() error) {
10412+
return in + "\n\ninsecure-entitlements = [\"network.host\"]\n", nil
1040810413
}
1040910414

1041010415
type networkModeSandbox struct{}
1041110416

10412-
func (*networkModeSandbox) UpdateConfigFile(in string) string {
10413-
return in
10417+
func (*networkModeSandbox) UpdateConfigFile(in string) (string, func() error) {
10418+
return in, nil
1041410419
}
1041510420

1041610421
var (

solver/jobs_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,16 @@ func testParallelism(t *testing.T, sb integration.Sandbox) {
9090

9191
type parallelismSetterSingle struct{}
9292

93-
func (*parallelismSetterSingle) UpdateConfigFile(in string) string {
94-
return in + "\n\n[worker.oci]\n max-parallelism = 1\n\n[worker.containerd]\n max-parallelism = 1\n"
93+
func (*parallelismSetterSingle) UpdateConfigFile(in string) (string, func() error) {
94+
return in + "\n\n[worker.oci]\n max-parallelism = 1\n\n[worker.containerd]\n max-parallelism = 1\n", nil
9595
}
9696

9797
var maxParallelismSingle integration.ConfigUpdater = &parallelismSetterSingle{}
9898

9999
type parallelismSetterUnlimited struct{}
100100

101-
func (*parallelismSetterUnlimited) UpdateConfigFile(in string) string {
102-
return in
101+
func (*parallelismSetterUnlimited) UpdateConfigFile(in string) (string, func() error) {
102+
return in, nil
103103
}
104104

105105
var maxParallelismUnlimited integration.ConfigUpdater = &parallelismSetterUnlimited{}

solver/llbsolver/proc/provenance.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"github.com/pkg/errors"
1717
)
1818

19-
func ProvenanceProcessor(slsaVersion provenancetypes.ProvenanceSLSA, attrs map[string]string) llbsolver.Processor {
19+
func ProvenanceProcessor(slsaVersion provenancetypes.ProvenanceSLSA, attrs map[string]string, customEnv map[string]any) llbsolver.Processor {
2020
return func(ctx context.Context, res *llbsolver.Result, s *llbsolver.Solver, j *solver.Job, usage *resources.SysSampler) (*llbsolver.Result, error) {
2121
span, ctx := tracing.StartSpan(ctx, "create provenance attestation")
2222
defer span.End()
@@ -46,7 +46,7 @@ func ProvenanceProcessor(slsaVersion provenancetypes.ProvenanceSLSA, attrs map[s
4646
return nil, errors.Errorf("could not find ref %s", p.ID)
4747
}
4848

49-
pc, err := llbsolver.NewProvenanceCreator(ctx, slsaVersion, cp, ref, attrs, j, usage)
49+
pc, err := llbsolver.NewProvenanceCreator(ctx, slsaVersion, cp, ref, attrs, j, usage, customEnv)
5050
if err != nil {
5151
return nil, err
5252
}

solver/llbsolver/provenance.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ type ProvenanceCreator struct {
339339
addLayers func(context.Context) error
340340
}
341341

342-
func NewProvenanceCreator(ctx context.Context, slsaVersion provenancetypes.ProvenanceSLSA, cp *provenance.Capture, res solver.ResultProxy, attrs map[string]string, j *solver.Job, usage *resources.SysSampler) (*ProvenanceCreator, error) {
342+
func NewProvenanceCreator(ctx context.Context, slsaVersion provenancetypes.ProvenanceSLSA, cp *provenance.Capture, res solver.ResultProxy, attrs map[string]string, j *solver.Job, usage *resources.SysSampler, customEnv map[string]any) (*ProvenanceCreator, error) {
343343
var reproducible bool
344344
if v, ok := attrs["reproducible"]; ok {
345345
b, err := strconv.ParseBool(v)
@@ -451,6 +451,8 @@ func NewProvenanceCreator(ctx context.Context, slsaVersion provenancetypes.Prove
451451
return nil, errors.Errorf("invalid mode %q", mode)
452452
}
453453

454+
pr.Invocation.Environment.ProvenanceCustomEnv = customEnv
455+
454456
pc := &ProvenanceCreator{
455457
pr: pr,
456458
slsaVersion: slsaVersion,

0 commit comments

Comments
 (0)