github.phpd.cn/hashicorp/packer@v1.3.2/builder/amazon/common/step_key_pair.go (about)

     1  package common
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"runtime"
     9  
    10  	"github.com/aws/aws-sdk-go/service/ec2"
    11  	"github.com/hashicorp/packer/helper/communicator"
    12  	"github.com/hashicorp/packer/helper/multistep"
    13  	"github.com/hashicorp/packer/packer"
    14  )
    15  
    16  type StepKeyPair struct {
    17  	Debug        bool
    18  	Comm         *communicator.Config
    19  	DebugKeyPath string
    20  
    21  	doCleanup bool
    22  }
    23  
    24  func (s *StepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
    25  	ui := state.Get("ui").(packer.Ui)
    26  
    27  	if s.Comm.SSHPrivateKeyFile != "" {
    28  		ui.Say("Using existing SSH private key")
    29  		privateKeyBytes, err := ioutil.ReadFile(s.Comm.SSHPrivateKeyFile)
    30  		if err != nil {
    31  			state.Put("error", fmt.Errorf(
    32  				"Error loading configured private key file: %s", err))
    33  			return multistep.ActionHalt
    34  		}
    35  
    36  		s.Comm.SSHPrivateKey = privateKeyBytes
    37  
    38  		return multistep.ActionContinue
    39  	}
    40  
    41  	if s.Comm.SSHAgentAuth && s.Comm.SSHKeyPairName == "" {
    42  		ui.Say("Using SSH Agent with key pair in Source AMI")
    43  		return multistep.ActionContinue
    44  	}
    45  
    46  	if s.Comm.SSHAgentAuth && s.Comm.SSHKeyPairName != "" {
    47  		ui.Say(fmt.Sprintf("Using SSH Agent for existing key pair %s", s.Comm.SSHKeyPairName))
    48  		return multistep.ActionContinue
    49  	}
    50  
    51  	if s.Comm.SSHTemporaryKeyPairName == "" {
    52  		ui.Say("Not using temporary keypair")
    53  		s.Comm.SSHKeyPairName = ""
    54  		return multistep.ActionContinue
    55  	}
    56  
    57  	ec2conn := state.Get("ec2").(*ec2.EC2)
    58  
    59  	ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.Comm.SSHTemporaryKeyPairName))
    60  	keyResp, err := ec2conn.CreateKeyPair(&ec2.CreateKeyPairInput{
    61  		KeyName: &s.Comm.SSHTemporaryKeyPairName})
    62  	if err != nil {
    63  		state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err))
    64  		return multistep.ActionHalt
    65  	}
    66  
    67  	s.doCleanup = true
    68  
    69  	// Set some data for use in future steps
    70  	s.Comm.SSHKeyPairName = s.Comm.SSHTemporaryKeyPairName
    71  	s.Comm.SSHPrivateKey = []byte(*keyResp.KeyMaterial)
    72  
    73  	// If we're in debug mode, output the private key to the working
    74  	// directory.
    75  	if s.Debug {
    76  		ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
    77  		f, err := os.Create(s.DebugKeyPath)
    78  		if err != nil {
    79  			state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
    80  			return multistep.ActionHalt
    81  		}
    82  		defer f.Close()
    83  
    84  		// Write the key out
    85  		if _, err := f.Write([]byte(*keyResp.KeyMaterial)); err != nil {
    86  			state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
    87  			return multistep.ActionHalt
    88  		}
    89  
    90  		// Chmod it so that it is SSH ready
    91  		if runtime.GOOS != "windows" {
    92  			if err := f.Chmod(0600); err != nil {
    93  				state.Put("error", fmt.Errorf("Error setting permissions of debug key: %s", err))
    94  				return multistep.ActionHalt
    95  			}
    96  		}
    97  	}
    98  
    99  	return multistep.ActionContinue
   100  }
   101  
   102  func (s *StepKeyPair) Cleanup(state multistep.StateBag) {
   103  	if !s.doCleanup {
   104  		return
   105  	}
   106  
   107  	ec2conn := state.Get("ec2").(*ec2.EC2)
   108  	ui := state.Get("ui").(packer.Ui)
   109  
   110  	// Remove the keypair
   111  	ui.Say("Deleting temporary keypair...")
   112  	_, err := ec2conn.DeleteKeyPair(&ec2.DeleteKeyPairInput{KeyName: &s.Comm.SSHTemporaryKeyPairName})
   113  	if err != nil {
   114  		ui.Error(fmt.Sprintf(
   115  			"Error cleaning up keypair. Please delete the key manually: %s", s.Comm.SSHTemporaryKeyPairName))
   116  	}
   117  
   118  	// Also remove the physical key if we're debugging.
   119  	if s.Debug {
   120  		if err := os.Remove(s.DebugKeyPath); err != nil {
   121  			ui.Error(fmt.Sprintf(
   122  				"Error removing debug key '%s': %s", s.DebugKeyPath, err))
   123  		}
   124  	}
   125  }