From 6dc505186185938009b9d22d3c5274aa2fcd1747 Mon Sep 17 00:00:00 2001 From: Johannes Dillmann Date: Fri, 8 Nov 2024 13:30:45 +0100 Subject: [PATCH] Allow trusted builders by repo and tag --- .../{known_builder.go => trusted_builder.go} | 33 +++++- internal/builder/trusted_builder_test.go | 102 ++++++++++++++++++ internal/commands/build.go | 8 +- internal/commands/builder_inspect.go | 9 +- internal/commands/commands.go | 12 --- internal/commands/config_trusted_builder.go | 6 +- 6 files changed, 153 insertions(+), 17 deletions(-) rename internal/builder/{known_builder.go => trusted_builder.go} (72%) create mode 100644 internal/builder/trusted_builder_test.go diff --git a/internal/builder/known_builder.go b/internal/builder/trusted_builder.go similarity index 72% rename from internal/builder/known_builder.go rename to internal/builder/trusted_builder.go index 4c164ac00e..8a1fb47cd6 100644 --- a/internal/builder/known_builder.go +++ b/internal/builder/trusted_builder.go @@ -1,5 +1,11 @@ package builder +import ( + "github.com/google/go-containerregistry/pkg/name" + + "github.com/buildpacks/pack/internal/config" +) + type KnownBuilder struct { Vendor string Image string @@ -67,11 +73,34 @@ var KnownBuilders = []KnownBuilder{ }, } -var IsKnownTrustedBuilder = func(b string) bool { +func IsKnownTrustedBuilder(builderName string) bool { for _, knownBuilder := range KnownBuilders { - if b == knownBuilder.Image && knownBuilder.Trusted { + if builderName == knownBuilder.Image && knownBuilder.Trusted { return true } } return false } + +func IsTrustedBuilder(cfg config.Config, builderName string) (bool, error) { + builderReference, err := name.ParseReference(builderName, name.WithDefaultTag("")) + if err != nil { + return false, err + } + for _, trustedBuilder := range cfg.TrustedBuilders { + trustedBuilderReference, err := name.ParseReference(trustedBuilder.Name, name.WithDefaultTag("")) + if err != nil { + return false, err + } + if trustedBuilderReference.Identifier() != "" { + if builderReference.Name() == trustedBuilderReference.Name() { + return true, nil + } + } else { + if builderReference.Context().RepositoryStr() == trustedBuilderReference.Context().RepositoryStr() { + return true, nil + } + } + } + return false, nil +} diff --git a/internal/builder/trusted_builder_test.go b/internal/builder/trusted_builder_test.go new file mode 100644 index 0000000000..90e7599cd8 --- /dev/null +++ b/internal/builder/trusted_builder_test.go @@ -0,0 +1,102 @@ +package builder_test + +import ( + "testing" + + "github.com/heroku/color" + "github.com/sclevine/spec" + "github.com/sclevine/spec/report" + + bldr "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/config" + + h "github.com/buildpacks/pack/testhelpers" +) + +func TestTrustedBuilder(t *testing.T) { + color.Disable(true) + defer color.Disable(false) + spec.Run(t, "Trusted Builder", trustedBuilder, spec.Parallel(), spec.Report(report.Terminal{})) +} + +func trustedBuilder(t *testing.T, when spec.G, it spec.S) { + when("IsKnownTrustedBuilder", func() { + it("matches exactly", func() { + h.AssertTrue(t, bldr.IsKnownTrustedBuilder("paketobuildpacks/builder-jammy-base")) + h.AssertFalse(t, bldr.IsKnownTrustedBuilder("paketobuildpacks/builder-jammy-base:latest")) + h.AssertFalse(t, bldr.IsKnownTrustedBuilder("paketobuildpacks/builder-jammy-base:1.2.3")) + h.AssertFalse(t, bldr.IsKnownTrustedBuilder("my/private/builder")) + }) + }) + + when("IsTrustedBuilder", func() { + it("trust image without tag", func() { + cfg := config.Config{ + TrustedBuilders: []config.TrustedBuilder{ + { + Name: "my/trusted/builder-jammy", + }, + }, + } + + trustedBuilders := []string{ + "my/trusted/builder-jammy", + "my/trusted/builder-jammy:latest", + "my/trusted/builder-jammy:1.2.3", + } + + untrustedBuilders := []string{ + "my/private/builder", // random builder + "my/trusted/builder-jammy-base", // shared prefix + } + + for _, builder := range trustedBuilders { + isTrusted, err := bldr.IsTrustedBuilder(cfg, builder) + h.AssertNil(t, err) + h.AssertTrue(t, isTrusted) + } + + for _, builder := range untrustedBuilders { + isTrusted, err := bldr.IsTrustedBuilder(cfg, builder) + h.AssertNil(t, err) + h.AssertFalse(t, isTrusted) + } + }) + it("trust image with tag", func() { + cfg := config.Config{ + TrustedBuilders: []config.TrustedBuilder{ + { + Name: "my/trusted/builder-jammy:1.2.3", + }, + { + Name: "my/trusted/builder-jammy:latest", + }, + }, + } + + trustedBuilders := []string{ + "my/trusted/builder-jammy:1.2.3", + "my/trusted/builder-jammy:latest", + } + + untrustedBuilders := []string{ + "my/private/builder", + "my/trusted/builder-jammy", + "my/trusted/builder-jammy:2.0.0", + "my/trusted/builder-jammy-base", + } + + for _, builder := range trustedBuilders { + isTrusted, err := bldr.IsTrustedBuilder(cfg, builder) + h.AssertNil(t, err) + h.AssertTrue(t, isTrusted) + } + + for _, builder := range untrustedBuilders { + isTrusted, err := bldr.IsTrustedBuilder(cfg, builder) + h.AssertNil(t, err) + h.AssertFalse(t, isTrusted) + } + }) + }) +} diff --git a/internal/commands/build.go b/internal/commands/build.go index 1d34c2ccca..144bc17651 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -12,6 +12,8 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" + bldr "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/config" "github.com/buildpacks/pack/internal/style" "github.com/buildpacks/pack/pkg/cache" @@ -110,7 +112,11 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob return err } - trustBuilder := isTrustedBuilder(cfg, builder) || flags.TrustBuilder + isTrusted, err := bldr.IsTrustedBuilder(cfg, builder) + if err != nil { + return err + } + trustBuilder := isTrusted || bldr.IsKnownTrustedBuilder(builder) || flags.TrustBuilder if trustBuilder { logger.Debugf("Builder %s is trusted", style.Symbol(builder)) if flags.LifecycleImage != "" { diff --git a/internal/commands/builder_inspect.go b/internal/commands/builder_inspect.go index e86f91defa..36fa93be93 100644 --- a/internal/commands/builder_inspect.go +++ b/internal/commands/builder_inspect.go @@ -8,6 +8,8 @@ import ( "github.com/buildpacks/pack/internal/config" "github.com/buildpacks/pack/pkg/client" "github.com/buildpacks/pack/pkg/logging" + + bldr "github.com/buildpacks/pack/internal/builder" ) type BuilderInspector interface { @@ -61,10 +63,15 @@ func inspectBuilder( inspector BuilderInspector, writerFactory writer.BuilderWriterFactory, ) error { + isTrusted, err := bldr.IsTrustedBuilder(cfg, imageName) + if err != nil { + return err + } + builderInfo := writer.SharedBuilderInfo{ Name: imageName, IsDefault: imageName == cfg.DefaultBuilder, - Trusted: isTrustedBuilder(cfg, imageName), + Trusted: isTrusted, } localInfo, localErr := inspector.InspectBuilder(imageName, true, client.WithDetectionOrderDepth(flags.Depth)) diff --git a/internal/commands/commands.go b/internal/commands/commands.go index f322b1a431..8a3a37d5a2 100644 --- a/internal/commands/commands.go +++ b/internal/commands/commands.go @@ -7,8 +7,6 @@ import ( "os/signal" "syscall" - "github.com/buildpacks/pack/internal/builder" - "github.com/google/go-containerregistry/pkg/v1/types" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -107,16 +105,6 @@ func getMirrors(config config.Config) map[string][]string { return mirrors } -func isTrustedBuilder(cfg config.Config, builderName string) bool { - for _, trustedBuilder := range cfg.TrustedBuilders { - if builderName == trustedBuilder.Name { - return true - } - } - - return builder.IsKnownTrustedBuilder(builderName) -} - func deprecationWarning(logger logging.Logger, oldCmd, replacementCmd string) { logger.Warnf("Command %s has been deprecated, please use %s instead", style.Symbol("pack "+oldCmd), style.Symbol("pack "+replacementCmd)) } diff --git a/internal/commands/config_trusted_builder.go b/internal/commands/config_trusted_builder.go index 4ccc469249..36bcfb6018 100644 --- a/internal/commands/config_trusted_builder.go +++ b/internal/commands/config_trusted_builder.go @@ -51,7 +51,11 @@ func addTrustedBuilder(args []string, logger logging.Logger, cfg config.Config, imageName := args[0] builderToTrust := config.TrustedBuilder{Name: imageName} - if isTrustedBuilder(cfg, imageName) { + isTrusted, err := bldr.IsTrustedBuilder(cfg, imageName) + if err != nil { + return err + } + if isTrusted || bldr.IsKnownTrustedBuilder(imageName) { logger.Infof("Builder %s is already trusted", style.Symbol(imageName)) return nil }