diff --git a/pkg/builder/builder.go b/pkg/builder/builder.go index ca61660f..249a70ba 100644 --- a/pkg/builder/builder.go +++ b/pkg/builder/builder.go @@ -36,16 +36,30 @@ var ( knownArgs = map[utils.KnownImageType][]string{ utils.BeagleBone: {"-cpu", "cortex-a8"}, } - defaultChrootTypes = [][]string{ + + defaultBase = [][]string{ {"proc", "proc", "/proc"}, {"sysfs", "sysfs", "/sys"}, {"bind", "/dev", "/dev"}, {"devpts", "devpts", "/dev/pts"}, {"binfmt_misc", "binfmt_misc", "/proc/sys/fs/binfmt_misc"}, - {"bind", "/etc/resolv.conf", "/etc/resolv.conf"}, + } + resolvConfBindMount = []string{"bind", "/etc/resolv.conf", "/etc/resolv.conf"} + + defaultChrootTypes = map[utils.KnownImageType][][]string{ + utils.Unknown: defaultBase, } ) +type ResolvConfBehavior string + +const ( + Off ResolvConfBehavior = "off" + CopyHost ResolvConfBehavior = "copy-host" + BindHost ResolvConfBehavior = "bind-host" + Delete ResolvConfBehavior = "delete" +) + type Config struct { packer_common.PackerConfig `mapstructure:",squash"` // While arm image are not ISOs, we resuse the ISO logic as it basically has no ISO specific code. @@ -88,6 +102,9 @@ type Config struct { // for example: `["bind", "/run/systemd", "/run/systemd"]` AdditionalChrootMounts [][]string `mapstructure:"additional_chroot_mounts"` + // Can be one of: off, copy-host, bind-host, delete. Defaults to off + ResolvConf ResolvConfBehavior `mapstructure:"resolv-conf"` + // Should the last partition be extended? this only works for the last partition in the // dos partition table, and ext filesystem LastPartitionExtraSize uint64 `mapstructure:"last_partition_extra_size"` @@ -157,13 +174,20 @@ func (b *Builder) Prepare(cfgs ...interface{}) ([]string, []string, error) { } if len(b.config.ChrootMounts) == 0 { - b.config.ChrootMounts = defaultChrootTypes + b.config.ChrootMounts = defaultChrootTypes[utils.Unknown] + if imageDefaults, ok := defaultChrootTypes[b.config.ImageType]; ok { + b.config.ChrootMounts = imageDefaults + } } if len(b.config.AdditionalChrootMounts) > 0 { b.config.ChrootMounts = append(b.config.ChrootMounts, b.config.AdditionalChrootMounts...) } + if b.config.ResolvConf == BindHost { + b.config.ChrootMounts = append(b.config.ChrootMounts, resolvConfBindMount) + } + if b.config.CommandWrapper == "" { b.config.CommandWrapper = "{{.Command}}" } @@ -233,7 +257,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack state.Put("ui", ui) state.Put("wrappedCommand", packer_common.CommandWrapper(wrappedCommand)) - // HACK: go-getter automatically decompreses, which hurts caching. + // HACK: go-getter automatically decompress, which hurts caching. // additionally, we use native binaries to decompress which is faster anyway. // disable decompressors: getter.Decompressors = make(map[string]getter.Decompressor) @@ -271,6 +295,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &StepMountExtra{ChrootKey: "mount_path"}, ) + if b.config.ResolvConf == CopyHost || b.config.ResolvConf == Delete { + steps = append(steps, + &stepHandleResolvConf{ChrootKey: "mount_path", Delete: b.config.ResolvConf == Delete}) + } + native := runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" if !native { steps = append(steps, diff --git a/pkg/builder/builder.hcl2spec.go b/pkg/builder/builder.hcl2spec.go index 1b679c02..0c563245 100644 --- a/pkg/builder/builder.hcl2spec.go +++ b/pkg/builder/builder.hcl2spec.go @@ -32,6 +32,7 @@ type FlatConfig struct { MountPath *string `mapstructure:"mount_path" cty:"mount_path"` ChrootMounts [][]string `mapstructure:"chroot_mounts" cty:"chroot_mounts"` AdditionalChrootMounts [][]string `mapstructure:"additional_chroot_mounts" cty:"additional_chroot_mounts"` + ResolvConf *ResolvConfBehavior `mapstructure:"resolv-conf" cty:"resolv-conf"` LastPartitionExtraSize *uint64 `mapstructure:"last_partition_extra_size" cty:"last_partition_extra_size"` TargetImageSize *uint64 `mapstructure:"target_image_size" cty:"target_image_size"` QemuBinary *string `mapstructure:"qemu_binary" cty:"qemu_binary"` @@ -72,6 +73,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "mount_path": &hcldec.AttrSpec{Name: "mount_path", Type: cty.String, Required: false}, "chroot_mounts": &hcldec.BlockListSpec{TypeName: "chroot_mounts", Nested: &hcldec.AttrSpec{Name: "chroot_mounts", Type: cty.List(cty.String), Required: false}}, "additional_chroot_mounts": &hcldec.BlockListSpec{TypeName: "additional_chroot_mounts", Nested: &hcldec.AttrSpec{Name: "additional_chroot_mounts", Type: cty.List(cty.String), Required: false}}, + "resolv-conf": &hcldec.AttrSpec{Name: "resolv-conf", Type: cty.String, Required: false}, "last_partition_extra_size": &hcldec.AttrSpec{Name: "last_partition_extra_size", Type: cty.Number, Required: false}, "target_image_size": &hcldec.AttrSpec{Name: "target_image_size", Type: cty.Number, Required: false}, "qemu_binary": &hcldec.AttrSpec{Name: "qemu_binary", Type: cty.String, Required: false}, diff --git a/pkg/builder/step_handle_resolv_conf.go b/pkg/builder/step_handle_resolv_conf.go new file mode 100644 index 00000000..74adfa51 --- /dev/null +++ b/pkg/builder/step_handle_resolv_conf.go @@ -0,0 +1,61 @@ +package builder + +// taken from here: https://github.com/hashicorp/packer/blob/81522dced0b25084a824e79efda02483b12dc7cd/builder/amazon/chroot/step_chroot_provision.go + +import ( + "context" + "io" + "os" + "path/filepath" + + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" +) + +// stepHandleResolvConf provisions the instance within a chroot. +type stepHandleResolvConf struct { + ChrootKey string + Delete bool +} + +func (s *stepHandleResolvConf) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { + mountPath := state.Get(s.ChrootKey).(string) + ui := state.Get("ui").(packer.Ui) + + const origResolvConf = "/etc/resolv.conf" + destResolvConf := filepath.Join(mountPath, origResolvConf) + + if s.Delete { + err := os.Remove(destResolvConf) + if err != nil { + ui.Error(err.Error()) + return multistep.ActionHalt + } + } else { + // copy file over: + err := copyFile(destResolvConf, origResolvConf) + if err != nil { + ui.Error(err.Error()) + return multistep.ActionHalt + } + } + + return multistep.ActionContinue +} + +func (s *stepHandleResolvConf) Cleanup(state multistep.StateBag) {} + +func copyFile(dst, src string) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + _, err = io.Copy(out, in) + return err +} diff --git a/pkg/image/utils/images.go b/pkg/image/utils/images.go index cada016a..3a7dd602 100644 --- a/pkg/image/utils/images.go +++ b/pkg/image/utils/images.go @@ -12,6 +12,7 @@ const ( RaspberryPi KnownImageType = "raspberrypi" BeagleBone KnownImageType = "beaglebone" Kali KnownImageType = "kali" + Unknown KnownImageType = "" ) func GuessImageType(url string) KnownImageType {