diff --git a/builder/osc/bsusurrogate/builder.go b/builder/osc/bsusurrogate/builder.go index 2329b9e02..a49222184 100644 --- a/builder/osc/bsusurrogate/builder.go +++ b/builder/osc/bsusurrogate/builder.go @@ -153,6 +153,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SubnetFilter: b.config.SubnetFilter, SubregionName: b.config.Subregion, }, + &osccommon.StepKeyPair{ + Debug: b.config.PackerDebug, + Comm: &b.config.RunConfig.Comm, + DebugKeyPath: fmt.Sprintf("oapi_%s.pem", b.config.PackerBuildName), + }, } b.runner = common.NewRunner(steps, b.config.PackerConfig, ui) diff --git a/builder/osc/common/step_key_pair.go b/builder/osc/common/step_key_pair.go new file mode 100644 index 000000000..580046b55 --- /dev/null +++ b/builder/osc/common/step_key_pair.go @@ -0,0 +1,123 @@ +package common + +import ( + "context" + "fmt" + "os" + "runtime" + + "github.com/hashicorp/packer/helper/communicator" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" + "github.com/outscale/osc-go/oapi" +) + +type StepKeyPair struct { + Debug bool + Comm *communicator.Config + DebugKeyPath string + + doCleanup bool +} + +func (s *StepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packer.Ui) + + if s.Comm.SSHPrivateKeyFile != "" { + ui.Say("Using existing SSH private key") + privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile() + if err != nil { + state.Put("error", err) + return multistep.ActionHalt + } + + s.Comm.SSHPrivateKey = privateKeyBytes + + return multistep.ActionContinue + } + + if s.Comm.SSHAgentAuth && s.Comm.SSHKeyPairName == "" { + ui.Say("Using SSH Agent with key pair in Source AMI") + return multistep.ActionContinue + } + + if s.Comm.SSHAgentAuth && s.Comm.SSHKeyPairName != "" { + ui.Say(fmt.Sprintf("Using SSH Agent for existing key pair %s", s.Comm.SSHKeyPairName)) + return multistep.ActionContinue + } + + if s.Comm.SSHTemporaryKeyPairName == "" { + ui.Say("Not using temporary keypair") + s.Comm.SSHKeyPairName = "" + return multistep.ActionContinue + } + + oapiconn := state.Get("oapi").(*oapi.Client) + + ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.Comm.SSHTemporaryKeyPairName)) + keyResp, err := oapiconn.POST_CreateKeypair(oapi.CreateKeypairRequest{ + KeypairName: s.Comm.SSHTemporaryKeyPairName}) + if err != nil { + state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err)) + return multistep.ActionHalt + } + + s.doCleanup = true + + // Set some data for use in future steps + s.Comm.SSHKeyPairName = s.Comm.SSHTemporaryKeyPairName + s.Comm.SSHPrivateKey = []byte(keyResp.OK.Keypair.PrivateKey) + + // If we're in debug mode, output the private key to the working + // directory. + if s.Debug { + ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath)) + f, err := os.Create(s.DebugKeyPath) + if err != nil { + state.Put("error", fmt.Errorf("Error saving debug key: %s", err)) + return multistep.ActionHalt + } + defer f.Close() + + // Write the key out + if _, err := f.Write([]byte(keyResp.OK.Keypair.PrivateKey)); err != nil { + state.Put("error", fmt.Errorf("Error saving debug key: %s", err)) + return multistep.ActionHalt + } + + // Chmod it so that it is SSH ready + if runtime.GOOS != "windows" { + if err := f.Chmod(0600); err != nil { + state.Put("error", fmt.Errorf("Error setting permissions of debug key: %s", err)) + return multistep.ActionHalt + } + } + } + + return multistep.ActionContinue +} + +func (s *StepKeyPair) Cleanup(state multistep.StateBag) { + if !s.doCleanup { + return + } + + oapiconn := state.Get("oapi").(*oapi.Client) + ui := state.Get("ui").(packer.Ui) + + // Remove the keypair + ui.Say("Deleting temporary keypair...") + _, err := oapiconn.POST_DeleteKeypair(oapi.DeleteKeypairRequest{KeypairName: s.Comm.SSHTemporaryKeyPairName}) + if err != nil { + ui.Error(fmt.Sprintf( + "Error cleaning up keypair. Please delete the key manually: %s", s.Comm.SSHTemporaryKeyPairName)) + } + + // Also remove the physical key if we're debugging. + if s.Debug { + if err := os.Remove(s.DebugKeyPath); err != nil { + ui.Error(fmt.Sprintf( + "Error removing debug key '%s': %s", s.DebugKeyPath, err)) + } + } +}