From 95ee45715bd2d5a7e60cd58093f2a87a88a4564d Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 12 Jul 2023 15:28:00 -0700 Subject: [PATCH] [allow-insecure] Allow insecure packages with --allow-insecure flag (#1265) ## Summary This allows installing insecure packages using the `--allow-insecure` flag: `devbox add nodejs@16 --allow-insecure` This saves the allow insecure state to lock file. If user tries to do add/shell/run/install and there are insecure pacakges that are not in marked in lock file, they will see an error indicating they should use flag. I used flag (instead of prompt) to limit the size of this already massive PR. TODO (in follow up): * When installing an insecure package, ask the user if they want to allow it, update the devbox.json, and install it. ## How was it tested? ```bash devbox add nodejs@16 devbox add nodejs@16 --allow-insecure devbox run run_test # edited lockfile to remove allow_insecure devbox run run_test # error devbox install # error devbox shell # error ``` See examples/insecure --- devbox.json | 2 +- examples/insecure/devbox.json | 15 ++++ examples/insecure/devbox.lock | 12 ++++ internal/boxcli/add.go | 12 +++- internal/devpkg/package.go | 20 ++++++ internal/impl/devbox.go | 31 ++++---- internal/impl/devopt/devboxopts.go | 9 +-- internal/impl/packages.go | 41 ++++++++--- internal/lock/lockfile.go | 9 +++ internal/lock/package.go | 8 +++ internal/nix/command.go | 9 ++- internal/nix/eval.go | 56 +++++++++++++++ internal/nix/nix.go | 23 +++++- internal/nix/profiles.go | 15 +++- internal/shellgen/flake_input.go | 35 +++++---- internal/shellgen/flake_plan.go | 5 +- internal/shellgen/generate_test.go | 72 +++++++++++++------ internal/shellgen/testdata/flake.nix.golden | 2 + internal/shellgen/tmpl/flake.nix.tmpl | 9 ++- .../tmpl/flake_remove_nixpkgs.nix.tmpl | 9 ++- 20 files changed, 316 insertions(+), 78 deletions(-) create mode 100644 examples/insecure/devbox.json create mode 100644 examples/insecure/devbox.lock create mode 100644 internal/nix/eval.go diff --git a/devbox.json b/devbox.json index ba04e5eeaf4..39905cd3f00 100644 --- a/devbox.json +++ b/devbox.json @@ -22,4 +22,4 @@ "nixpkgs": { "commit": "3364b5b117f65fe1ce65a3cdd5612a078a3b31e3" } -} \ No newline at end of file +} diff --git a/examples/insecure/devbox.json b/examples/insecure/devbox.json new file mode 100644 index 00000000000..f66385ea8d6 --- /dev/null +++ b/examples/insecure/devbox.json @@ -0,0 +1,15 @@ +{ + "packages": [ + "nodejs@16" + ], + "shell": { + "init_hook": [ + "echo 'Welcome to devbox!' > /dev/null" + ], + "scripts": { + "run_test": [ + "node --version" + ] + } + } +} diff --git a/examples/insecure/devbox.lock b/examples/insecure/devbox.lock new file mode 100644 index 00000000000..117db460694 --- /dev/null +++ b/examples/insecure/devbox.lock @@ -0,0 +1,12 @@ +{ + "lockfile_version": "1", + "packages": { + "nodejs@16": { + "allow_insecure": true, + "last_modified": "2023-06-29T16:20:38Z", + "resolved": "github:NixOS/nixpkgs/3c614fbc76fc152f3e1bc4b2263da6d90adf80fb#nodejs_16", + "source": "devbox-search", + "version": "16.20.1" + } + } +} diff --git a/internal/boxcli/add.go b/internal/boxcli/add.go index 099cf662f45..f1a194b9c2a 100644 --- a/internal/boxcli/add.go +++ b/internal/boxcli/add.go @@ -18,7 +18,8 @@ import ( const toSearchForPackages = "To search for packages, use the `devbox search` command" type addCmdFlags struct { - config configFlags + config configFlags + allowInsecure bool } func addCmd() *cobra.Command { @@ -47,13 +48,18 @@ func addCmd() *cobra.Command { } flags.config.register(command) + command.Flags().BoolVar( + &flags.allowInsecure, "allow-insecure", false, + "Allow adding packages marked as insecure.") + return command } func addCmdFunc(cmd *cobra.Command, args []string, flags addCmdFlags) error { box, err := devbox.Open(&devopt.Opts{ - Dir: flags.config.path, - Writer: cmd.ErrOrStderr(), + Dir: flags.config.path, + Writer: cmd.ErrOrStderr(), + AllowInsecureAdds: flags.allowInsecure, }) if err != nil { return errors.WithStack(err) diff --git a/internal/devpkg/package.go b/internal/devpkg/package.go index 6b80bc041c3..1987fd687c0 100644 --- a/internal/devpkg/package.go +++ b/internal/devpkg/package.go @@ -542,3 +542,23 @@ func (p *Package) ContentAddressedPath() (string, error) { } return localPath, err } + +func (p *Package) AllowInsecure() bool { + return p.lockfile.Get(p.Raw).IsAllowInsecure() +} + +// StoreName returns the last section of the store path. Example: +// /nix/store/abc123-foo-1.0.0 -> foo-1.0.0 +// Warning, this is probably slowish. If you need to call this multiple times, +// consider caching the result. +func (p *Package) StoreName() (string, error) { + u, err := p.urlForInstall() + if err != nil { + return "", err + } + name, err := nix.EvalPackageName(u) + if err != nil { + return "", err + } + return name, nil +} diff --git a/internal/impl/devbox.go b/internal/impl/devbox.go index 171100aa14c..24cb9e93318 100644 --- a/internal/impl/devbox.go +++ b/internal/impl/devbox.go @@ -52,12 +52,13 @@ const ( ) type Devbox struct { - cfg *devconfig.Config - lockfile *lock.File - nix nix.Nixer - projectDir string - pluginManager *plugin.Manager - pure bool + cfg *devconfig.Config + lockfile *lock.File + nix nix.Nixer + projectDir string + pluginManager *plugin.Manager + pure bool + allowInsecureAdds bool // Possible TODO: hardcode this to stderr. Allowing the caller to specify the // writer is error prone. Since it is almost always stderr, we should default @@ -81,18 +82,24 @@ func Open(opts *devopt.Opts) (*Devbox, error) { } box := &Devbox{ - cfg: cfg, - nix: &nix.Nix{}, - projectDir: projectDir, - pluginManager: plugin.NewManager(), - writer: opts.Writer, - pure: opts.Pure, + cfg: cfg, + nix: &nix.Nix{}, + projectDir: projectDir, + pluginManager: plugin.NewManager(), + writer: opts.Writer, + pure: opts.Pure, + allowInsecureAdds: opts.AllowInsecureAdds, } lock, err := lock.GetFile(box) if err != nil { return nil, err } + // if lockfile has any allow insecure, we need to set the env var to ensure + // all nix commands work. + if opts.AllowInsecureAdds || lock.HasAllowInsecurePackages() { + nix.AllowInsecurePackages() + } box.pluginManager.ApplyOptions( plugin.WithDevbox(box), plugin.WithLockfile(lock), diff --git a/internal/impl/devopt/devboxopts.go b/internal/impl/devopt/devboxopts.go index 7fd11ec62ab..4f7a02ec444 100644 --- a/internal/impl/devopt/devboxopts.go +++ b/internal/impl/devopt/devboxopts.go @@ -5,8 +5,9 @@ import ( ) type Opts struct { - Dir string - Pure bool - IgnoreWarnings bool - Writer io.Writer + AllowInsecureAdds bool + Dir string + Pure bool + IgnoreWarnings bool + Writer io.Writer } diff --git a/internal/impl/packages.go b/internal/impl/packages.go index 4ea89e4c768..a2be067425b 100644 --- a/internal/impl/packages.go +++ b/internal/impl/packages.go @@ -40,10 +40,16 @@ func (d *Devbox) Add(ctx context.Context, pkgsNames ...string) error { // Only add packages that are not already in config. If same canonical exists, // replace it. - pkgs := []*devpkg.Package{} - for _, pkg := range devpkg.PackageFromStrings(lo.Uniq(pkgsNames), d.lockfile) { + pkgs := devpkg.PackageFromStrings(lo.Uniq(pkgsNames), d.lockfile) + + // addedPackageNames keeps track of the possibly transformed (versioned) + // names of added packages (even if they are already in config). We use this + // to know the exact name to mark as allowed insecure later on. + addedPackageNames := []string{} + for _, pkg := range pkgs { // If exact versioned package is already in the config, skip. if slices.Contains(d.cfg.Packages, pkg.Versioned()) { + addedPackageNames = append(addedPackageNames, pkg.Versioned()) continue } @@ -61,11 +67,30 @@ func (d *Devbox) Add(ctx context.Context, pkgsNames ...string) error { // if not, fallback to legacy vanilla nix. versionedPkg := devpkg.PackageFromString(pkg.Versioned(), d.lockfile) ok, err := versionedPkg.ValidateExists() + packageNameForConfig := pkg.Raw if err == nil && ok { - d.cfg.Packages = append(d.cfg.Packages, pkg.Versioned()) - } else { - // fallthrough and treat package as a legacy package. - d.cfg.Packages = append(d.cfg.Packages, pkg.Raw) + // Only use versioned if it exists in search. + packageNameForConfig = pkg.Versioned() + } + // else { + // // TODO (landau): use nix.Search to check if this package exists + // // fallthrough and treat package as a legacy package. + // } + + d.cfg.Packages = append(d.cfg.Packages, packageNameForConfig) + addedPackageNames = append(addedPackageNames, packageNameForConfig) + } + + // Resolving here ensures we allow insecure before running ensurePackagesAreInstalled + // which will call print-dev-env. Resolving does not save the lockfile, we + // save at the end when everything has succeeded. + if d.allowInsecureAdds { + for _, name := range addedPackageNames { + p, err := d.lockfile.Resolve(name) + if err != nil { + return err + } + p.AllowInsecure = true } } @@ -88,9 +113,7 @@ func (d *Devbox) Add(ctx context.Context, pkgsNames ...string) error { } } - if err := d.lockfile.Add( - lo.Map(pkgs, func(pkg *devpkg.Package, _ int) string { return pkg.Raw })..., - ); err != nil { + if err := d.lockfile.Save(); err != nil { return err } diff --git a/internal/lock/lockfile.go b/internal/lock/lockfile.go index 885d3b121fb..ce82015aeee 100644 --- a/internal/lock/lockfile.go +++ b/internal/lock/lockfile.go @@ -113,6 +113,15 @@ func (l *File) Get(pkg string) *Package { return entry } +func (l *File) HasAllowInsecurePackages() bool { + for _, pkg := range l.Packages { + if pkg.AllowInsecure { + return true + } + } + return false +} + // This probably belongs in input.go but can't add it there because it will // create a circular dependency. We could move Input into own package. func IsLegacyPackage(pkg string) bool { diff --git a/internal/lock/package.go b/internal/lock/package.go index cc61f275d8b..5ce97c1b2b8 100644 --- a/internal/lock/package.go +++ b/internal/lock/package.go @@ -9,6 +9,7 @@ const ( ) type Package struct { + AllowInsecure bool `json:"allow_insecure,omitempty"` LastModified string `json:"last_modified,omitempty"` PluginVersion string `json:"plugin_version,omitempty"` Resolved string `json:"resolved,omitempty"` @@ -35,3 +36,10 @@ func (p *Package) GetSource() string { } return p.Source } + +func (p *Package) IsAllowInsecure() bool { + if p == nil { + return false + } + return p.AllowInsecure +} diff --git a/internal/nix/command.go b/internal/nix/command.go index 81327328e81..7df6bcdd066 100644 --- a/internal/nix/command.go +++ b/internal/nix/command.go @@ -1,7 +1,6 @@ package nix import ( - "os" "os/exec" ) @@ -12,6 +11,10 @@ func command(args ...string) *exec.Cmd { return cmd } -func allowUnfreeEnv() []string { - return append(os.Environ(), "NIXPKGS_ALLOW_UNFREE=1") +func allowUnfreeEnv(curEnv []string) []string { + return append(curEnv, "NIXPKGS_ALLOW_UNFREE=1") +} + +func allowInsecureEnv(curEnv []string) []string { + return append(curEnv, "NIXPKGS_ALLOW_INSECURE=1") } diff --git a/internal/nix/eval.go b/internal/nix/eval.go new file mode 100644 index 00000000000..00843d2a404 --- /dev/null +++ b/internal/nix/eval.go @@ -0,0 +1,56 @@ +package nix + +import ( + "encoding/json" + "os" + "strconv" +) + +func EvalPackageName(path string) (string, error) { + cmd := command("eval", "--raw", path+".name") + out, err := cmd.Output() + if err != nil { + return "", err + } + return string(out), nil +} + +// PackageIsInsecure is a fun little nix eval that maybe works. +func PackageIsInsecure(path string) bool { + cmd := command("eval", path+".meta.insecure") + out, err := cmd.Output() + if err != nil { + // We can't know for sure, but probably not. + return false + } + var insecure bool + if err := json.Unmarshal(out, &insecure); err != nil { + // We can't know for sure, but probably not. + return false + } + return insecure +} + +func PackageKnownVulnerabilities(path string) []string { + cmd := command("eval", path+".meta.knownVulnerabilities") + out, err := cmd.Output() + if err != nil { + // We can't know for sure, but probably not. + return nil + } + var vulnerabilities []string + if err := json.Unmarshal(out, &vulnerabilities); err != nil { + // We can't know for sure, but probably not. + return nil + } + return vulnerabilities +} + +func AllowInsecurePackages() { + os.Setenv("NIXPKGS_ALLOW_INSECURE", "1") +} + +func IsInsecureAllowed() bool { + allowed, _ := strconv.ParseBool(os.Getenv("NIXPKGS_ALLOW_INSECURE")) + return allowed +} diff --git a/internal/nix/nix.go b/internal/nix/nix.go index 31200516ea5..c5763ef8950 100644 --- a/internal/nix/nix.go +++ b/internal/nix/nix.go @@ -10,11 +10,13 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "runtime/trace" "strings" "github.com/pkg/errors" "go.jetpack.io/devbox/internal/boxcli/featureflag" + "go.jetpack.io/devbox/internal/boxcli/usererr" "go.jetpack.io/devbox/internal/debug" ) @@ -69,7 +71,9 @@ func (*Nix) PrintDevEnv(ctx context.Context, args *PrintDevEnvArgs) (*PrintDevEn cmd.Args = append(cmd.Args, "--json") debug.Log("Running print-dev-env cmd: %s\n", cmd) data, err = cmd.Output() - if err != nil { + if insecure, insecureErr := isExitErrorInsecurePackage(err); insecure { + return nil, insecureErr + } else if err != nil { return nil, errors.Wrapf(err, "Command: %s", cmd) } @@ -120,6 +124,7 @@ func System() (string, error) { // For Savil to debug "remove nixpkgs" feature. The Search api lacks x86-darwin info. // So, I need to fake that I am x86-linux and inspect the output in generated devbox.lock // and flake.nix files. + // This is also used by unit tests. override := os.Getenv("__DEVBOX_NIX_SYSTEM") if override != "" { return override, nil @@ -144,3 +149,19 @@ func System() (string, error) { func ProfileBinPath(projectDir string) string { return filepath.Join(projectDir, ProfilePath, "bin") } + +func isExitErrorInsecurePackage(err error) (bool, error) { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) && exitErr.ExitCode() == 1 { + if strings.Contains(string(exitErr.Stderr), "is marked as insecure") { + re := regexp.MustCompile(`Package ([^ ]+)`) + match := re.FindStringSubmatch(string(exitErr.Stderr)) + return true, usererr.New( + "Package %s is insecure. \n\n"+ + "To override use `devbox add --allow-insecure`", + match[0], + ) + } + } + return false, nil +} diff --git a/internal/nix/profiles.go b/internal/nix/profiles.go index 5b180bf331e..3c35d894b40 100644 --- a/internal/nix/profiles.go +++ b/internal/nix/profiles.go @@ -13,6 +13,7 @@ import ( "path/filepath" "github.com/pkg/errors" + "go.jetpack.io/devbox/internal/boxcli/usererr" "go.jetpack.io/devbox/internal/redact" ) @@ -50,6 +51,16 @@ func ProfileList(writer io.Writer, profilePath string) ([]string, error) { func ProfileInstall(writer io.Writer, profilePath string, installable string) error { + if !IsInsecureAllowed() && PackageIsInsecure(installable) { + knownVulnerabilities := PackageKnownVulnerabilities(installable) + errString := fmt.Sprintf("Package %s is insecure. \n\n", installable) + if len(knownVulnerabilities) > 0 { + errString += fmt.Sprintf("Known vulnerabilities: %s \n\n", knownVulnerabilities) + } + errString += "To override use `devbox add --allow-insecure`" + return usererr.New(errString) + } + cmd := command( "profile", "install", "--profile", profilePath, @@ -60,7 +71,7 @@ func ProfileInstall(writer io.Writer, profilePath string, installable string) er "--priority", nextPriority(profilePath), installable, ) - cmd.Env = allowUnfreeEnv() + cmd.Env = allowUnfreeEnv(os.Environ()) // If nix profile install runs as tty, the output is much nicer. If we ever // need to change this to our own writers, consider that you may need @@ -81,7 +92,7 @@ func ProfileRemove(profilePath string, indexes []string) error { "--impure", // for NIXPKGS_ALLOW_UNFREE }, indexes...)..., ) - cmd.Env = allowUnfreeEnv() + cmd.Env = allowUnfreeEnv(allowInsecureEnv(os.Environ())) out, err := cmd.CombinedOutput() if err != nil { diff --git a/internal/shellgen/flake_input.go b/internal/shellgen/flake_input.go index 8219c383162..95befdfa723 100644 --- a/internal/shellgen/flake_input.go +++ b/internal/shellgen/flake_input.go @@ -14,7 +14,7 @@ import ( type flakeInput struct { Name string - Packages []string + Packages []*devpkg.Package URL string } @@ -47,17 +47,28 @@ func (f *flakeInput) PkgImportName() string { return f.Name + "-pkgs" } -func (f *flakeInput) BuildInputs() []string { +func (f *flakeInput) BuildInputs() ([]string, error) { + var err error + attributePaths := lo.Map(f.Packages, func(pkg *devpkg.Package, _ int) string { + attributePath, attributePathErr := pkg.FullPackageAttributePath() + if attributePathErr != nil { + err = attributePathErr + } + return attributePath + }) + if err != nil { + return nil, err + } if !f.IsNixpkgs() { - return lo.Map(f.Packages, func(pkg string, _ int) string { + return lo.Map(attributePaths, func(pkg string, _ int) string { return f.Name + "." + pkg - }) + }), nil } - return lo.Map(f.Packages, func(pkg string, _ int) string { + return lo.Map(attributePaths, func(pkg string, _ int) string { parts := strings.Split(pkg, ".") // Ugh, not sure if this is reliable? return f.PkgImportName() + "." + strings.Join(parts[2:], ".") - }) + }), nil } // flakeInputs returns a list of flake inputs for the top level flake.nix @@ -66,7 +77,7 @@ func (f *flakeInput) BuildInputs() []string { // i.e. have a commit hash and always resolve to the same package/version. // Note: inputs returned by this function include plugin packages. (php only for now) // It's not entirely clear we always want to add plugin packages to the top level -func flakeInputs(ctx context.Context, packages []*devpkg.Package) ([]*flakeInput, error) { +func flakeInputs(ctx context.Context, packages []*devpkg.Package) []*flakeInput { defer trace.StartRegion(ctx, "flakeInputs").End() // Use the verbose name flakeInputs to distinguish from `inputs` @@ -90,23 +101,19 @@ func flakeInputs(ctx context.Context, packages []*devpkg.Package) ([]*flakeInput order := []string{} for _, input := range packages { - AttributePath, err := input.FullPackageAttributePath() - if err != nil { - return nil, err - } if flkInput, ok := flakeInputs[input.URLForFlakeInput()]; !ok { order = append(order, input.URLForFlakeInput()) flakeInputs[input.URLForFlakeInput()] = &flakeInput{ Name: input.FlakeInputName(), URL: input.URLForFlakeInput(), - Packages: []string{AttributePath}, + Packages: []*devpkg.Package{input}, } } else { flkInput.Packages = lo.Uniq( - append(flakeInputs[input.URLForFlakeInput()].Packages, AttributePath), + append(flakeInputs[input.URLForFlakeInput()].Packages, input), ) } } - return goutil.PickByKeysSorted(flakeInputs, order), nil + return goutil.PickByKeysSorted(flakeInputs, order) } diff --git a/internal/shellgen/flake_plan.go b/internal/shellgen/flake_plan.go index 93c9c3b25b1..56d38b2d925 100644 --- a/internal/shellgen/flake_plan.go +++ b/internal/shellgen/flake_plan.go @@ -51,10 +51,7 @@ func newFlakePlan(ctx context.Context, devbox devboxer) (*flakePlan, error) { // priority field to the config. packages := append(pluginPackages, userPackages...) - flakeInputs, err := flakeInputs(ctx, packages) - if err != nil { - return nil, err - } + flakeInputs := flakeInputs(ctx, packages) nixpkgsInfo := getNixpkgsInfo(devbox.Config().NixPkgsCommitHash()) diff --git a/internal/shellgen/generate_test.go b/internal/shellgen/generate_test.go index 304b4a6c739..c6a9c4fe056 100644 --- a/internal/shellgen/generate_test.go +++ b/internal/shellgen/generate_test.go @@ -11,12 +11,16 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "go.jetpack.io/devbox/internal/devpkg" + "go.jetpack.io/devbox/internal/lock" + "go.jetpack.io/devbox/internal/searcher" ) // update overwrites golden files with the new test results. var update = flag.Bool("update", false, "update the golden files with the test results") func TestWriteFromTemplate(t *testing.T) { + t.Setenv("__DEVBOX_NIX_SYSTEM", "x86_64-linux") dir := filepath.Join(t.TempDir(), "makeme") outPath := filepath.Join(dir, "flake.nix") err := writeFromTemplate(dir, testFlakeTmplPlan, "flake.nix", "flake.nix") @@ -77,6 +81,7 @@ If the new file is correct, you can update the golden file with: } } +var locker = &lockmock{} var testFlakeTmplPlan = &struct { NixpkgsInfo struct { URL string @@ -92,30 +97,51 @@ var testFlakeTmplPlan = &struct { { Name: "nixpkgs", URL: "github:NixOS/nixpkgs/b9c00c1d41ccd6385da243415299b39aa73357be", - Packages: []string{ - "legacyPackages.aarch64-darwin.php", - "legacyPackages.aarch64-darwin.php81Packages.composer", - "legacyPackages.aarch64-darwin.php81Extensions.blackfire", - "legacyPackages.aarch64-darwin.flyctl", - "legacyPackages.aarch64-darwin.postgresql", - "legacyPackages.aarch64-darwin.tree", - "legacyPackages.aarch64-darwin.git", - "legacyPackages.aarch64-darwin.zsh", - "legacyPackages.aarch64-darwin.openssh", - "legacyPackages.aarch64-darwin.vim", - "legacyPackages.aarch64-darwin.sqlite", - "legacyPackages.aarch64-darwin.jq", - "legacyPackages.aarch64-darwin.delve", - "legacyPackages.aarch64-darwin.ripgrep", - "legacyPackages.aarch64-darwin.shellcheck", - "legacyPackages.aarch64-darwin.terraform", - "legacyPackages.aarch64-darwin.xz", - "legacyPackages.aarch64-darwin.zstd", - "legacyPackages.aarch64-darwin.gnupg", - "legacyPackages.aarch64-darwin.go_1_20", - "legacyPackages.aarch64-darwin.python3", - "legacyPackages.aarch64-darwin.graphviz", + Packages: []*devpkg.Package{ + devpkg.PackageFromString("php@latest", locker), + devpkg.PackageFromString("php81Packages.composer@latest", locker), + devpkg.PackageFromString("php81Extensions.blackfire@latest", locker), + devpkg.PackageFromString("flyctl@latest", locker), + devpkg.PackageFromString("postgresql@latest", locker), + devpkg.PackageFromString("tree@latest", locker), + devpkg.PackageFromString("git@latest", locker), + devpkg.PackageFromString("zsh@latest", locker), + devpkg.PackageFromString("openssh@latest", locker), + devpkg.PackageFromString("vim@latest", locker), + devpkg.PackageFromString("sqlite@latest", locker), + devpkg.PackageFromString("jq@latest", locker), + devpkg.PackageFromString("delve@latest", locker), + devpkg.PackageFromString("ripgrep@latest", locker), + devpkg.PackageFromString("shellcheck@latest", locker), + devpkg.PackageFromString("terraform@latest", locker), + devpkg.PackageFromString("xz@latest", locker), + devpkg.PackageFromString("zstd@latest", locker), + devpkg.PackageFromString("gnupg@latest", locker), + devpkg.PackageFromString("go_1_20@latest", locker), + devpkg.PackageFromString("python3@latest", locker), + devpkg.PackageFromString("graphviz@latest", locker), }, }, }, } + +type lockmock struct{} + +func (*lockmock) Resolve(pkg string) (*lock.Package, error) { + name, _, _ := searcher.ParseVersionedPackage(pkg) + return &lock.Package{ + Resolved: "#" + name, + }, nil +} + +func (*lockmock) Get(pkg string) *lock.Package { + return nil +} + +func (*lockmock) LegacyNixpkgsPath(pkg string) string { + return "" +} + +func (*lockmock) ProjectDir() string { + return "" +} diff --git a/internal/shellgen/testdata/flake.nix.golden b/internal/shellgen/testdata/flake.nix.golden index 2959223494d..44a6e8dd540 100644 --- a/internal/shellgen/testdata/flake.nix.golden +++ b/internal/shellgen/testdata/flake.nix.golden @@ -22,6 +22,8 @@ nixpkgs-pkgs = (import nixpkgs { inherit system; config.allowUnfree = true; + config.permittedInsecurePackages = [ + ]; }); in { diff --git a/internal/shellgen/tmpl/flake.nix.tmpl b/internal/shellgen/tmpl/flake.nix.tmpl index 52fdc595b33..9c28ed06972 100644 --- a/internal/shellgen/tmpl/flake.nix.tmpl +++ b/internal/shellgen/tmpl/flake.nix.tmpl @@ -24,11 +24,18 @@ inherit system; config.allowUnfree = true; }); - {{- range .FlakeInputs }} + {{- range $_, $flake := .FlakeInputs }} {{- if .IsNixpkgs }} {{.PkgImportName}} = (import {{.Name}} { inherit system; config.allowUnfree = true; + config.permittedInsecurePackages = [ + {{- range $flake.Packages }} + {{- if .AllowInsecure }} + "{{ .StoreName }}" + {{- end }} + {{- end }} + ]; }); {{- end }} {{- end }} diff --git a/internal/shellgen/tmpl/flake_remove_nixpkgs.nix.tmpl b/internal/shellgen/tmpl/flake_remove_nixpkgs.nix.tmpl index 6cf78efcb64..fa0a3e6ae7d 100644 --- a/internal/shellgen/tmpl/flake_remove_nixpkgs.nix.tmpl +++ b/internal/shellgen/tmpl/flake_remove_nixpkgs.nix.tmpl @@ -17,11 +17,18 @@ }: let pkgs = nixpkgs.legacyPackages.{{ .System }}; - {{- range .FlakeInputs }} + {{- range $_, $flake := .FlakeInputs }} {{- if .IsNixpkgs }} {{.PkgImportName}} = (import {{.Name}} { system = "{{ $.System }}"; config.allowUnfree = true; + config.permittedInsecurePackages = [ + {{- range $flake.Packages }} + {{- if .AllowInsecure }} + "{{ .StoreName }}" + {{- end }} + {{- end }} + ]; }); {{- end }} {{- end }}