From 30704ba80bd737352c59d72daf90874afc60b61d Mon Sep 17 00:00:00 2001 From: Aidan Delaney Date: Fri, 19 Jul 2024 07:08:51 +0100 Subject: [PATCH 1/2] Trust buildpacks in addition to those on the builder Trust buildpacks provided when `--buildpack` is provided on the command line. Signed-off-by: Aidan Delaney --- internal/commands/build.go | 73 ++++++++++++++++++++------------------ pkg/client/build.go | 29 +++++++++------ pkg/client/build_test.go | 22 ++++++++++++ 3 files changed, 79 insertions(+), 45 deletions(-) diff --git a/internal/commands/build.go b/internal/commands/build.go index 2118a0444..621c55c0f 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -24,39 +24,40 @@ import ( ) type BuildFlags struct { - Publish bool - ClearCache bool - TrustBuilder bool - Interactive bool - Sparse bool - DockerHost string - CacheImage string - Cache cache.CacheOpts - AppPath string - Builder string - Registry string - RunImage string - Platform string - Policy string - Network string - DescriptorPath string - DefaultProcessType string - LifecycleImage string - Env []string - EnvFiles []string - Buildpacks []string - Extensions []string - Volumes []string - AdditionalTags []string - Workspace string - GID int - UID int - PreviousImage string - SBOMDestinationDir string - ReportDestinationDir string - DateTime string - PreBuildpacks []string - PostBuildpacks []string + Publish bool + ClearCache bool + TrustBuilder bool + TrustAdditionalBuildpacks bool + Interactive bool + Sparse bool + DockerHost string + CacheImage string + Cache cache.CacheOpts + AppPath string + Builder string + Registry string + RunImage string + Platform string + Policy string + Network string + DescriptorPath string + DefaultProcessType string + LifecycleImage string + Env []string + EnvFiles []string + Buildpacks []string + Extensions []string + Volumes []string + AdditionalTags []string + Workspace string + GID int + UID int + PreviousImage string + SBOMDestinationDir string + ReportDestinationDir string + DateTime string + PreBuildpacks []string + PostBuildpacks []string } // Build an image from source code @@ -180,8 +181,9 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob TrustBuilder: func(string) bool { return trustBuilder }, - Buildpacks: buildpacks, - Extensions: extensions, + TrustAdditionalBuildpacks: flags.TrustAdditionalBuildpacks, + Buildpacks: buildpacks, + Extensions: extensions, ContainerConfig: client.ContainerConfig{ Network: flags.Network, Volumes: flags.Volumes, @@ -273,6 +275,7 @@ This option may set DOCKER_HOST environment variable for the build container if cmd.Flags().StringVar(&buildFlags.RunImage, "run-image", "", "Run image (defaults to default stack's run image)") cmd.Flags().StringSliceVarP(&buildFlags.AdditionalTags, "tag", "t", nil, "Additional tags to push the output image to.\nTags should be in the format 'image:tag' or 'repository/image:tag'."+stringSliceHelp("tag")) cmd.Flags().BoolVar(&buildFlags.TrustBuilder, "trust-builder", false, "Trust the provided builder.\nAll lifecycle phases will be run in a single container.\nFor more on trusted builders, and when to trust or untrust a builder, check out our docs here: https://buildpacks.io/docs/tools/pack/concepts/trusted_builders") + cmd.Flags().BoolVar(&buildFlags.TrustAdditionalBuildpacks, "trust-additional-buildpacks", false, "Trust buildpacks that are provided in addition to the buildpacks on the builder") cmd.Flags().StringArrayVar(&buildFlags.Volumes, "volume", nil, "Mount host volume into the build container, in the form ':[:]'.\n- 'host path': Name of the volume or absolute directory path to mount.\n- 'target path': The path where the file or directory is available in the container.\n- 'options' (default \"ro\"): An optional comma separated list of mount options.\n - \"ro\", volume contents are read-only.\n - \"rw\", volume contents are readable and writeable.\n - \"volume-opt==\", can be specified more than once, takes a key-value pair consisting of the option name and its value."+stringArrayHelp("volume")) cmd.Flags().StringVar(&buildFlags.Workspace, "workspace", "", "Location at which to mount the app dir in the build image") cmd.Flags().IntVar(&buildFlags.GID, "gid", 0, `Override GID of user's group in the stack's build and run images. The provided value must be a positive number`) diff --git a/pkg/client/build.go b/pkg/client/build.go index 73b1f455b..c73b55537 100644 --- a/pkg/client/build.go +++ b/pkg/client/build.go @@ -203,9 +203,17 @@ type BuildOptions struct { // TrustBuilder when true optimizes builds by running // all lifecycle phases in a single container. // This places registry credentials on the builder's build image. - // Only trust builders from reputable sources. + // Only trust builders from reputable sources. The optimized + // build happens only when both builder and buildpacks are + // trusted TrustBuilder IsTrustedBuilder + // TrustAdditionalBuildpacks when true optimizes builds by running + // all lifecycle phases in a single container. The optimized + // build happens only when both builder and buildpacks are + // trusted + TrustAdditionalBuildpacks bool + // Directory to output any SBOM artifacts SBOMDestinationDir string @@ -430,16 +438,17 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { // Get the platform API version to use lifecycleVersion := bldr.LifecycleDescriptor().Info.Version useCreator := supportsCreator(lifecycleVersion) && opts.TrustBuilder(opts.Builder) - hasAdditionalModules := func() bool { - if len(fetchedBPs) == 0 && len(fetchedExs) == 0 { - return false - } - if len(fetchedBPs) == nInlineBPs && len(fetchedExs) == 0 { - return false - } - return true + hasAdditionalBuildpacks := func() bool { + return len(fetchedBPs) != nInlineBPs }() - if useCreator && hasAdditionalModules { + hasExtensions := func() bool { + return len(fetchedExs) != 0 + }() + if hasExtensions { + c.logger.Warnf("Builder is trusted but additional modules were added; using the untrusted (5 phases) build flow") + useCreator = false + } + if hasAdditionalBuildpacks && !opts.TrustAdditionalBuildpacks { c.logger.Warnf("Builder is trusted but additional modules were added; using the untrusted (5 phases) build flow") useCreator = false } diff --git a/pkg/client/build_test.go b/pkg/client/build_test.go index 9b2dcd798..4d41092e1 100644 --- a/pkg/client/build_test.go +++ b/pkg/client/build_test.go @@ -2091,6 +2091,28 @@ api = "0.2" }) when("additional buildpacks were added", func() { + it("uses creator when additional buildpacks are provided and TrustAdditionalBuildpacks is set", func() { + additionalBP := ifakes.CreateBuildpackTar(t, tmpDir, dist.BuildpackDescriptor{ + WithAPI: api.MustParse("0.3"), + WithInfo: dist.ModuleInfo{ + ID: "buildpack.add.1.id", + Version: "buildpack.add.1.version", + }, + WithStacks: []dist.Stack{{ID: defaultBuilderStackID}}, + WithOrder: nil, + }) + + h.AssertNil(t, subject.Build(context.TODO(), BuildOptions{ + Image: "some/app", + Builder: defaultBuilderName, + Publish: true, + TrustBuilder: func(string) bool { return true }, + TrustAdditionalBuildpacks: true, + Buildpacks: []string{additionalBP}, + })) + h.AssertEq(t, fakeLifecycle.Opts.UseCreator, true) + }) + it("uses the 5 phases with the lifecycle image", func() { additionalBP := ifakes.CreateBuildpackTar(t, tmpDir, dist.BuildpackDescriptor{ WithAPI: api.MustParse("0.3"), From b195e95e2fad6a30d9683140b432c36f7a982e4d Mon Sep 17 00:00:00 2001 From: Aidan Delaney Date: Mon, 22 Jul 2024 05:54:03 +0100 Subject: [PATCH 2/2] Add --trust-extra-buildpacks option Use the term "extra buildpacks" instead of "additional buildpacks" Signed-off-by: Aidan Delaney --- internal/commands/build.go | 76 +++++++++++++++++++------------------- pkg/client/build.go | 6 +-- pkg/client/build_test.go | 14 +++---- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/internal/commands/build.go b/internal/commands/build.go index 621c55c0f..c80123d77 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -24,40 +24,40 @@ import ( ) type BuildFlags struct { - Publish bool - ClearCache bool - TrustBuilder bool - TrustAdditionalBuildpacks bool - Interactive bool - Sparse bool - DockerHost string - CacheImage string - Cache cache.CacheOpts - AppPath string - Builder string - Registry string - RunImage string - Platform string - Policy string - Network string - DescriptorPath string - DefaultProcessType string - LifecycleImage string - Env []string - EnvFiles []string - Buildpacks []string - Extensions []string - Volumes []string - AdditionalTags []string - Workspace string - GID int - UID int - PreviousImage string - SBOMDestinationDir string - ReportDestinationDir string - DateTime string - PreBuildpacks []string - PostBuildpacks []string + Publish bool + ClearCache bool + TrustBuilder bool + TrustExtraBuildpacks bool + Interactive bool + Sparse bool + DockerHost string + CacheImage string + Cache cache.CacheOpts + AppPath string + Builder string + Registry string + RunImage string + Platform string + Policy string + Network string + DescriptorPath string + DefaultProcessType string + LifecycleImage string + Env []string + EnvFiles []string + Buildpacks []string + Extensions []string + Volumes []string + AdditionalTags []string + Workspace string + GID int + UID int + PreviousImage string + SBOMDestinationDir string + ReportDestinationDir string + DateTime string + PreBuildpacks []string + PostBuildpacks []string } // Build an image from source code @@ -181,9 +181,9 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob TrustBuilder: func(string) bool { return trustBuilder }, - TrustAdditionalBuildpacks: flags.TrustAdditionalBuildpacks, - Buildpacks: buildpacks, - Extensions: extensions, + TrustExtraBuildpacks: flags.TrustExtraBuildpacks, + Buildpacks: buildpacks, + Extensions: extensions, ContainerConfig: client.ContainerConfig{ Network: flags.Network, Volumes: flags.Volumes, @@ -275,7 +275,7 @@ This option may set DOCKER_HOST environment variable for the build container if cmd.Flags().StringVar(&buildFlags.RunImage, "run-image", "", "Run image (defaults to default stack's run image)") cmd.Flags().StringSliceVarP(&buildFlags.AdditionalTags, "tag", "t", nil, "Additional tags to push the output image to.\nTags should be in the format 'image:tag' or 'repository/image:tag'."+stringSliceHelp("tag")) cmd.Flags().BoolVar(&buildFlags.TrustBuilder, "trust-builder", false, "Trust the provided builder.\nAll lifecycle phases will be run in a single container.\nFor more on trusted builders, and when to trust or untrust a builder, check out our docs here: https://buildpacks.io/docs/tools/pack/concepts/trusted_builders") - cmd.Flags().BoolVar(&buildFlags.TrustAdditionalBuildpacks, "trust-additional-buildpacks", false, "Trust buildpacks that are provided in addition to the buildpacks on the builder") + cmd.Flags().BoolVar(&buildFlags.TrustExtraBuildpacks, "trust-extra-buildpacks", false, "Trust buildpacks that are provided in addition to the buildpacks on the builder") cmd.Flags().StringArrayVar(&buildFlags.Volumes, "volume", nil, "Mount host volume into the build container, in the form ':[:]'.\n- 'host path': Name of the volume or absolute directory path to mount.\n- 'target path': The path where the file or directory is available in the container.\n- 'options' (default \"ro\"): An optional comma separated list of mount options.\n - \"ro\", volume contents are read-only.\n - \"rw\", volume contents are readable and writeable.\n - \"volume-opt==\", can be specified more than once, takes a key-value pair consisting of the option name and its value."+stringArrayHelp("volume")) cmd.Flags().StringVar(&buildFlags.Workspace, "workspace", "", "Location at which to mount the app dir in the build image") cmd.Flags().IntVar(&buildFlags.GID, "gid", 0, `Override GID of user's group in the stack's build and run images. The provided value must be a positive number`) diff --git a/pkg/client/build.go b/pkg/client/build.go index c73b55537..901c0865a 100644 --- a/pkg/client/build.go +++ b/pkg/client/build.go @@ -208,11 +208,11 @@ type BuildOptions struct { // trusted TrustBuilder IsTrustedBuilder - // TrustAdditionalBuildpacks when true optimizes builds by running + // TrustExtraBuildpacks when true optimizes builds by running // all lifecycle phases in a single container. The optimized // build happens only when both builder and buildpacks are // trusted - TrustAdditionalBuildpacks bool + TrustExtraBuildpacks bool // Directory to output any SBOM artifacts SBOMDestinationDir string @@ -448,7 +448,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { c.logger.Warnf("Builder is trusted but additional modules were added; using the untrusted (5 phases) build flow") useCreator = false } - if hasAdditionalBuildpacks && !opts.TrustAdditionalBuildpacks { + if hasAdditionalBuildpacks && !opts.TrustExtraBuildpacks { c.logger.Warnf("Builder is trusted but additional modules were added; using the untrusted (5 phases) build flow") useCreator = false } diff --git a/pkg/client/build_test.go b/pkg/client/build_test.go index 4d41092e1..b645421f8 100644 --- a/pkg/client/build_test.go +++ b/pkg/client/build_test.go @@ -2091,7 +2091,7 @@ api = "0.2" }) when("additional buildpacks were added", func() { - it("uses creator when additional buildpacks are provided and TrustAdditionalBuildpacks is set", func() { + it("uses creator when additional buildpacks are provided and TrustExtraBuildpacks is set", func() { additionalBP := ifakes.CreateBuildpackTar(t, tmpDir, dist.BuildpackDescriptor{ WithAPI: api.MustParse("0.3"), WithInfo: dist.ModuleInfo{ @@ -2103,12 +2103,12 @@ api = "0.2" }) h.AssertNil(t, subject.Build(context.TODO(), BuildOptions{ - Image: "some/app", - Builder: defaultBuilderName, - Publish: true, - TrustBuilder: func(string) bool { return true }, - TrustAdditionalBuildpacks: true, - Buildpacks: []string{additionalBP}, + Image: "some/app", + Builder: defaultBuilderName, + Publish: true, + TrustBuilder: func(string) bool { return true }, + TrustExtraBuildpacks: true, + Buildpacks: []string{additionalBP}, })) h.AssertEq(t, fakeLifecycle.Opts.UseCreator, true) })