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(ctx 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. if !s.Comm.SSHClearAuthorizedKeys { return multistep.ActionContinue } if s.Comm.Type != "ssh" { return multistep.ActionContinue } if s.Comm.SSHTemporaryKeyPairName == "" { return multistep.ActionContinue } comm := state.Get("communicator").(packer.Communicator) ui := state.Get("ui").(packer.Ui) cmd := new(packer.RemoteCmd) ui.Say("Trying to remove ephemeral keys from authorized_keys files") // Per the OpenSSH manual (https://man.openbsd.org/sshd.8), a typical // line in the 'authorized_keys' file contains several fields that // are delimited by spaces. Here is an (abbreviated) example of a line: // ssh-rsa AAAAB3Nza...LiPk== user@example.net // // In the above example, 'ssh-rsa' is the key pair type, // 'AAAAB3Nza...LiPk==' is the base64 encoded public key, // and 'user@example.net' is a comment (in this case, describing // who the key belongs to). // // In the following 'sed' calls, the comment field will be equal to // the value of communicator.Config.SSHTemporaryKeyPairName. // We can remove an authorized public key using 'sed' by looking // for a line ending in ' packer-key-pair-comment' (note the // leading space). // // TODO: Why create a backup file if you are going to remove it? cmd.Command = fmt.Sprintf("sed -i.bak '/ %s$/d' ~/.ssh/authorized_keys; rm ~/.ssh/authorized_keys.bak", s.Comm.SSHTemporaryKeyPairName) if err := cmd.RunWithUi(ctx, 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 '/ %s$/d' /root/.ssh/authorized_keys; sudo rm /root/.ssh/authorized_keys.bak", s.Comm.SSHTemporaryKeyPairName) if err := cmd.RunWithUi(ctx, 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) { }