diff --git a/builder/alicloud/ecs/builder.go b/builder/alicloud/ecs/builder.go index 476b3c4a2..3b2688b1f 100644 --- a/builder/alicloud/ecs/builder.go +++ b/builder/alicloud/ecs/builder.go @@ -157,6 +157,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.RunConfig.Comm, + }, &stepStopAlicloudInstance{ ForceStop: b.config.ForceStopInstance, }, diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 7cce60f83..60b201e26 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -211,6 +211,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.RunConfig.Comm, + }, &awscommon.StepStopEBSBackedInstance{ Skip: b.config.IsSpotInstance(), DisableStopInstance: b.config.DisableStopInstance, diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index f10c88585..44dabbc67 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -228,6 +228,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.RunConfig.Comm, + }, &awscommon.StepStopEBSBackedInstance{ Skip: b.config.IsSpotInstance(), DisableStopInstance: b.config.DisableStopInstance, diff --git a/builder/amazon/ebsvolume/builder.go b/builder/amazon/ebsvolume/builder.go index 98f6cd116..15493b790 100644 --- a/builder/amazon/ebsvolume/builder.go +++ b/builder/amazon/ebsvolume/builder.go @@ -203,6 +203,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.RunConfig.Comm, + }, &awscommon.StepStopEBSBackedInstance{ Skip: b.config.IsSpotInstance(), DisableStopInstance: b.config.DisableStopInstance, diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 9fa4a16f8..815caa474 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -286,6 +286,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.RunConfig.Comm, + }, &StepUploadX509Cert{}, &StepBundleVolume{ Debug: b.config.PackerDebug, diff --git a/builder/azure/arm/builder.go b/builder/azure/arm/builder.go index 061595ba0..6ba41523f 100644 --- a/builder/azure/arm/builder.go +++ b/builder/azure/arm/builder.go @@ -177,6 +177,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, &packerCommon.StepProvision{}, + &packerCommon.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, NewStepGetOSDisk(azureClient, ui), NewStepGetAdditionalDisks(azureClient, ui), NewStepPowerOffCompute(azureClient, ui), diff --git a/builder/cloudstack/builder.go b/builder/cloudstack/builder.go index f803d77dc..2efa4f853 100644 --- a/builder/cloudstack/builder.go +++ b/builder/cloudstack/builder.go @@ -82,6 +82,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe WinRMPort: commPort, }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, &stepShutdownInstance{}, &stepCreateTemplate{}, } diff --git a/builder/digitalocean/builder.go b/builder/digitalocean/builder.go index 1c34f6591..276c6c539 100644 --- a/builder/digitalocean/builder.go +++ b/builder/digitalocean/builder.go @@ -90,6 +90,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, new(common.StepProvision), + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, new(stepShutdown), new(stepPowerOff), new(stepSnapshot), diff --git a/builder/docker/builder.go b/builder/docker/builder.go index 951231c8d..a9cf432ed 100644 --- a/builder/docker/builder.go +++ b/builder/docker/builder.go @@ -54,6 +54,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, } if b.config.Discard { diff --git a/builder/googlecompute/builder.go b/builder/googlecompute/builder.go index b4a5f7bb9..998bd6ccf 100644 --- a/builder/googlecompute/builder.go +++ b/builder/googlecompute/builder.go @@ -71,6 +71,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe WinRMConfig: winrmConfig, }, new(common.StepProvision), + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, } if _, exists := b.config.Metadata[StartupScriptKey]; exists || b.config.StartupScriptFile != "" { steps = append(steps, new(StepWaitStartupScript)) diff --git a/builder/hyperv/iso/builder.go b/builder/hyperv/iso/builder.go index a50821ad1..682e2cb30 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -460,6 +460,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe // provision requires communicator to be setup &common.StepProvision{}, + // Remove ephemeral key from authorized_hosts if using SSH communicator + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, + &hypervcommon.StepShutdown{ Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, diff --git a/builder/hyperv/vmcx/builder.go b/builder/hyperv/vmcx/builder.go index 2bf5c84f5..024c4c7cb 100644 --- a/builder/hyperv/vmcx/builder.go +++ b/builder/hyperv/vmcx/builder.go @@ -489,6 +489,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe // provision requires communicator to be setup &common.StepProvision{}, + // Remove ephemeral SSH keys, if using + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, + &hypervcommon.StepShutdown{ Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, diff --git a/builder/ncloud/builder.go b/builder/ncloud/builder.go index ae7de4c80..9e53edcf8 100644 --- a/builder/ncloud/builder.go +++ b/builder/ncloud/builder.go @@ -54,6 +54,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, NewStepStopServerInstance(conn, ui), NewStepCreateServerImage(conn, ui, b.config), NewStepDeleteBlockStorageInstance(conn, ui, b.config), diff --git a/builder/oneandone/builder.go b/builder/oneandone/builder.go index 2faf953c6..12bc071e8 100644 --- a/builder/oneandone/builder.go +++ b/builder/oneandone/builder.go @@ -48,6 +48,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, new(stepTakeSnapshot), } diff --git a/builder/openstack/builder.go b/builder/openstack/builder.go index b049868ca..7aba1d432 100644 --- a/builder/openstack/builder.go +++ b/builder/openstack/builder.go @@ -133,6 +133,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.RunConfig.Comm, + }, &StepStopServer{}, &StepDetachVolume{ UseBlockStorageVolume: b.config.UseBlockStorageVolume, diff --git a/builder/oracle/classic/builder.go b/builder/oracle/classic/builder.go index 7ad084982..b0bfeef4f 100644 --- a/builder/oracle/classic/builder.go +++ b/builder/oracle/classic/builder.go @@ -77,6 +77,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, &stepSnapshot{}, &stepListImages{}, } diff --git a/builder/oracle/oci/builder.go b/builder/oracle/oci/builder.go index a423b1001..e3989a23a 100644 --- a/builder/oracle/oci/builder.go +++ b/builder/oracle/oci/builder.go @@ -69,6 +69,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, &stepImage{}, } diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index 55c6ced0c..b3609cf7f 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -209,6 +209,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Ctx: b.config.ctx, }, new(common.StepProvision), + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, ¶llelscommon.StepShutdown{ Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, diff --git a/builder/parallels/pvm/builder.go b/builder/parallels/pvm/builder.go index 423afde1d..34e3b5da8 100644 --- a/builder/parallels/pvm/builder.go +++ b/builder/parallels/pvm/builder.go @@ -102,6 +102,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, }, + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, ¶llelscommon.StepPrlctl{ Commands: b.config.PrlctlPost, Ctx: b.config.ctx, diff --git a/builder/profitbricks/builder.go b/builder/profitbricks/builder.go index dfc754ad4..c4823de3e 100644 --- a/builder/profitbricks/builder.go +++ b/builder/profitbricks/builder.go @@ -45,6 +45,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, new(stepTakeSnapshot), } diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index 47ebb2396..189569288 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -403,6 +403,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe steps = append(steps, new(common.StepProvision), ) + + steps = append(steps, + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, + ) steps = append(steps, new(stepShutdown), ) diff --git a/builder/scaleway/builder.go b/builder/scaleway/builder.go index 2f668f994..51b2bae56 100644 --- a/builder/scaleway/builder.go +++ b/builder/scaleway/builder.go @@ -61,6 +61,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, new(common.StepProvision), + &common.StepCleanupTempKeys{ + Comm: &b.config.Comm, + }, new(stepShutdown), new(stepSnapshot), new(stepImage), diff --git a/builder/triton/builder.go b/builder/triton/builder.go index 1d5c7f583..163ee17cd 100644 --- a/builder/triton/builder.go +++ b/builder/triton/builder.go @@ -68,6 +68,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &config.Comm, + }, &StepStopMachine{}, &StepCreateImageFromMachine{}, &StepDeleteMachine{}, diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index 2d0f3a837..df0c9630b 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -267,6 +267,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Ctx: b.config.ctx, }, new(common.StepProvision), + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, &vboxcommon.StepShutdown{ Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index 3d7deb4a3..c87a16cb0 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -128,6 +128,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Ctx: b.config.ctx, }, new(common.StepProvision), + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, &vboxcommon.StepShutdown{ Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 779cc868c..054ff4664 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -368,6 +368,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Ctx: b.config.ctx, }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, &vmwcommon.StepShutdown{ Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 3cbd14ec2..42a550f29 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -111,6 +111,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Ctx: b.config.ctx, }, &common.StepProvision{}, + &common.StepCleanupTempKeys{ + Comm: &b.config.SSHConfig.Comm, + }, &vmwcommon.StepShutdown{ Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, diff --git a/common/step_cleanup_temp_keys.go b/common/step_cleanup_temp_keys.go new file mode 100644 index 000000000..0299257cc --- /dev/null +++ b/common/step_cleanup_temp_keys.go @@ -0,0 +1,56 @@ +package common + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/packer/helper/communicator" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" +) + +type StepCleanupTempKeys struct { + Comm *communicator.Config +} + +func (s *StepCleanupTempKeys) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { + // This step is mostly cosmetic; Packer deletes the ephemeral keys anyway + // so there's no realistic situation where these keys can cause issues. + // However, it's nice to clean up after yourself. + + comm := state.Get("communicator").(packer.Communicator) + ui := state.Get("ui").(packer.Ui) + + if !s.Comm.SSHClearAuthorizedKeys { + return multistep.ActionContinue + } + + if s.Comm.Type != "ssh" { + return multistep.ActionContinue + } + + if s.Comm.SSHTemporaryKeyPairName == "" { + return multistep.ActionContinue + } + + cmd := new(packer.RemoteCmd) + + ui.Say("Trying to remove ephemeral keys from authorized_keys files") + + cmd.Command = fmt.Sprintf("sed -i.bak '/ssh-rsa.*%s$/d' ~/.ssh/authorized_keys; rm ~/.ssh/authorized_keys.bak", s.Comm.SSHTemporaryKeyPairName) + if err := cmd.StartWithUi(comm, ui); err != nil { + log.Printf("Error cleaning up ~/.ssh/authorized_keys; please clean up keys manually: %s", err) + } + cmd = new(packer.RemoteCmd) + cmd.Command = fmt.Sprintf("sudo sed -i.bak '/ssh-rsa.*%s$/d' /root/.ssh/authorized_keys; sudo rm /root/.ssh/authorized_keys.bak", s.Comm.SSHTemporaryKeyPairName) + + if err := cmd.StartWithUi(comm, ui); err != nil { + log.Printf("Error cleaning up /root/.ssh/authorized_keys; please clean up keys manually: %s", err) + } + + return multistep.ActionContinue +} + +func (s *StepCleanupTempKeys) Cleanup(state multistep.StateBag) { +} diff --git a/helper/communicator/config.go b/helper/communicator/config.go index 44bc5a999..44738d61b 100644 --- a/helper/communicator/config.go +++ b/helper/communicator/config.go @@ -31,6 +31,7 @@ type Config struct { SSHPrivateKey []byte `mapstructure:"ssh_private_key"` SSHKeyPairName string `mapstructure:"ssh_keypair_name"` SSHTemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"` + SSHClearAuthorizedKeys bool `mapstructure:"ssh_clear_authorized_keys"` SSHPrivateKeyFile string `mapstructure:"ssh_private_key_file"` SSHInterface string `mapstructure:"ssh_interface"` SSHIPVersion string `mapstructure:"ssh_ip_version"` diff --git a/website/source/docs/templates/communicator.html.md b/website/source/docs/templates/communicator.html.md index 725c3e890..c38e3af2f 100644 --- a/website/source/docs/templates/communicator.html.md +++ b/website/source/docs/templates/communicator.html.md @@ -79,6 +79,13 @@ The SSH communicator has the following options: - `ssh_bastion_username` (string) - The username to connect to the bastion host. +- `ssh_clear_authorized_keys` (boolean) - If true, Packer will attempt to + remove its temporary key from `~/.ssh/authorized_keys` and + `/root/.ssh/authorized_keys`. This is a mostly cosmetic option, since Packer + will delete the temporary private key from the host system regardless of + whether this is set to true (unless the user has set the `-debug` flag). + Defaults to "false"; currently only works on guests with `sed` installed. + - `ssh_disable_agent_forwarding` (boolean) - If true, SSH agent forwarding will be disabled. Defaults to `false`.