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